コード例 #1
0
  def __init__(self, target_outputs, base_dir, build_dir, output_file):
    """
    base_dir: path from source root to directory containing this gyp file,
              by gyp semantics, all input paths are relative to this
    build_dir: path from source root to build output
    """

    self.target_outputs = target_outputs
    self.base_dir = base_dir
    self.build_dir = build_dir
    self.ninja = ninja_syntax.Writer(output_file)

    # Relative path from build output dir to base dir.
    self.build_to_base = os.path.join(InvertRelativePath(build_dir), base_dir)
    # Relative path from base dir to build dir.
    self.base_to_build = os.path.join(InvertRelativePath(base_dir), build_dir)
コード例 #2
0
    def __init__(self,
                 hash_for_rules,
                 target_outputs,
                 base_dir,
                 build_dir,
                 output_file,
                 toplevel_build,
                 output_file_name,
                 flavor,
                 toplevel_dir=None):
        """
    base_dir: path from source root to directory containing this gyp file,
              by gyp semantics, all input paths are relative to this
    build_dir: path from source root to build output
    toplevel_dir: path to the toplevel directory
    """

        self.hash_for_rules = hash_for_rules
        self.target_outputs = target_outputs
        self.base_dir = base_dir
        self.build_dir = build_dir
        self.ninja = ninja_syntax.Writer(output_file)
        self.toplevel_build = toplevel_build
        self.output_file_name = output_file_name

        self.flavor = flavor
        self.abs_build_dir = None
        if toplevel_dir is not None:
            self.abs_build_dir = os.path.abspath(
                os.path.join(toplevel_dir, build_dir))
        self.obj_ext = '.obj' if flavor == 'win' else '.o'
        if flavor == 'win':
            # See docstring of msvs_emulation.GenerateEnvironmentFiles().
            self.win_env = {}
            for arch in ('x86', 'x64'):
                self.win_env[arch] = 'environment.' + arch

        # Relative path from build output dir to base dir.
        build_to_top = gyp.common.InvertRelativePath(build_dir, toplevel_dir)
        self.build_to_base = os.path.join(build_to_top, base_dir)
        # Relative path from base dir to build dir.
        base_to_top = gyp.common.InvertRelativePath(base_dir, toplevel_dir)
        self.base_to_build = os.path.join(base_to_top, build_dir)
コード例 #3
0
ファイル: ninja.py プロジェクト: philips/luvit
  def __init__(self, target_outputs, base_dir, build_dir, output_file, flavor,
               abs_build_dir=None):
    """
    base_dir: path from source root to directory containing this gyp file,
              by gyp semantics, all input paths are relative to this
    build_dir: path from source root to build output
    abs_build_dir: absolute path to the build directory
    """

    self.target_outputs = target_outputs
    self.base_dir = base_dir
    self.build_dir = build_dir
    self.ninja = ninja_syntax.Writer(output_file)
    self.flavor = flavor
    self.abs_build_dir = abs_build_dir
    self.obj_ext = '.obj' if flavor == 'win' else '.o'

    # Relative path from build output dir to base dir.
    self.build_to_base = os.path.join(InvertRelativePath(build_dir), base_dir)
    # Relative path from base dir to build dir.
    self.base_to_build = os.path.join(InvertRelativePath(base_dir), build_dir)
コード例 #4
0
    def WriteSpec(self, spec, config_name, generator_flags):
        """The main entry point for NinjaWriter: write the build rules for a spec.

    Returns a Target object, which represents the output paths for this spec.
    Returns None if there are no outputs (e.g. a settings-only 'none' type
    target)."""

        self.config_name = config_name
        self.name = spec['target_name']
        self.toolset = spec['toolset']
        config = spec['configurations'][config_name]
        self.target = Target(spec['type'])
        self.is_standalone_static_library = bool(
            spec.get('standalone_static_library', 0))
        # Track if this target contains any C++ files, to decide if gcc or g++
        # should be used for linking.
        self.uses_cpp = False

        self.is_mac_bundle = gyp.xcode_emulation.IsMacBundle(self.flavor, spec)
        self.xcode_settings = self.msvs_settings = None
        if self.flavor == 'mac':
            self.xcode_settings = gyp.xcode_emulation.XcodeSettings(spec)
        if self.flavor == 'win':
            self.msvs_settings = gyp.msvs_emulation.MsvsSettings(
                spec, generator_flags)
            arch = self.msvs_settings.GetArch(config_name)
            self.ninja.variable('arch', self.win_env[arch])
            self.ninja.variable('cc', '$cl_' + arch)
            self.ninja.variable('cxx', '$cl_' + arch)
            self.ninja.variable('cc_host', '$cl_' + arch)
            self.ninja.variable('cxx_host', '$cl_' + arch)
            self.ninja.variable('asm', '$ml_' + arch)

        if self.flavor == 'mac':
            self.archs = self.xcode_settings.GetActiveArchs(config_name)
            if len(self.archs) > 1:
                self.arch_subninjas = dict(
                    (arch,
                     ninja_syntax.Writer(
                         OpenOutput(
                             os.path.join(self.toplevel_build,
                                          self._SubninjaNameForArch(arch)),
                             'w'))) for arch in self.archs)

        # Compute predepends for all rules.
        # actions_depends is the dependencies this target depends on before running
        # any of its action/rule/copy steps.
        # compile_depends is the dependencies this target depends on before running
        # any of its compile steps.
        actions_depends = []
        compile_depends = []
        # TODO(evan): it is rather confusing which things are lists and which
        # are strings.  Fix these.
        if 'dependencies' in spec:
            for dep in spec['dependencies']:
                if dep in self.target_outputs:
                    target = self.target_outputs[dep]
                    actions_depends.append(target.PreActionInput(self.flavor))
                    compile_depends.append(target.PreCompileInput())
            actions_depends = filter(None, actions_depends)
            compile_depends = filter(None, compile_depends)
            actions_depends = self.WriteCollapsedDependencies(
                'actions_depends', actions_depends)
            compile_depends = self.WriteCollapsedDependencies(
                'compile_depends', compile_depends)
            self.target.preaction_stamp = actions_depends
            self.target.precompile_stamp = compile_depends

        # Write out actions, rules, and copies.  These must happen before we
        # compile any sources, so compute a list of predependencies for sources
        # while we do it.
        extra_sources = []
        mac_bundle_depends = []
        self.target.actions_stamp = self.WriteActionsRulesCopies(
            spec, extra_sources, actions_depends, mac_bundle_depends)

        # If we have actions/rules/copies, we depend directly on those, but
        # otherwise we depend on dependent target's actions/rules/copies etc.
        # We never need to explicitly depend on previous target's link steps,
        # because no compile ever depends on them.
        compile_depends_stamp = (self.target.actions_stamp or compile_depends)

        # Write out the compilation steps, if any.
        link_deps = []
        sources = extra_sources + spec.get('sources', [])
        if sources:
            if self.flavor == 'mac' and len(self.archs) > 1:
                # Write subninja file containing compile and link commands scoped to
                # a single arch if a fat binary is being built.
                for arch in self.archs:
                    self.ninja.subninja(self._SubninjaNameForArch(arch))

            pch = None
            if self.flavor == 'win':
                gyp.msvs_emulation.VerifyMissingSources(
                    sources, self.abs_build_dir, generator_flags,
                    self.GypPathToNinja)
                pch = gyp.msvs_emulation.PrecompiledHeader(
                    self.msvs_settings, config_name, self.GypPathToNinja,
                    self.GypPathToUniqueOutput, self.obj_ext)
            else:
                pch = gyp.xcode_emulation.MacPrefixHeader(
                    self.xcode_settings, self.GypPathToNinja, lambda path,
                    lang: self.GypPathToUniqueOutput(path + '-' + lang))
            link_deps = self.WriteSources(self.ninja, config_name, config,
                                          sources, compile_depends_stamp, pch,
                                          spec)
            # Some actions/rules output 'sources' that are already object files.
            obj_outputs = [f for f in sources if f.endswith(self.obj_ext)]
            if obj_outputs:
                if self.flavor != 'mac' or len(self.archs) == 1:
                    link_deps += [self.GypPathToNinja(o) for o in obj_outputs]
                else:
                    print "Warning: Actions/rules writing object files don't work with " \
                          "multiarch targets, dropping. (target %s)" % spec['target_name']
        elif self.flavor == 'mac' and len(self.archs) > 1:
            link_deps = collections.defaultdict(list)

        compile_deps = self.target.actions_stamp or actions_depends
        if self.flavor == 'win' and self.target.type == 'static_library':
            self.target.component_objs = link_deps
            self.target.compile_deps = compile_deps

        # Write out a link step, if needed.
        output = None
        is_empty_bundle = not link_deps and not mac_bundle_depends
        if link_deps or self.target.actions_stamp or actions_depends:
            output = self.WriteTarget(spec, config_name, config, link_deps,
                                      compile_deps)
            if self.is_mac_bundle:
                mac_bundle_depends.append(output)

        # Bundle all of the above together, if needed.
        if self.is_mac_bundle:
            output = self.WriteMacBundle(spec, mac_bundle_depends,
                                         is_empty_bundle)

        if not output:
            return None

        assert self.target.FinalOutput(), output
        return self.target
コード例 #5
0
def GenerateOutput(target_list, target_dicts, data, params):
  options = params['options']
  generator_flags = params.get('generator_flags', {})

  if options.generator_output:
    raise NotImplementedError, "--generator_output not implemented for ninja"

  config_name = generator_flags.get('config', None)
  if config_name is None:
    # Guess which config we want to use: pick the first one from the
    # first target.
    config_name = target_dicts[target_list[0]]['default_configuration']

  # builddir: relative path from source root to our output files.
  # e.g. "out/Debug"
  builddir = os.path.join(generator_flags.get('output_dir', 'out'), config_name)

  master_ninja = ninja_syntax.Writer(
      OpenOutput(os.path.join(options.toplevel_dir, builddir, 'build.ninja')),
      width=120)

  # TODO: compute cc/cxx/ld/etc. by command-line arguments and system tests.
  master_ninja.variable('cc', os.environ.get('CC', 'gcc'))
  master_ninja.variable('cxx', os.environ.get('CXX', 'g++'))
  master_ninja.variable('ld', '$cxx -Wl,--threads -Wl,--thread-count=4')
  master_ninja.variable('cc_host', '$cc')
  master_ninja.variable('cxx_host', '$cxx')
  master_ninja.newline()

  master_ninja.rule(
    'cc',
    description='CC $out',
    command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_c '
             '-c $in -o $out'),
    depfile='$out.d')
  master_ninja.rule(
    'cxx',
    description='CXX $out',
    command=('$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_cc '
             '-c $in -o $out'),
    depfile='$out.d')
  master_ninja.rule(
    'alink',
    description='AR $out',
    command='rm -f $out && ar rcsT $out $in')
  master_ninja.rule(
    'solink',
    description='SOLINK $out',
    command=('$ld -shared $ldflags -o $out -Wl,-soname=$soname '
             '-Wl,--whole-archive $in -Wl,--no-whole-archive $libs'))
  master_ninja.rule(
    'link',
    description='LINK $out',
    command=('$ld $ldflags -o $out -Wl,-rpath=\$$ORIGIN/lib '
             '-Wl,--start-group $in -Wl,--end-group $libs'))
  master_ninja.rule(
    'stamp',
    description='STAMP $out',
    command='touch $out')
  master_ninja.rule(
    'copy',
    description='COPY $in $out',
    command='ln -f $in $out 2>/dev/null || cp -af $in $out')
  master_ninja.newline()

  all_targets = set()
  for build_file in params['build_files']:
    for target in gyp.common.AllTargets(target_list, target_dicts, build_file):
      all_targets.add(target)
  all_outputs = set()

  target_outputs = {}
  for qualified_target in target_list:
    # qualified_target is like: third_party/icu/icu.gyp:icui18n#target
    build_file, name, toolset = \
        gyp.common.ParseQualifiedTarget(qualified_target)

    # TODO: what is options.depth and how is it different than
    # options.toplevel_dir?
    build_file = gyp.common.RelativePath(build_file, options.depth)

    base_path = os.path.dirname(build_file)
    obj = 'obj'
    if toolset != 'target':
      obj += '.' + toolset
    output_file = os.path.join(obj, base_path, name + '.ninja')
    spec = target_dicts[qualified_target]
    config = spec['configurations'][config_name]

    writer = NinjaWriter(target_outputs, base_path, builddir,
                         OpenOutput(os.path.join(options.toplevel_dir,
                                                 builddir,
                                                 output_file)))
    master_ninja.subninja(output_file)

    output = writer.WriteSpec(spec, config)
    if output:
      linkable = spec['type'] in ('static_library', 'shared_library')
      target_outputs[qualified_target] = (output, linkable)

      if qualified_target in all_targets:
        all_outputs.add(output)

  if all_outputs:
    master_ninja.build('all', 'phony', list(all_outputs))
コード例 #6
0
ファイル: ninja.py プロジェクト: philips/luvit
def GenerateOutputForConfig(target_list, target_dicts, data, params,
                            config_name):
  options = params['options']
  flavor = gyp.common.GetFlavor(params)
  generator_flags = params.get('generator_flags', {})

  # build_dir: relative path from source root to our output files.
  # e.g. "out/Debug"
  build_dir = os.path.join(generator_flags.get('output_dir', 'out'),
                           config_name)

  master_ninja = ninja_syntax.Writer(
      OpenOutput(os.path.join(options.toplevel_dir, build_dir, 'build.ninja')),
      width=120)

  # Put build-time support tools in out/{config_name}.
  gyp.common.CopyTool(flavor, os.path.join(options.toplevel_dir, build_dir))

  # Grab make settings for CC/CXX.
  if flavor == 'win':
    cc = cxx = 'cl'
  else:
    cc, cxx = 'gcc', 'g++'
  build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0])
  make_global_settings = data[build_file].get('make_global_settings', [])
  build_to_root = InvertRelativePath(build_dir)
  for key, value in make_global_settings:
    if key == 'CC': cc = os.path.join(build_to_root, value)
    if key == 'CXX': cxx = os.path.join(build_to_root, value)

  flock = 'flock'
  if flavor == 'mac':
    flock = './gyp-mac-tool flock'
  master_ninja.variable('cc', os.environ.get('CC', cc))
  master_ninja.variable('cxx', os.environ.get('CXX', cxx))
  if flavor == 'win':
    master_ninja.variable('ld', 'link')
  else:
    master_ninja.variable('ld', flock + ' linker.lock $cxx')
  master_ninja.variable('cc_host', '$cc')
  master_ninja.variable('cxx_host', '$cxx')
  if flavor == 'mac':
    master_ninja.variable('mac_tool', os.path.join('.', 'gyp-mac-tool'))
  master_ninja.newline()

  if flavor != 'win':
    master_ninja.rule(
      'cc',
      description='CC $out',
      command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_c '
              '$cflags_pch_c -c $in -o $out'),
      depfile='$out.d')
    master_ninja.rule(
      'cxx',
      description='CXX $out',
      command=('$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_cc '
              '$cflags_pch_cc -c $in -o $out'),
      depfile='$out.d')
  else:
    # TODO(scottmg): Decide how /showIncludes handling should work in ninja.
    master_ninja.rule(
      'cc',
      description='CC $out',
      command=('$cc /nologo $defines $includes $cflags $cflags_c '
              '$cflags_pch_c /c $in /Fo$out'),
      depfile='$out.d')
    master_ninja.rule(
      'cxx',
      description='CXX $out',
      command=('$cxx /nologo $defines $includes $cflags $cflags_cc '
              '$cflags_pch_cc /c $in /Fo$out'),
      depfile='$out.d')

  if flavor != 'mac' and flavor != 'win':
    master_ninja.rule(
      'alink',
      description='AR $out',
      command='rm -f $out && ar rcsT $out $in')
    master_ninja.rule(
      'solink',
      description='SOLINK $out',
      command=('$ld -shared $ldflags -o $out -Wl,-soname=$soname '
               '-Wl,--whole-archive $in -Wl,--no-whole-archive $libs'))
    master_ninja.rule(
      'solink_module',
      description='SOLINK(module) $out',
      command=('$ld -shared $ldflags -o $out -Wl,-soname=$soname '
               '-Wl,--start-group $in -Wl,--end-group $libs'))
    master_ninja.rule(
      'link',
      description='LINK $out',
      command=('$ld $ldflags -o $out -Wl,-rpath=\$$ORIGIN/lib '
               '-Wl,--start-group $in -Wl,--end-group $libs'))
  elif flavor == 'win':
    master_ninja.rule(
      'alink',
      description='AR $out',
      command='lib /nologo /OUT:$out.lib $in')
    master_ninja.rule(
      'solink',
      description='SOLINK $out',
      command=('$ld /nologo /DLL $ldflags /OUT:$out.dll $in $libs'))
    master_ninja.rule(
      'solink_module',
      description='SOLINK(module) $out',
      command=('$ld /nologo /DLL $ldflags /OUT:$out.dll $in $libs'))
    master_ninja.rule(
      'link',
      description='LINK $out',
      command=('$ld /nologo $ldflags /OUT:$out.exe $in $libs'))
  else:
    master_ninja.rule(
      'objc',
      description='OBJC $out',
      command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_objc '
               '$cflags_pch_objc -c $in -o $out'),
      depfile='$out.d')
    master_ninja.rule(
      'objcxx',
      description='OBJCXX $out',
      command=('$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_objcc '
               '$cflags_pch_objcc -c $in -o $out'),
      depfile='$out.d')
    master_ninja.rule(
      'alink',
      description='LIBTOOL-STATIC $out, POSTBUILDS',
      command='rm -f $out && '
              './gyp-mac-tool filter-libtool libtool -static -o $out $in'
              '$postbuilds')
    # TODO(thakis): The solink_module rule is likely wrong. Xcode seems to pass
    # -bundle -single_module here (for osmesa.so).
    master_ninja.rule(
      'solink',
      description='SOLINK $out, POSTBUILDS',
      command=('$ld -shared $ldflags -o $out '
               '$in $libs$postbuilds'))
    master_ninja.rule(
      'solink_module',
      description='SOLINK(module) $out, POSTBUILDS',
      command=('$ld -shared $ldflags -o $out '
               '$in $libs$postbuilds'))
    master_ninja.rule(
      'link',
      description='LINK $out, POSTBUILDS',
      command=('$ld $ldflags -o $out '
               '$in $libs$postbuilds'))
    master_ninja.rule(
      'infoplist',
      description='INFOPLIST $out',
      command=('$cc -E -P -Wno-trigraphs -x c $defines $in -o $out && '
               'plutil -convert xml1 $out $out'))
    master_ninja.rule(
      'mac_tool',
      description='MACTOOL $mactool_cmd $in',
      command='$env $mac_tool $mactool_cmd $in $out')
    master_ninja.rule(
      'package_framework',
      description='PACKAGE FRAMEWORK $out, POSTBUILDS',
      command='$mac_tool package-framework $out $version$postbuilds '
              '&& touch $out')
  master_ninja.rule(
    'stamp',
    description='STAMP $out',
    command='${postbuilds}touch $out')
  if flavor == 'win':
    # TODO(scottmg): Copy fallback?
    master_ninja.rule(
      'copy',
      description='COPY $in $out',
      command='mklink /h $out $in >nul')
  else:
    master_ninja.rule(
      'copy',
      description='COPY $in $out',
      command='ln -f $in $out 2>/dev/null || (rm -rf $out && cp -af $in $out)')
  master_ninja.newline()

  all_targets = set()
  for build_file in params['build_files']:
    for target in gyp.common.AllTargets(target_list, target_dicts, build_file):
      all_targets.add(target)
  all_outputs = set()

  # target_outputs is a map from qualified target name to a Target object.
  target_outputs = {}
  for qualified_target in target_list:
    # qualified_target is like: third_party/icu/icu.gyp:icui18n#target
    build_file, name, toolset = \
        gyp.common.ParseQualifiedTarget(qualified_target)

    this_make_global_settings = data[build_file].get('make_global_settings', [])
    assert make_global_settings == this_make_global_settings, (
        "make_global_settings needs to be the same for all targets.")

    spec = target_dicts[qualified_target]
    if flavor == 'mac':
      gyp.xcode_emulation.MergeGlobalXcodeSettingsToSpec(data[build_file], spec)

    build_file = gyp.common.RelativePath(build_file, options.toplevel_dir)

    base_path = os.path.dirname(build_file)
    obj = 'obj'
    if toolset != 'target':
      obj += '.' + toolset
    output_file = os.path.join(obj, base_path, name + '.ninja')

    abs_build_dir=os.path.abspath(os.path.join(options.toplevel_dir, build_dir))
    writer = NinjaWriter(target_outputs, base_path, build_dir,
                         OpenOutput(os.path.join(options.toplevel_dir,
                                                 build_dir,
                                                 output_file)),
                         flavor, abs_build_dir=abs_build_dir)
    master_ninja.subninja(output_file)

    target = writer.WriteSpec(spec, config_name)
    if target:
      target_outputs[qualified_target] = target
      if qualified_target in all_targets:
        all_outputs.add(target.FinalOutput())

  if all_outputs:
    master_ninja.build('all', 'phony', list(all_outputs))
コード例 #7
0
ファイル: ninja.py プロジェクト: liexusong/phode
 def __init__(self, target_outputs, base_dir, output_file):
     self.target_outputs = target_outputs
     # The root-relative path to the source .gyp file; by gyp
     # semantics, all input paths are relative to this.
     self.base_dir = base_dir
     self.ninja = ninja_syntax.Writer(output_file)