示例#1
0
    def execute(self, parser, args):
        directory = args.directory or args.name
        if path.maybedir(directory):
            directory = path.join(directory, args.name)

        if not path.exists(directory):
            logger.debug('creating directory "{}"'.format(directory))
            path.makedirs(directory)
        elif not path.isdir(directory):
            logger.error('"{}" is not a directory'.format(directory))
            return 1

        if args.nested:
            directory = path.join(directory, 'craftr')
            path.makedirs(directory)

        mfile = path.join(directory, 'manifest.' + args.format)
        sfile = path.join(directory, 'Craftrfile')
        for fn in [mfile, sfile]:
            if path.isfile(fn):
                logger.error('"{}" already exists'.format(fn))
                return 1

        logger.debug('creating file "{}"'.format(mfile))
        with open(mfile, 'w') as fp:
            if args.format == 'cson':
                lines = textwrap.dedent('''
          name: "%s"
          version: "%s"
          project_dir: ".."
          author: ""
          url: ""
          dependencies: {}
          options: {}
        ''' % (args.name, args.version)).lstrip().split('\n')
                if not args.nested:
                    del lines[2]
            elif args.format == 'json':
                lines = textwrap.dedent('''
          {
            "name": "%s",
            "version": "%s",
            "project_dir": "..",
            "author": "",
            "url": "",
            "dependencies": {},
            "options": {}
          }''' % (args.name, args.version)).lstrip().split('\n')
                if not args.nested:
                    del lines[3]
            fp.write('\n'.join(lines))

        logger.debug('creating file "{}"'.format(sfile))
        with open(sfile, 'w') as fp:
            print('# {}'.format(args.name), file=fp)
示例#2
0
def write_cache(cachefile):
    # Write back the cache.
    try:
        path.makedirs(path.dirname(cachefile))
        with open(cachefile, 'w') as fp:
            session.write_cache(fp)
    except OSError as exc:
        logger.error('error writing cache file:', cachefile)
        logger.error(exc, indent=1)
    else:
        logger.debug('cache written:', cachefile)
示例#3
0
def write_cache(cachefile):
  # Write back the cache.
  try:
    path.makedirs(path.dirname(cachefile))
    with open(cachefile, 'w') as fp:
      session.write_cache(fp)
  except OSError as exc:
    logger.error('error writing cache file:', cachefile)
    logger.error(exc, indent=1)
  else:
    logger.debug('cache written:', cachefile)
示例#4
0
    def execute(self, parser, args):
        directory = args.directory or args.name
        if path.maybedir(directory):
            directory = path.join(directory, args.name)

        if not path.exists(directory):
            logger.debug('creating directory "{}"'.format(directory))
            path.makedirs(directory)
        elif not path.isdir(directory):
            logger.error('"{}" is not a directory'.format(directory))
            return 1

        if args.nested:
            directory = path.join(directory, "craftr")
            path.makedirs(directory)

        mfile = path.join(directory, MANIFEST_FILENAME)
        sfile = path.join(directory, "Craftrfile")
        for fn in [mfile, sfile]:
            if path.isfile(fn):
                logger.error('"{}" already exists'.format(fn))
                return 1

        logger.debug('creating file "{}"'.format(mfile))
        with open(mfile, "w") as fp:
            lines = (
                textwrap.dedent(
                    """
        {
          "name": "%s",
          "version": "%s",
          "project_dir": "..",
          "author": "",
          "url": "",
          "dependencies": {},
          "options": {}
        }\n"""
                    % (args.name, args.version)
                )
                .lstrip()
                .split("\n")
            )
            if not args.nested:
                del lines[3]
            fp.write("\n".join(lines))

        logger.debug('creating file "{}"'.format(sfile))
        with open(sfile, "w") as fp:
            print("# {}".format(args.name), file=fp)
示例#5
0
def read_cache(show_errors_and_exit=True):
    cachefile = os.path.join(session.builddir, '.craftrcache')
    try:
        with open(cachefile) as fp:
            try:
                session.read_cache(fp)
            except ValueError as exc:
                logger.warn('Invalid cache: "{}"'.format(cachefile))
                logger.warn('Load error is: {}'.format(exc))
                return False
    except IOError as exc:
        if show_errors_and_exit:
            logger.error('Unable to find file: "{}"'.format(cachefile))
            logger.error('Does not seem to be a build directory: "{}"'.format(
                session.builddir))
            logger.error(
                "Export build information using the 'craftr export' command.")
            sys.exit(1)
        return False
    return True
示例#6
0
    def _find_module(self, parser, args):
        """
    Find the main Craftr module that is to be executed. Returns None in
    modes that do not require a main module.
    """

        if self.mode not in ('export', 'run', 'help', 'dump-options',
                             'dump-deptree'):
            return None

        # Determine the module to execute, either from the current working
        # directory or find it by name if one is specified.
        if not args.module:
            for fn in MANIFEST_FILENAMES + [
                    path.join('craftr', x) for x in MANIFEST_FILENAMES
            ]:
                if path.isfile(fn):
                    module = session.parse_manifest(fn)
                    break
            else:
                logger.error('"{}" does not exist'.format(
                    MANIFEST_FILENAMES[0]))
                sys.exit(1)
        else:
            # TODO: For some reason, prints to stdout are not visible here.
            # TODO: Prints to stderr however work fine.
            try:
                module_name, version = parse_module_spec(args.module)
            except ValueError as exc:
                logger.error(
                    '{} (note: you have to escape > and < characters)'.format(
                        exc))
                sys.exit(1)
            try:
                module = session.find_module(module_name, version)
            except Module.NotFound as exc:
                logger.error('module not found: ' + str(exc))
                sys.exit(1)

        return module
示例#7
0
    def _build_or_clean(self, args):
        """
    Will be called for the 'build' and 'clean' modes. Loads the Craftr
    cache and invokes Ninja.
    """

        # Read the cache and parse command-line options.
        if not read_cache(True):
            sys.exit(1)

        parse_cmdline_options(session.cache['build']['options'])
        main = session.cache['build']['main']
        available_targets = frozenset(session.cache['build']['targets'])
        available_modules = unserialise_loaded_module_info(
            session.cache['build']['modules'])

        logger.debug('build main module:', main)
        session.expand_relative_options(get_volatile_module_version(main)[0])

        # Check if any of the modules changed, so we can let the user know he
        # might have to re-export the build files.
        changed_modules = []
        for name, versions in available_modules.items():
            for version, info in versions.items():
                if info['changed']:
                    changed_modules.append('{}-{}'.format(name, version))
        if changed_modules:
            if len(changed_modules) == 1:
                logger.info(
                    'note: module "{}" has changed, maybe you should re-export'
                    .format(changed_modules[0]))
            else:
                logger.info(
                    'note: some modules have changed, maybe you should re-export'
                )
                for name in changed_modules:
                    logger.info('  -', name)

        # Check the targets and if they exist.
        targets = []
        for target_name in args.targets:
            if '.' not in target_name:
                target_name = main + '.' + target_name
            elif target_name.startswith('.'):
                target_name = main + target_name

            module_name, target_name = target_name.rpartition('.')[::2]
            module_name, version = get_volatile_module_version(module_name)

            if module_name not in available_modules:
                error('no such module:', module_name)
            if not version:
                version = max(available_modules[module_name].keys())

            target_name = craftr.targetbuilder.get_full_name(
                target_name, module_name=module_name, version=version)
            if target_name not in available_targets:
                logger.error('no such target: {}'.format(target_name))
                return 1
            targets.append(target_name)

        # Make sure we get all the output before running the subcommand.
        logger.flush()

        # Execute the ninja build.
        cmd = [self.ninja_bin]
        if args.verbose:
            cmd += ['-v']
        if self.mode == 'clean':
            cmd += ['-t', 'clean']
            if not args.recursive:
                cmd += ['-r']
        cmd += targets
        return shell.run(cmd).returncode
示例#8
0
    def _export_run_or_help(self, args, module):
        """
    Called when the mode is 'export' or 'run'. Will execute the specified
    *module* and eventually export a Ninja manifest and Cache.
    """

        read_cache(False)

        session.expand_relative_options()
        session.cache['build'] = {}

        # Load the dependency lock information if it exists.
        deplock_fn = path.join(path.dirname(module.manifest.filename),
                               '.dependency-lock')
        if os.path.isfile(deplock_fn):
            with open(deplock_fn) as fp:
                session.preferred_versions = cson.load(fp)
                logger.debug('note: dependency lock file "{}" loaded'.format(
                    deplock_fn))

        try:
            module.run()
        except Module.InvalidOption as exc:
            for error in exc.format_errors():
                logger.error(error)
            return 1
        except craftr.defaults.ModuleError as exc:
            logger.error('error:', exc)
            return 1
        finally:
            if sys.exc_info() and self.mode == 'export':
                # We still want to write the cache, especially so that data already
                # loaded with loaders doesn't need to be re-loaded. They'll find out
                # when the cached information was not valid.
                write_cache(self.cachefile)

        # Fill the cache.
        session.cache['build']['targets'] = list(session.graph.targets.keys())
        session.cache['build']['modules'] = serialise_loaded_module_info()
        session.cache['build']['main'] = module.ident
        session.cache['build']['options'] = args.options
        session.cache['build']['dependency_lock_filename'] = deplock_fn

        if self.mode == 'export':
            # Add the Craftr_run_command variable which is necessary for tasks
            # to properly executed.
            run_command = ['craftr', '-q', '-P', path.rel(session.maindir)]
            if args.no_config: run_command += ['-C']
            run_command += ['-c' + x for x in args.config]
            run_command += ['run']
            if args.module: run_command += ['-m', args.module]
            run_command += ['-i' + x for x in args.include_path]
            run_command += ['-b', path.rel(session.builddir)]
            session.graph.vars['Craftr_run_command'] = shell.join(run_command)

            write_cache(self.cachefile)

            # Write the Ninja manifest.
            with open("build.ninja", 'w') as fp:
                platform = core.build.get_platform_helper()
                context = core.build.ExportContext(self.ninja_version)
                writer = core.build.NinjaWriter(fp)
                session.graph.export(writer, context, platform)
                logger.info('exported "build.ninja"')

            return 0

        elif self.mode == 'run':
            if args.task:
                if args.task not in session.graph.tasks:
                    logger.error('no such task exists: "{}"'.format(args.task))
                    return 1
                task = session.graph.tasks[args.task]
                return task.invoke(args.task_args)
            return 0

        elif self.mode == 'help':
            if args.name not in vars(module.namespace):
                logger.error('symbol not found: "{}:{}"'.format(
                    module.manifest.name, args.name))
                return 1
            help(getattr(module.namespace, args.name))
            return 0

        assert False, "unhandled mode: {}".format(self.mode)
示例#9
0
  def execute(self, parser, args):
    session.path.extend(map(path.norm, args.include_path))

    if self.is_export:
      # Determine the module to execute, either from the current working
      # directory or find it by name if one is specified.
      if not args.module:
        for fn in [MANIFEST_FILENAME, path.join('craftr', MANIFEST_FILENAME)]:
          if path.isfile(fn):
            module = session.parse_manifest(fn)
            break
        else:
          parser.error('"{}" does not exist'.format(MANIFEST_FILENAME))
      else:
        # TODO: For some reason, prints to stdout are not visible here.
        # TODO: Prints to stderr however work fine.
        try:
          module_name, version = parse_module_spec(args.module)
        except ValueError as exc:
          parser.error('{} (note: you have to escape > and < characters)'.format(exc))
        try:
          module = session.find_module(module_name, version)
        except Module.NotFound as exc:
          parser.error('module not found: ' + str(exc))
    else:
      module = None

    ninja_bin, ninja_version = get_ninja_info()

    # Create and switch to the build directory.
    session.builddir = path.abs(args.build_dir)
    path.makedirs(session.builddir)
    os.chdir(session.builddir)

    # Read the cache and parse command-line options.
    cachefile = path.join(session.builddir, '.craftrcache')
    if not read_cache(cachefile) and not self.is_export:
      logger.error('Unable to load "{}", can not build'.format(cachefile))
      return 1

    # Prepare options, loaders and execute.
    if self.is_export:
      session.cache['build'] = {}
      try:
        write_cache(cachefile)
        module.run()
      except (Module.InvalidOption, Module.LoaderInitializationError) as exc:
        for error in exc.format_errors():
          logger.error(error)
        return 1
      except craftr.defaults.ModuleError as exc:
        logger.error(exc)
        return 1

      # Write the cache back.
      session.cache['build']['targets'] = list(session.graph.targets.keys())
      session.cache['build']['main'] = module.ident
      session.cache['build']['options'] = args.options
      write_cache(cachefile)

      # Write the Ninja manifest.
      with open("build.ninja", 'w') as fp:
        platform = core.build.get_platform_helper()
        context = core.build.ExportContext(ninja_version)
        writer = core.build.NinjaWriter(fp)
        session.graph.export(writer, context, platform)

    else:
      parse_cmdline_options(session.cache['build']['options'])
      main = session.cache['build']['main']
      available_targets = frozenset(session.cache['build']['targets'])

      # Check the targets and if they exist.
      targets = []
      for target in args.targets:
        if '.' not in target:
          target = main + '.' + target
        elif target.startswith('.'):
          target = main + target

        module_name, target = target.rpartition('.')[::2]
        module_name, version = get_volatile_module_version(module_name)
        ref_module = session.find_module(module_name, version or '*')
        target = craftr.targetbuilder.get_full_name(target, ref_module)
        if target not in available_targets:
          parser.error('no such target: {}'.format(target))
        targets.append(target)

      # Execute the ninja build.
      cmd = [ninja_bin]
      if args.verbose:
        cmd += ['-v']
      cmd += targets
      shell.run(cmd)
示例#10
0
    def execute(self, parser, args):
        session.path.extend(map(path.norm, args.include_path))

        if self.mode == "export":
            # Determine the module to execute, either from the current working
            # directory or find it by name if one is specified.
            if not args.module:
                for fn in [MANIFEST_FILENAME, path.join("craftr", MANIFEST_FILENAME)]:
                    if path.isfile(fn):
                        module = session.parse_manifest(fn)
                        break
                else:
                    parser.error('"{}" does not exist'.format(MANIFEST_FILENAME))
            else:
                # TODO: For some reason, prints to stdout are not visible here.
                # TODO: Prints to stderr however work fine.
                try:
                    module_name, version = parse_module_spec(args.module)
                except ValueError as exc:
                    parser.error("{} (note: you have to escape > and < characters)".format(exc))
                try:
                    module = session.find_module(module_name, version)
                except Module.NotFound as exc:
                    parser.error("module not found: " + str(exc))
        else:
            module = None

        ninja_bin, ninja_version = get_ninja_info()

        # Create and switch to the build directory.
        session.builddir = path.abs(args.build_dir)
        path.makedirs(session.builddir)
        os.chdir(session.builddir)

        # Read the cache and parse command-line options.
        cachefile = path.join(session.builddir, ".craftrcache")
        if not read_cache(cachefile) and self.mode != "export":
            logger.error('Unable to load "{}", can not {}'.format(cachefile, self.mode))
            logger.error("Make sure to generate a build tree with 'craftr export'")
            return 1

        # Prepare options, loaders and execute.
        if self.mode == "export":
            session.expand_relative_options(module.manifest.name)
            session.cache["build"] = {}
            try:
                module.run()
            except Module.InvalidOption as exc:
                for error in exc.format_errors():
                    logger.error(error)
                return 1
            except craftr.defaults.ModuleError as exc:
                logger.error("error:", exc)
                return 1
            finally:
                if sys.exc_info():
                    # We still want to write the cache, especially so that data already
                    # loaded with loaders doesn't need to be re-loaded. They'll find out
                    # when the cached information was not valid.
                    write_cache(cachefile)

            # Write the cache back.
            session.cache["build"]["targets"] = list(session.graph.targets.keys())
            session.cache["build"]["main"] = module.ident
            session.cache["build"]["options"] = args.options
            write_cache(cachefile)

            # Write the Ninja manifest.
            with open("build.ninja", "w") as fp:
                platform = core.build.get_platform_helper()
                context = core.build.ExportContext(ninja_version)
                writer = core.build.NinjaWriter(fp)
                session.graph.export(writer, context, platform)

        else:
            parse_cmdline_options(session.cache["build"]["options"])
            main = session.cache["build"]["main"]
            available_targets = frozenset(session.cache["build"]["targets"])

            logger.debug("build main module:", main)
            session.expand_relative_options(get_volatile_module_version(main)[0])

            # Check the targets and if they exist.
            targets = []
            for target in args.targets:
                if "." not in target:
                    target = main + "." + target
                elif target.startswith("."):
                    target = main + target

                module_name, target = target.rpartition(".")[::2]
                module_name, version = get_volatile_module_version(module_name)
                ref_module = session.find_module(module_name, version or "*")
                target = craftr.targetbuilder.get_full_name(target, ref_module)
                if target not in available_targets:
                    parser.error("no such target: {}".format(target))
                targets.append(target)

            # Execute the ninja build.
            cmd = [ninja_bin]
            if args.verbose:
                cmd += ["-v"]
            if self.mode == "clean":
                cmd += ["-t", "clean"]
                if not args.recursive:
                    cmd += ["-r"]
            cmd += targets
            return shell.run(cmd).returncode