App-ArduinoBuilder

 view release on metacpan or  search on metacpan

lib/App/ArduinoBuilder.pm  view on Meta::CPAN

  # We are first adding all the includes path for all the library before building any of them.
  for my $l ($lib_config->keys()) {
    my $lib_dir = $lib_config->get($l);
    fatal "Library directory does not exist for library '${l}': ${lib_dir}" unless -d $lib_dir;
    my $lib_properties_file = catfile($lib_dir, 'library.properties');
    my $has_lib_properties = -f $lib_properties_file;
    my $recursive_lib = $has_lib_properties && -d catdir($lib_dir, 'src');
    # These config entry (and any other added to $lib_config) are undocummented and should never be
    # set by the user.
    $lib_config->set($l.'.is_flat' => !$recursive_lib);
    if ($recursive_lib) {
      $config->append('includes', '"-I'.catdir($lib_dir, 'src').'"');
    } else {
      $config->append('includes', "\"-I${lib_dir}\"");
    }
    if ($has_lib_properties) {
      my $lib_properties = App::ArduinoBuilder::Config->new(file => $lib_properties_file);
      $lib_config->set($l.'.name' => $lib_properties->get('name', default => $l));
    }
  }
  # TODO: we are ignoring the dot_a_linkage properties of the libraries (unclear what it brings)
  # and also the precompiled
  if ($run_step->('libraries')) {
    info 'Building libraries...';
    $builder->run_hook('libraries.prebuild');
    for my $l (@all_libs) {
      # Todo: we could add "lib-$l" pseudo-steps, but we need to take care of the --only
      # interaction with the 'libraries' step.
      info '  Building library %s...', $lib_config->get("${l}.name");
      my $base_dir = $lib_config->get($l);
      my $output_dir = catdir($config->get('build.path'), 'libs', $l);
      my $built_lib;
      if ($lib_config->get("${l}.is_flat")) {
        my $utility_dir = catdir($base_dir, 'utility');
        my @dirs = ($base_dir, (-d $utility_dir ? $utility_dir : ()));
        $built_lib = $builder->build_object_files(\@dirs, $output_dir, [], $force->('libraries'), 1);
      }  else {
        $built_lib = $builder->build_object_files(catdir($base_dir, 'src'), $output_dir, [], $force->('libraries'));
      }
      info ($built_lib ? '    Success' : '    Already up-to-date');
      $built_something |= $built_lib;
    }
    $builder->run_hook('libraries.postbuild');
  }

  $config->append('includes', '"-I'.$config->get('builder.source.path').'"');

  if ($run_step->('sketch')) {
    info 'Building sketch...';
    $builder->run_hook('sketch.prebuild');
    # TODO: add configuration option for the ignored directories and also a way to
    # build only the code inside the src/ directory
    my $built_sketch = $builder->build_object_files(
        $config->get('builder.source.path'), catdir($config->get('build.path'), 'sketch'),
        [], $force->('sketch'), !$config->get('builder.source.is_recursive'));
    info ($built_sketch ? '  Success' : '  Already up-to-date');
    $built_something |= $built_sketch;
    $builder->run_hook('sketch.postbuild');
  }
  # Bug: there is a similar bug to the one in build_archive: if a source file is
  # removed, we won’t remove it’s object file. I guess we could try to detect it.
  # Meanwhile it’s probably acceptable to ask for a cleanup from time to time.
  my @object_files = find_all_files_with_extensions(catdir($config->get('build.path'), 'sketch'), ['o']);
  for my $l (@all_libs) {
    push @object_files, find_all_files_with_extensions(catdir($config->get('build.path'), 'libs', $l), ['o']);
  }
  debug 'Object files: '.join(', ', @object_files);

  info 'Linking binary...';
  if (($built_something && $run_step->('link')) || $force->('link')) {
    $built_something = 1;
    $builder->run_hook('linking.prelink');
    $builder->link_executable(\@object_files, 'core.a');
    $builder->run_hook('linking.postlink');
    info '  Success';
  } else {
    info '  Already up-to-date';
  }

  info 'Extracting binary data';
  if (($built_something && $run_step->('objcopy')) || $force->('objcopy')) {
    $builder->run_hook('objcopy.preobjcopy');
    $builder->objcopy();
    $builder->run_hook('objcopy.postobjcopy');
    info '  Success';
  } else {
    info '  Already up-to-date';
  }

  info 'Computing binary sketch size';
  if (($built_something && $run_step->('size')) || $force->('size')) {
    $builder->compute_binary_size();
    # Not printing 'Success' here because the command already has an output.
  } else {
    info '  No new binary built';
  }

  info 'Success!';
}

sub discover {
  my ($config) = @_;

  if ($config->get('builder.forced_port.forced', default => 0)) {
    info 'Skipping board discovery';
    return;
  }

  info 'Running board discovery...';
  my @ports = App::ArduinoBuilder::Discovery::discover($config);
  # Discovery can be run more than once, as the port of a board can be changed
  # after upload. So we override any previous discovered ports.
  $config->set('builder.internal.ports' => \@ports, allow_override =>1);
  if (@ports) {
    debug 'Found port%s: %s', (@ports > 1 ? 's' : ''), join(', ', map { $_->get('upload.port.label') } @ports);
  } else {
    warning 'No port found.';
  }
}

sub select_port {



( run in 1.055 second using v1.01-cache-2.11-cpan-39bf76dae61 )