Example #1
0
 def export(self, writer, context, platform):
     name = str(self)[1:]
     if not self.preamble and not self.environ:
         self.exported_command = shell.join(self.command)
     else:
         filename = path.join('.tools', name)
         command, filename = platform.write_command_file(
             filename,
             list(self.preamble) + [self.command],
             environ=self.environ,
             accept_additional_args=True)
         self.exported_command = shell.join(command)
     writer.variable(name, self.exported_command)
Example #2
0
  def write_command_file(self, filename, commands, inputs=None, outputs=None,
      cwd=None, environ=None, foreach=False, suffix='.cmd', dry=False,
      accept_additional_args=False):

    if suffix is not None:
      filename = path.addsuffix(filename, suffix)
    result = ['cmd', '/Q', '/c', filename]
    if foreach:
      result += ['$in', '$out']
      inputs, outputs = ['%1'], ['%2']

    commands = self.replace_commands_inout_vars(commands, inputs, outputs)
    if dry:
      return result, filename

    path.makedirs(path.dirname(path.abs(filename)))
    with open(filename, 'w') as fp:
      fp.write('REM This file is automatically generated with Craftr. It is \n')
      fp.write('REM not recommended to modify it manually.\n\n')
      if cwd is not None:
        fp.write('cd ' + shell.quote(cwd) + '\n\n')
      for key, value in environ.items():
        fp.write('set ' + shell.quote('{}={}'.format(key, value), for_ninja=True) + '\n')
      fp.write('\n')
      for index, command in enumerate(commands):
        if accept_additional_args and index == len(commands)-1:
          command.append(shell.safe('%*'))
        fp.write(shell.join(command) + '\n')
        fp.write('if %errorlevel% neq 0 exit %errorlevel%\n\n')

    return result, filename
Example #3
0
    def export(self, writer, context, platform):
        """
    Export the target to a Ninja manifest.
    """

        writer.comment("target: {}".format(self.name))
        writer.comment("--------" + "-" * len(self.name))
        commands = platform.prepare_commands(
            [list(map(str, c)) for c in self.commands])

        # Check if we need to export a command file or can export the command
        # directly.
        if not self.environ and len(commands) == 1:
            commands = [platform.prepare_single_command(commands[0], self.cwd)]
        else:
            filename = path.join('.commands', self.name)
            command, __ = platform.write_command_file(filename,
                                                      commands,
                                                      self.inputs,
                                                      self.outputs,
                                                      cwd=self.cwd,
                                                      environ=self.environ,
                                                      foreach=self.foreach)
            commands = [command]

        assert len(commands) == 1
        command = shell.join(commands[0], for_ninja=True)

        writer.rule(self.name,
                    command,
                    pool=self.pool,
                    deps=self.deps,
                    depfile=self.depfile,
                    description=self.description)

        if self.msvc_deps_prefix:
            # We can not write msvc_deps_prefix on the rule level with Ninja
            # versions older than 1.7.1. Write it global instead, but that *could*
            # lead to issues...
            indent = 1 if context.ninja_version > '1.7.1' else 0
            writer.variable('msvc_deps_prefix', self.msvc_deps_prefix, indent)

        writer.newline()
        if self.foreach:
            assert len(self.inputs) == len(self.outputs)
            for infile, outfile in zip(self.inputs, self.outputs):
                writer.build([outfile],
                             self.name, [infile],
                             implicit=self.implicit_deps,
                             order_only=self.order_only_deps)
        else:
            writer.build(self.outputs or [self.name],
                         self.name,
                         self.inputs,
                         implicit=self.implicit_deps,
                         order_only=self.order_only_deps)

        if self.outputs and self.name not in self.outputs and not self.explicit:
            writer.build(self.name, 'phony', self.outputs)
Example #4
0
 def export(self, writer, context, platform):
   name = str(self)[1:]
   if not self.preamble and not self.environ:
     self.exported_command = shlex.join(self.command)
   else:
     filename = path.join('.tools', name)
     command, filename = platform.write_command_file(
         filename, list(self.preamble) + [self.command], environ=self.environ,
         accept_additional_args=True)
     self.exported_command = shell.join(command)
   writer.variable(name, self.exported_command)
Example #5
0
  def export(self, writer, context, platform):
    """
    Export the target to a Ninja manifest.
    """

    writer.comment("target: {}".format(self.name))
    writer.comment("--------" + "-" * len(self.name))
    commands = platform.prepare_commands([list(map(str, c)) for c in self.commands])

    # Check if we need to export a command file or can export the command
    # directly.
    if not self.environ and len(commands) == 1:
      commands = [platform.prepare_single_command(commands[0], self.cwd)]
    else:
      filename = path.join('.commands', self.name)
      command, __ = platform.write_command_file(filename, commands,
        self.inputs, self.outputs, cwd=self.cwd, environ=self.environ,
        foreach=self.foreach)
      commands = [command]

    assert len(commands) == 1
    command = shell.join(commands[0], for_ninja=True)

    writer.rule(self.name, command, pool=self.pool, deps=self.deps,
      depfile=self.depfile, description=self.description)

    if self.msvc_deps_prefix:
      # We can not write msvc_deps_prefix on the rule level with Ninja
      # versions older than 1.7.1. Write it global instead, but that *could*
      # lead to issues...
      indent = 1 if context.ninja_version > '1.7.1' else 0
      writer.variable('msvc_deps_prefix', self.msvc_deps_prefix, indent)

    writer.newline()
    if self.foreach:
      assert len(self.inputs) == len(self.outputs)
      for infile, outfile in zip(self.inputs, self.outputs):
        writer.build(
          [outfile],
          self.name,
          [infile],
          implicit=self.implicit_deps,
          order_only=self.order_only_deps)
    else:
      writer.build(
        self.outputs or [self.name],
        self.name,
        self.inputs,
        implicit=self.implicit_deps,
        order_only=self.order_only_deps)

    if self.outputs and self.name not in self.outputs and not self.explicit:
      writer.build(self.name, 'phony', self.outputs)
Example #6
0
    def write_command_file(self,
                           filename,
                           commands,
                           inputs=None,
                           outputs=None,
                           cwd=None,
                           environ=None,
                           foreach=False,
                           suffix='.sh',
                           dry=False,
                           accept_additional_args=False):

        if suffix is not None:
            filename = path.addsuffix(filename, suffix)
        result = [filename]
        if foreach:
            result += ['$in', '$out']
            inputs, outputs = ['%1'], ['%2']

        commands = self.replace_commands_inout_vars(commands, inputs, outputs)
        if dry:
            return result, filename

        path.makedirs(path.dirname(filename))
        with open(filename, 'w') as fp:
            # TODO: Make sure this also works for shells other than bash.
            fp.write('#!' + shell.find_program(environ.get('SHELL', 'bash')) +
                     '\n')
            fp.write('set -e\n')
            if cwd:
                fp.write('cd ' + shell.quote(cwd) + '\n')
            fp.write('\n')
            for key, value in environ.items():
                fp.write('export {}={}\n'.format(key, shell.quote(value)))
            fp.write('\n')
            for index, command in enumerate(commands):
                if accept_additional_args and index == len(commands) - 1:
                    command.append(shell.safe('$*'))
                fp.write(shell.join(command))
                fp.write('\n')

        os.chmod(filename, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR
                 | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH)  # rwxrw-r--

        return result, filename
Example #7
0
    def write_command_file(self,
                           filename,
                           commands,
                           inputs=None,
                           outputs=None,
                           cwd=None,
                           environ=None,
                           foreach=False,
                           suffix='.cmd',
                           dry=False,
                           accept_additional_args=False):

        if suffix is not None:
            filename = path.addsuffix(filename, suffix)
        result = ['cmd', '/Q', '/c', filename]
        if foreach:
            result += ['$in', '$out']
            inputs, outputs = ['%1'], ['%2']

        commands = self.replace_commands_inout_vars(commands, inputs, outputs)
        if dry:
            return result, filename

        path.makedirs(path.dirname(path.abs(filename)))
        with open(filename, 'w') as fp:
            fp.write(
                'REM This file is automatically generated with Craftr. It is \n'
            )
            fp.write('REM not recommended to modify it manually.\n\n')
            if cwd is not None:
                fp.write('cd ' + shell.quote(cwd) + '\n\n')
            for key, value in environ.items():
                fp.write(
                    'set ' +
                    shell.quote('{}={}'.format(key, value), for_ninja=True) +
                    '\n')
            fp.write('\n')
            for index, command in enumerate(commands):
                if accept_additional_args and index == len(commands) - 1:
                    command.append(shell.safe('%*'))
                fp.write(shell.join(command) + '\n')
                fp.write('if %errorlevel% neq 0 exit %errorlevel%\n\n')

        return result, filename
Example #8
0
def write_response_file(arguments, builder=None, name=None, force_file=False, suffix=''):
  """
  Creates a response-file with the specified *name* in the in the
  ``buildfiles/`` directory and writes the *arguments* list quoted into
  the file. If *builder* is specified, it must be a :class:`TargetBuilder`
  and the response file will be added to the implicit dependencies.

  If *force_file* is set to True, a file will always be written. Otherwise,
  the function will into possible limitations of the platform and decide
  whether to write a response file or to return the *arguments* as is.

  Returns a tuple of ``(filename, arguments)``. If a response file is written,
  the returned *arguments* will be a list with a single string that is the
  filename prepended with ``@``. The *filename* part can be None if no
  response file needed to be exported.
  """

  if not name:
    if not builder:
      raise ValueError('builder must be specified if name is bot')
    name = builder.name + suffix + '.response.txt'

  if platform.name != 'win':
    return None, arguments

  # We'll just assume that there won't be more than 2048 characters for
  # other flags. The windows max buffer size is 8192.
  content = shell.join(arguments)
  if len(content) < 6144:
    return None, arguments

  filename = buildlocal(path.join('buildfiles', name))
  if builder:
    builder.implicit_deps.append(filename)

  if session.builddir:
    path.makedirs(path.dirname(filename))
    with open(filename, 'w') as fp:
      fp.write(content)
  return filename, ['@' + filename]
Example #9
0
def write_response_file(arguments, builder=None, name=None, force_file=False):
  """
  Creates a response-file with the specified *name* in the in the
  ``buildfiles/`` directory and writes the *arguments* list quoted into
  the file. If *builder* is specified, it must be a :class:`TargetBuilder`
  and the response file will be added to the implicit dependencies.

  If *force_file* is set to True, a file will always be written. Otherwise,
  the function will into possible limitations of the platform and decide
  whether to write a response file or to return the *arguments* as is.

  Returns a tuple of ``(filename, arguments)``. If a response file is written,
  the returned *arguments* will be a list with a single string that is the
  filename prepended with ``@``. The *filename* part can be None if no
  response file needed to be exported.
  """

  if not name:
    if not builder:
      raise ValueError('builder must be specified if name is bot')
    name = builder.name + '.response.txt'

  if platform.name != 'win':
    return None, arguments

  # We'll just assume that there won't be more than 2048 characters for
  # other flags. The windows max buffer size is 8192.
  content = shell.join(arguments)
  if len(content) < 6144:
    return None, arguments

  filename = buildlocal(path.join('buildfiles', name))
  if builder:
    builder.implicit_deps.append(filename)

  if session.builddir:
    path.makedirs(path.dirname(filename))
    with open(filename, 'w') as fp:
      fp.write(content)
  return filename, ['@' + filename]
Example #10
0
  def write_command_file(self, filename, commands, inputs=None, outputs=None,
      cwd=None, environ=None, foreach=False, suffix='.sh', dry=False,
      accept_additional_args=False):

    if suffix is not None:
      filename = path.addsuffix(filename, suffix)
    result = [filename]
    if foreach:
      result += ['$in', '$out']
      inputs, outputs = ['%1'], ['%2']

    commands = self.replace_commands_inout_vars(commands, inputs, outputs)
    if dry:
      return result, filename

    path.makedirs(path.dirname(filename))
    with open(filename, 'w') as fp:
      # TODO: Make sure this also works for shells other than bash.
      fp.write('#!' + shell.find_program(environ.get('SHELL', 'bash')) + '\n')
      fp.write('set -e\n')
      if cwd:
        fp.write('cd ' + shell.quote(cwd) + '\n')
      fp.write('\n')
      for key, value in environ.items():
        fp.write('export {}={}\n'.format(key, shell.quote(value)))
      fp.write('\n')
      for index, command in enumerate(commands):
        if accept_additional_args and index == len(commands)-1:
          command.append(shell.safe('$*'))
        fp.write(shell.join(command))
        fp.write('\n')

    os.chmod(filename, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR |
      stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH)  # rwxrw-r--

    return result, filename
Example #11
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)