| Index: pylib/gyp/generator/ninja.py
|
| diff --git a/pylib/gyp/generator/ninja.py b/pylib/gyp/generator/ninja.py
|
| index 6823f4ffbdaf25ad8676650f65e55cd3e58b2a30..602f9fdb36d5a1406303974736d0376b4b21acd5 100644
|
| --- a/pylib/gyp/generator/ninja.py
|
| +++ b/pylib/gyp/generator/ninja.py
|
| @@ -140,6 +140,10 @@ class Target(object):
|
| # On Windows, incremental linking requires linking against all the .objs
|
| # that compose a .lib (rather than the .lib itself). That list is stored
|
| # here.
|
| +
|
| + # Path to the file representing completion of building module, if any.
|
| + self.module_stamp = None
|
| +
|
| self.component_objs = None
|
| # Windows only. The import .lib is the output of a build step, but
|
| # because dependents only link against the lib (not both the lib and the
|
| @@ -376,6 +380,9 @@ class NinjaWriter(object):
|
| # should be used for linking.
|
| self.uses_cpp = False
|
|
|
| + # Track if there are any swift sources
|
| + self.uses_swift = False
|
| +
|
| self.is_mac_bundle = gyp.xcode_emulation.IsMacBundle(self.flavor, spec)
|
| self.xcode_settings = self.msvs_settings = None
|
| if self.flavor == 'mac':
|
| @@ -408,6 +415,7 @@ class NinjaWriter(object):
|
| # any of its compile steps.
|
| actions_depends = []
|
| compile_depends = []
|
| + module_depends = []
|
| # TODO(evan): it is rather confusing which things are lists and which
|
| # are strings. Fix these.
|
| if 'dependencies' in spec:
|
| @@ -416,8 +424,14 @@ class NinjaWriter(object):
|
| target = self.target_outputs[dep]
|
| actions_depends.append(target.PreActionInput(self.flavor))
|
| compile_depends.append(target.PreCompileInput())
|
| + module_depends.append(target.module_stamp)
|
| actions_depends = filter(None, actions_depends)
|
| compile_depends = filter(None, compile_depends)
|
| + module_depends = filter(None, module_depends)
|
| + if (self.flavor == 'mac' and
|
| + self.xcode_settings.AreModulesEnabled(config_name)):
|
| + compile_depends += module_depends
|
| +
|
| actions_depends = self.WriteCollapsedDependencies('actions_depends',
|
| actions_depends)
|
| compile_depends = self.WriteCollapsedDependencies('compile_depends',
|
| @@ -439,6 +453,14 @@ class NinjaWriter(object):
|
| # because no compile ever depends on them.
|
| compile_depends_stamp = (self.target.actions_stamp or compile_depends)
|
|
|
| + if self.flavor == 'mac':
|
| + # Module should be written before compilaton, because Swift compiler
|
| + # use it
|
| + module_stamp = self.WriteModule(self.ninja, compile_depends_stamp,
|
| + config_name, spec)
|
| + if module_stamp:
|
| + compile_depends_stamp = module_stamp
|
| +
|
| # Write out the compilation steps, if any.
|
| link_deps = []
|
| sources = extra_sources + spec.get('sources', [])
|
| @@ -855,6 +877,236 @@ class NinjaWriter(object):
|
| ('binary', isBinary)])
|
| bundle_depends.append(out)
|
|
|
| + def _AddSwiftModuleExt(self, module):
|
| + return module + '.swiftmodule'
|
| +
|
| + def _GetSwiftModulePath(self, config_name, spec, arch=None):
|
| + module_path = self._AddSwiftModuleExt(
|
| + self.xcode_settings.GetProductModuleName(config_name))
|
| + if self._IsFramework(spec):
|
| + module_path = os.path.join(
|
| + self.xcode_settings.GetBundleModulesFolderPath(), module_path)
|
| + if arch:
|
| + # Fixing path for armv7, since Xcode expects it to have 'arm' name instead
|
| + if arch == 'armv7':
|
| + arch = 'arm'
|
| + module_path = os.path.join(module_path, self._AddSwiftModuleExt(arch))
|
| + return module_path
|
| +
|
| + def WriteFrameworkHeaders(self, ninja_file, headers, headers_dir):
|
| + outputs = []
|
| + for header in headers:
|
| + out_path = os.path.join(headers_dir, os.path.basename(header))
|
| + outputs.append(out_path)
|
| + self.ninja.build(out_path, 'mac_tool', header,
|
| + variables=[('mactool_cmd', 'copy-bundle-resource'), \
|
| + ('binary', False)])
|
| + return outputs
|
| +
|
| + def _GetModuleMapFilePath(self):
|
| + return os.path.join(self.xcode_settings.GetBundleModulesFolderPath(),
|
| + 'module.modulemap')
|
| +
|
| + def _IsFramework(self, spec):
|
| + is_framework = (spec['type'] == 'shared_library') and self.is_mac_bundle
|
| + return is_framework
|
| +
|
| + def WriteModule(self, ninja_file, predepends, config_name, spec):
|
| + """Write build rules to build Clang module."""
|
| + if not self.xcode_settings.IsModuleDefined(config_name):
|
| + return None
|
| + if not self._IsFramework(spec):
|
| + # There are no any actions by Xcode for non-framework targets
|
| + return None
|
| +
|
| + assert(self.xcode_settings.AreModulesEnabled(config_name))
|
| +
|
| + ninja_file.newline()
|
| +
|
| + module_inputs = []
|
| + # Copying headers to framework
|
| + public_headers = map(self.GypPathToNinja,
|
| + list(spec.get('mac_framework_headers', [])))
|
| + module_inputs += self.WriteFrameworkHeaders(
|
| + ninja_file, public_headers,
|
| + self.xcode_settings.GetBundlePublicHeadersFolderPath())
|
| +
|
| + private_headers = map(self.GypPathToNinja,
|
| + list(spec.get('mac_framework_private_headers', [])))
|
| + module_inputs += self.WriteFrameworkHeaders(
|
| + ninja_file, private_headers,
|
| + self.xcode_settings.GetBundlePrivateHeadersFolderPath())
|
| +
|
| + module_name = self.xcode_settings.GetProductModuleName(config_name)
|
| + umbrella_header = None
|
| + for header in public_headers:
|
| + filename, _ = os.path.splitext(os.path.basename(header))
|
| + if filename == module_name:
|
| + umbrella_header = header
|
| + break
|
| +
|
| + assert(umbrella_header)
|
| +
|
| + # Building module map file in the /Modules folder
|
| + module_map_path = self._GetModuleMapFilePath()
|
| + variables = {
|
| + 'module_name': module_name,
|
| + 'umbrella_header': os.path.basename(umbrella_header),
|
| + 'map_file': module_map_path }
|
| + module_map_stamp = self.GypPathToUniqueOutput('modulemap.stamp')
|
| + self.ninja.build(module_map_stamp, 'modulemap', [umbrella_header],
|
| + variables=variables)
|
| + module_inputs.append(module_map_stamp)
|
| +
|
| + # Resulting module stamp
|
| + module_stamp = self.GypPathToUniqueOutput('module.stamp')
|
| + self.ninja.build(module_stamp, 'stamp', module_inputs,
|
| + order_only=predepends)
|
| + self.target.module_stamp = module_stamp
|
| + ninja_file.newline()
|
| + return module_stamp
|
| +
|
| + def WriteSwiftSourcesForArch(self, ninja_file, config_name, sources,
|
| + predepends, spec, arch=None):
|
| + assert(self.flavor == 'mac')
|
| +
|
| + # Collecting all Swift sources
|
| + swift_sources = []
|
| + for source in sources:
|
| + filename, ext = os.path.splitext(source)
|
| + ext = ext[1:]
|
| + if ext == 'swift':
|
| + swift_sources.append(self.GypPathToNinja(source))
|
| + if not swift_sources:
|
| + return ([], None)
|
| +
|
| + self.uses_swift = True
|
| +
|
| + if not arch:
|
| + arch = self.archs[0]
|
| +
|
| + # Writing compile flags
|
| + swift_compile_flags = self.xcode_settings.GetSwiftCompileFlags(
|
| + config_name, self.GypPathToNinja, arch)
|
| + self.WriteVariableList(ninja_file, 'swift_compile_flags',
|
| + map(self.ExpandSpecial, swift_compile_flags))
|
| + ninja_file.newline()
|
| +
|
| + # Writing per-file rules
|
| + link_deps = []
|
| + partial_modules = []
|
| + for source in swift_sources:
|
| + filename, ext = os.path.splitext(os.path.basename(source))
|
| + obj_path = self.GypPathToUniqueOutput(filename + self.obj_ext)
|
| + obj_path = AddArch(obj_path, arch)
|
| + src_module_path = self.GypPathToUniqueOutput(
|
| + self._AddSwiftModuleExt(filename))
|
| + src_module_path = AddArch(src_module_path, arch)
|
| +
|
| + compile_input = [source]
|
| + for another_source in swift_sources:
|
| + if source != another_source:
|
| + compile_input.append(another_source)
|
| +
|
| + variables = {'out_obj': obj_path, 'out_module': src_module_path}
|
| + ninja_file.build([obj_path, src_module_path], 'swift', compile_input,
|
| + variables=variables,
|
| + order_only=predepends)
|
| +
|
| + link_deps.append(obj_path)
|
| + partial_modules.append(src_module_path)
|
| +
|
| + ninja_file.newline()
|
| +
|
| + # Writing Swift merge flags
|
| + swift_merge_flags = self.xcode_settings.GetSwiftMergeFlags(
|
| + config_name, self.GypPathToNinja, arch)
|
| + self.WriteVariableList(ninja_file, 'swift_merge_flags',
|
| + map(self.ExpandSpecial, swift_merge_flags))
|
| + ninja_file.newline()
|
| +
|
| +
|
| + # Writing header for first arch without arch extension,
|
| + # for it to be used by Objc sources
|
| + header_arch = None if arch == self.archs[0] else arch
|
| + header_path = self.xcode_settings.GetSwiftHeaderPath(
|
| + config_name, self.GypPathToNinja, header_arch)
|
| + module_path = self._GetSwiftModulePath(config_name, spec, arch)
|
| + variables = {'out_module': module_path, 'out_header': header_path}
|
| + ninja_file.build([module_path, header_path], 'swiftmerge',
|
| + partial_modules, variables=variables)
|
| + ninja_file.newline()
|
| +
|
| + return (link_deps, module_path)
|
| +
|
| + def WriteSwiftModule(self, ninja_file, config_name, spec):
|
| + """Write build rules to build Swift module data"""
|
| + if not self.uses_swift:
|
| + return
|
| +
|
| + assert(self.xcode_settings.AreModulesEnabled(config_name))
|
| +
|
| + ninja_file.newline()
|
| +
|
| + module_inputs = []
|
| + map_depends = []
|
| + for arch in self.archs:
|
| + swift_module_path = self._GetSwiftModulePath(config_name, spec, arch)
|
| + module_inputs.append(swift_module_path)
|
| + map_depends.append(swift_module_path)
|
| +
|
| + if self._IsFramework(spec):
|
| + assert(self.xcode_settings.IsModuleDefined(config_name))
|
| +
|
| + # Copying Swift header to framework
|
| + swift_header = self.xcode_settings.GetSwiftHeaderPath(
|
| + config_name, self.GypPathToNinja)
|
| + module_inputs += self.WriteFrameworkHeaders(
|
| + ninja_file, [swift_header],
|
| + self.xcode_settings.GetBundlePublicHeadersFolderPath())
|
| +
|
| + # Appending Swift info to the module map file in the /Modules folder
|
| + module_name = self.xcode_settings.GetProductModuleName(config_name)
|
| + module_map_path = self._GetModuleMapFilePath()
|
| + variables = {
|
| + 'module_name': module_name,
|
| + 'swift_header': os.path.basename(swift_header),
|
| + 'map_file': module_map_path }
|
| + module_map_stamp = self.GypPathToUniqueOutput('swiftmodulemap.stamp')
|
| + self.ninja.build(module_map_stamp, 'swiftmodulemap', [swift_header],
|
| + order_only=map_depends, variables=variables)
|
| + module_inputs.append(module_map_stamp)
|
| +
|
| + # Resulting Swift actions stamp
|
| + module_stamp = self.GypPathToUniqueOutput('swift_module.stamp')
|
| + self.ninja.build(module_stamp, 'stamp', module_inputs)
|
| + self.target.module_stamp = module_stamp
|
| + ninja_file.newline()
|
| +
|
| + def AppendSwiftLinkerOptions(self, ldflags, implicit_deps, config_name, spec,
|
| + arch):
|
| + if not self.uses_swift:
|
| + return
|
| + if arch is None:
|
| + arch = self.archs[0]
|
| + module_path = self._GetSwiftModulePath(config_name, spec, arch)
|
| + ldflags += self.xcode_settings.GetSwiftLdflags(config_name, module_path)
|
| + implicit_deps.add(module_path)
|
| +
|
| + def CopySwiftLibsToBundle(self, spec):
|
| + is_final = spec['type'] in ('executable', 'loadable_module')
|
| + if not gyp.xcode_emulation.IsSwiftSupported() or not is_final:
|
| + return None
|
| +
|
| + # Copying all needed Swift dylibs right into the bundle
|
| + app_frameworks_path = (
|
| + self.xcode_settings.GetBundleFrameworksFolderPath())
|
| + swift_libs_path = self.xcode_settings.GetSwiftLibsPath(self.config_name)
|
| + variables = {'swift_libs_path': swift_libs_path}
|
| + self.ninja.build(app_frameworks_path, 'copyswiftlibs', self.target.binary,
|
| + variables=variables)
|
| + return app_frameworks_path
|
| +
|
| def WriteSources(self, ninja_file, config_name, config, sources, predepends,
|
| precompiled_header, spec):
|
| """Write build rules to compile all of |sources|."""
|
| @@ -976,6 +1228,13 @@ class NinjaWriter(object):
|
| map(self.ExpandSpecial, arflags))
|
| ninja_file.newline()
|
| outputs = []
|
| +
|
| + if self.flavor == 'mac':
|
| + swift_outputs, swift_module = self.WriteSwiftSourcesForArch(
|
| + ninja_file, config_name, sources, predepends, spec, arch)
|
| + outputs += swift_outputs
|
| + predepends = swift_module or predepends
|
| +
|
| has_rc_source = False
|
| for source in sources:
|
| filename, ext = os.path.splitext(source)
|
| @@ -1139,6 +1398,8 @@ class NinjaWriter(object):
|
| self.ExpandSpecial(generator_default_variables['PRODUCT_DIR']),
|
| self.GypPathToNinja, arch)
|
| ldflags = env_ldflags + ldflags
|
| + self.AppendSwiftLinkerOptions(
|
| + ldflags, implicit_deps, config_name, spec, arch)
|
| elif self.flavor == 'win':
|
| manifest_base_name = self.GypPathToUniqueOutput(
|
| self.ComputeOutputFileName(spec))
|
| @@ -1248,6 +1509,7 @@ class NinjaWriter(object):
|
| return linked_binary
|
|
|
| def WriteTarget(self, spec, config_name, config, link_deps, compile_deps):
|
| + self.WriteSwiftModule(self.ninja, config_name, spec)
|
| extra_link_deps = any(self.target_outputs.get(dep).Linkable()
|
| for dep in spec.get('dependencies', [])
|
| if dep in self.target_outputs)
|
| @@ -1300,6 +1562,14 @@ class NinjaWriter(object):
|
|
|
| def WriteMacBundle(self, spec, mac_bundle_depends, is_empty):
|
| assert self.is_mac_bundle
|
| +
|
| + swift_frameworks = self.CopySwiftLibsToBundle(spec)
|
| + if swift_frameworks:
|
| + mac_bundle_depends.append(swift_frameworks)
|
| +
|
| + if self.target.module_stamp:
|
| + mac_bundle_depends.append(self.target.module_stamp)
|
| +
|
| package_framework = spec['type'] in ('shared_library', 'loadable_module')
|
| output = self.ComputeMacBundleOutput()
|
| if is_empty:
|
| @@ -1922,6 +2192,10 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params,
|
| master_ninja.variable(
|
| 'readelf', GetEnvironFallback(['READELF_target', 'READELF'], readelf))
|
|
|
| + if flavor == 'mac' and gyp.xcode_emulation.IsSwiftSupported():
|
| + master_ninja.variable(
|
| + 'swift', subprocess.check_output(['xcrun', '-f', 'swift']))
|
| +
|
| if generator_supports_multiple_toolsets:
|
| if not cc_host:
|
| cc_host = cc
|
| @@ -2106,6 +2380,32 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params,
|
| depfile='$out.d',
|
| deps=deps)
|
| master_ninja.rule(
|
| + 'swift',
|
| + description='SWIFT $out_obj',
|
| + command=('$swift -frontend -c -primary-file $in $swift_compile_flags '
|
| + '-emit-module-path $out_module '
|
| + '-o $out_obj'))
|
| + master_ninja.rule(
|
| + 'swiftmerge',
|
| + description='SWIFT MERGE $out_module',
|
| + command=('$swift -frontend -emit-module $in $swift_merge_flags '
|
| + '-emit-objc-header-path $out_header '
|
| + '-o $out_module'))
|
| + master_ninja.rule(
|
| + 'copyswiftlibs',
|
| + description='COPY SWIFT LIBS $out',
|
| + command=('./gyp-mac-tool copy-swift-libs $swift_libs_path $out $in'))
|
| + master_ninja.rule(
|
| + 'modulemap',
|
| + description='MODULE MAP $map_file',
|
| + command=('./gyp-mac-tool build-module-map-file '
|
| + '$module_name $umbrella_header $map_file $out'))
|
| + master_ninja.rule(
|
| + 'swiftmodulemap',
|
| + description='SWIFT MODULE MAP $map_file',
|
| + command=('./gyp-mac-tool append-swift-to-module-map-file '
|
| + '$module_name $swift_header $map_file $out'))
|
| + master_ninja.rule(
|
| 'alink',
|
| description='LIBTOOL-STATIC $out, POSTBUILDS',
|
| command='rm -f $out && '
|
|
|