From dbfc8198a6879a0764314db701b610ca2f0c038b Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Tue, 18 Oct 2011 14:38:48 -0700 Subject: [PATCH] Upgrade GYP to r1078 --- tools/gyp/DEPS | 16 +- tools/gyp/pylib/gyp/MSVSSettings.py | 2 +- tools/gyp/pylib/gyp/__init__.py | 2 + tools/gyp/pylib/gyp/generator/gypd.py | 3 +- tools/gyp/pylib/gyp/generator/gypsh.py | 3 +- tools/gyp/pylib/gyp/generator/make.py | 338 +++++++++++++++++-------- tools/gyp/pylib/gyp/generator/msvs.py | 96 ++++--- tools/gyp/pylib/gyp/generator/ninja.py | 33 ++- tools/gyp/pylib/gyp/generator/scons.py | 3 +- tools/gyp/pylib/gyp/generator/xcode.py | 5 +- tools/gyp/pylib/gyp/mac_tool.py | 10 +- 11 files changed, 341 insertions(+), 170 deletions(-) diff --git a/tools/gyp/DEPS b/tools/gyp/DEPS index 0e56c063df..c331448091 100644 --- a/tools/gyp/DEPS +++ b/tools/gyp/DEPS @@ -2,7 +2,21 @@ # # (You don't need to use gclient for normal GYP development work.) +vars = { + "chrome_trunk": "http://src.chromium.org/svn/trunk", +} + deps = { "scons": - "http://src.chromium.org/svn/trunk/src/third_party/scons@44099", + Var("chrome_trunk") + "/src/third_party/scons@44099", +} + +deps_os = { + "win": { + "third_party/cygwin": + Var("chrome_trunk") + "/deps/third_party/cygwin@66844", + + "third_party/python_26": + Var("chrome_trunk") + "/tools/third_party/python_26@89111", + }, } diff --git a/tools/gyp/pylib/gyp/MSVSSettings.py b/tools/gyp/pylib/gyp/MSVSSettings.py index 496f179bf6..6b364826a5 100644 --- a/tools/gyp/pylib/gyp/MSVSSettings.py +++ b/tools/gyp/pylib/gyp/MSVSSettings.py @@ -966,6 +966,7 @@ _Same(_lib, 'ModuleDefinitionFile', _file_name) # /DEF _Same(_lib, 'OutputFile', _file_name) # /OUT _Same(_lib, 'SuppressStartupBanner', _boolean) # /NOLOGO _Same(_lib, 'UseUnicodeResponseFiles', _boolean) +_Same(_lib, 'LinkTimeCodeGeneration', _boolean) # /LTCG # TODO(jeanluc) _link defines the same value that gets moved to # ProjectReference. We may want to validate that they are consistent. @@ -980,7 +981,6 @@ _MSBuildOnly(_lib, 'ErrorReporting', 'QueueForNextLogin', # /ERRORREPORT:QUEUE 'SendErrorReport', # /ERRORREPORT:SEND 'NoErrorReport'])) # /ERRORREPORT:NONE -_MSBuildOnly(_lib, 'LinkTimeCodeGeneration', _boolean) # /LTCG _MSBuildOnly(_lib, 'MinimumRequiredVersion', _string) _MSBuildOnly(_lib, 'Name', _file_name) # /NAME _MSBuildOnly(_lib, 'RemoveObjects', _file_list) # /REMOVE diff --git a/tools/gyp/pylib/gyp/__init__.py b/tools/gyp/pylib/gyp/__init__.py index 37635d0f9b..36d1b996ea 100644 --- a/tools/gyp/pylib/gyp/__init__.py +++ b/tools/gyp/pylib/gyp/__init__.py @@ -335,6 +335,7 @@ def main(args): 'linux2': 'make', 'linux3': 'make', 'openbsd4': 'make', + 'openbsd5': 'make', 'sunos5': 'make',}[sys.platform] ] if not options.generator_output and options.use_environment: @@ -418,6 +419,7 @@ def main(args): if home_dot_gyp != None: default_include = os.path.join(home_dot_gyp, 'include.gypi') if os.path.exists(default_include): + print 'Using overrides found in ' + default_include includes.append(default_include) # Command-line --include files come after the default include. diff --git a/tools/gyp/pylib/gyp/generator/gypd.py b/tools/gyp/pylib/gyp/generator/gypd.py index 948f0b8521..eeb8d5756e 100644 --- a/tools/gyp/pylib/gyp/generator/gypd.py +++ b/tools/gyp/pylib/gyp/generator/gypd.py @@ -1,6 +1,6 @@ #!/usr/bin/python -# Copyright (c) 2009 Google Inc. All rights reserved. +# Copyright (c) 2011 Google Inc. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -46,6 +46,7 @@ _generator_identity_variables = [ 'INTERMEDIATE_DIR', 'PRODUCT_DIR', 'RULE_INPUT_ROOT', + 'RULE_INPUT_DIRNAME', 'RULE_INPUT_EXT', 'RULE_INPUT_NAME', 'RULE_INPUT_PATH', diff --git a/tools/gyp/pylib/gyp/generator/gypsh.py b/tools/gyp/pylib/gyp/generator/gypsh.py index f48b03fa72..75d20f5813 100644 --- a/tools/gyp/pylib/gyp/generator/gypsh.py +++ b/tools/gyp/pylib/gyp/generator/gypsh.py @@ -1,6 +1,6 @@ #!/usr/bin/python -# Copyright (c) 2009 Google Inc. All rights reserved. +# Copyright (c) 2011 Google Inc. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -28,6 +28,7 @@ _generator_identity_variables = [ 'INTERMEDIATE_DIR', 'PRODUCT_DIR', 'RULE_INPUT_ROOT', + 'RULE_INPUT_DIRNAME', 'RULE_INPUT_EXT', 'RULE_INPUT_NAME', 'RULE_INPUT_PATH', diff --git a/tools/gyp/pylib/gyp/generator/make.py b/tools/gyp/pylib/gyp/generator/make.py index eded5ac0af..de920a71bb 100644 --- a/tools/gyp/pylib/gyp/generator/make.py +++ b/tools/gyp/pylib/gyp/generator/make.py @@ -44,6 +44,7 @@ generator_default_variables = { 'SHARED_INTERMEDIATE_DIR': '$(obj)/gen', 'PRODUCT_DIR': '$(builddir)', 'RULE_INPUT_ROOT': '%(INPUT_ROOT)s', # This gets expanded by Python. + 'RULE_INPUT_DIRNAME': '%(INPUT_DIRNAME)s', # This gets expanded by Python. 'RULE_INPUT_PATH': '$(abspath $<)', 'RULE_INPUT_EXT': '$(suffix $<)', 'RULE_INPUT_NAME': '$(notdir $<)', @@ -61,14 +62,7 @@ generator_wants_sorted_dependencies = False def GetFlavor(params): """Returns |params.flavor| if it's set, the system's default flavor else.""" - flavors = { - 'darwin': 'mac', - 'sunos5': 'solaris', - 'freebsd7': 'freebsd', - 'freebsd8': 'freebsd', - } - flavor = flavors.get(sys.platform, 'linux') - return params.get('flavor', flavor) + return params.get('flavor', 'mac' if sys.platform == 'darwin' else 'linux') def CalculateVariables(default_variables, params): @@ -77,8 +71,7 @@ def CalculateVariables(default_variables, params): default_variables['LINKER_SUPPORTS_ICF'] = \ gyp.system_test.TestLinkerSupportsICF(cc_command=cc_target) - flavor = GetFlavor(params) - if flavor == 'mac': + if GetFlavor(params) == 'mac': default_variables.setdefault('OS', 'mac') default_variables.setdefault('SHARED_LIB_SUFFIX', '.dylib') default_variables.setdefault('SHARED_LIB_DIR', @@ -101,7 +94,7 @@ def CalculateVariables(default_variables, params): global COMPILABLE_EXTENSIONS COMPILABLE_EXTENSIONS.update({'.m': 'objc', '.mm' : 'objcxx'}) else: - default_variables.setdefault('OS', flavor) + default_variables.setdefault('OS', 'linux') default_variables.setdefault('SHARED_LIB_SUFFIX', '.so') default_variables.setdefault('SHARED_LIB_DIR','$(builddir)/lib.$(TOOLSET)') default_variables.setdefault('LIB_DIR', '$(obj).$(TOOLSET)') @@ -255,6 +248,8 @@ abs_obj := $(abspath $(obj)) # generated dependency rule Makefiles in one pass. all_deps := +%(make_global_settings)s + # C++ apps need to be linked with g++. # # Note: flock is used to seralize linking. Linking is a memory-intensive @@ -266,9 +261,6 @@ all_deps := # This will allow make to invoke N linker processes as specified in -jN. LINK ?= %(flock)s $(builddir)/linker.lock $(CXX) -%(make_global_settings)s - -LINK ?= $(FLOCK) $(CXX) CC.target ?= $(CC) CFLAGS.target ?= $(CFLAGS) CXX.target ?= $(CXX) @@ -357,7 +349,7 @@ cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $ quiet_cmd_cxx = CXX($(TOOLSET)) $@ cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< -%(extra_commands)s +%(mac_commands)s quiet_cmd_touch = TOUCH $@ cmd_touch = touch $@ @@ -407,6 +399,23 @@ command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\\ # $| -- order-only dependencies prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?)) +# Helper that executes all postbuilds, and deletes the output file when done +# if any of the postbuilds failed. +define do_postbuilds + @E=0;\\ + for p in $(POSTBUILDS); do\\ + eval $$p;\\ + F=$$?;\\ + if [ $$F -ne 0 ]; then\\ + E=$$F;\\ + fi;\\ + done;\\ + if [ $$E -ne 0 ]; then\\ + rm -rf "$@";\\ + exit $$E;\\ + fi +endef + # do_cmd: run a command via the above cmd_foo names, if necessary. # Should always run for a given target to handle command-line changes. # Second argument, if non-zero, makes it do asm/C/C++ dependency munging. @@ -427,7 +436,7 @@ $(if $(or $(command_changed),$(prereq_changed)), @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile) @$(if $(2),$(fixup_dep)) $(if $(and $(3), $(POSTBUILDS)), - @for p in $(POSTBUILDS); do eval $$p; done + $(call do_postbuilds) ) ) endef @@ -471,14 +480,6 @@ quiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@ cmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(4) """ -SHARED_HEADER_SUN_COMMANDS = """ -# gyp-sun-tool is written next to the root Makefile by gyp. -# Use $(4) for the command, since $(2) and $(3) are used as flag by do_cmd -# already. -quiet_cmd_sun_tool = SUNTOOL $(4) $< -cmd_sun_tool = ./gyp-sun-tool $(4) $< "$@" -""" - def WriteRootHeaderSuffixRules(writer): extensions = sorted(COMPILABLE_EXTENSIONS.keys(), key=str.lower) @@ -654,9 +655,11 @@ class XcodeSettings(object): def _Test(self, test_key, cond_key, default): return self._Settings().get(test_key, default) == cond_key - def _Appendf(self, lst, test_key, format_str): + def _Appendf(self, lst, test_key, format_str, default=None): if test_key in self._Settings(): lst.append(format_str % str(self._Settings()[test_key])) + elif default: + lst.append(format_str % str(default)) def _WarnUnimplemented(self, test_key): if test_key in self._Settings(): @@ -676,8 +679,12 @@ class XcodeSettings(object): valid for bundles.""" assert self._IsBundle() if self.spec['type'] in ('loadable_module', 'shared_library'): + default_wrapper_extension = { + 'loadable_module': 'bundle', + 'shared_library': 'framework', + }[self.spec['type']] wrapper_extension = self.GetPerTargetSetting( - 'WRAPPER_EXTENSION', default='framework') + 'WRAPPER_EXTENSION', default=default_wrapper_extension) return '.' + self.spec.get('product_extension', wrapper_extension) elif self.spec['type'] == 'executable': return '.app' @@ -716,22 +723,47 @@ class XcodeSettings(object): """Returns the qualified path to the bundle's plist file. E.g. Chromium.app/Contents/Info.plist. Only valid for bundles.""" assert self._IsBundle() - assert self.spec['type'] != 'loadable_modules', ( - "Info.plist files for loadable_modules not yet supported by the " - "make generator (target %s)" % self.spec['target_name']) # Not tested. - if self.spec['type'] == 'executable': + if self.spec['type'] in ('executable', 'loadable_module'): return os.path.join(self.GetBundleContentsFolderPath(), 'Info.plist') else: return os.path.join(self.GetBundleContentsFolderPath(), 'Resources', 'Info.plist') + def GetProductType(self): + """Returns the PRODUCT_TYPE of this target.""" + if self._IsBundle(): + return { + 'executable': 'com.apple.product-type.application', + 'loadable_module': 'com.apple.product-type.bundle', + 'shared_library': 'com.apple.product-type.framework', + }[self.spec['type']] + else: + return { + 'executable': 'com.apple.product-type.tool', + 'loadable_module': 'com.apple.product-type.library.dynamic', + 'shared_library': 'com.apple.product-type.library.dynamic', + 'static_library': 'com.apple.product-type.library.static', + }[self.spec['type']] + + def GetMachOType(self): + """Returns the MACH_O_TYPE of this target.""" + # Weird, but matches Xcode. + if not self._IsBundle() and self.spec['type'] == 'executable': + return '' + return { + 'executable': 'mh_execute', + 'static_library': 'staticlib', + 'shared_library': 'mh_dylib', + 'loadable_module': 'mh_bundle', + }[self.spec['type']] + def _GetBundleBinaryPath(self): """Returns the name of the bundle binary of by this target. E.g. Chromium.app/Contents/MacOS/Chromium. Only valid for bundles.""" assert self._IsBundle() - if self.spec['type'] in ('loadable_module', 'shared_library'): + if self.spec['type'] in ('shared_library'): path = self.GetBundleContentsFolderPath() - elif self.spec['type'] == 'executable': + elif self.spec['type'] in ('executable', 'loadable_module'): path = os.path.join(self.GetBundleContentsFolderPath(), 'MacOS') return os.path.join(path, self.spec.get('product_name', self.spec['target_name'])) @@ -819,7 +851,7 @@ class XcodeSettings(object): if self._Test('GCC_ENABLE_PASCAL_STRINGS', 'YES', default='YES'): cflags.append('-mpascal-strings') - self._Appendf(cflags, 'GCC_OPTIMIZATION_LEVEL', '-O%s') + self._Appendf(cflags, 'GCC_OPTIMIZATION_LEVEL', '-O%s', default='s') if self._Test('GCC_GENERATE_DEBUGGING_SYMBOLS', 'YES', default='YES'): dbg_format = self._Settings().get('DEBUG_INFORMATION_FORMAT', 'dwarf') @@ -828,12 +860,7 @@ class XcodeSettings(object): elif dbg_format == 'stabs': raise NotImplementedError('stabs debug format is not supported yet.') elif dbg_format == 'dwarf-with-dsym': - # TODO(thakis): this is needed for mac_breakpad chromium builds, but not - # for regular chromium builds. - # -gdwarf-2 as well, but needs to invoke dsymutil after linking too: - # dsymutil build/Default/TestAppGyp.app/Contents/MacOS/TestAppGyp \ - # -o build/Default/TestAppGyp.app.dSYM - raise NotImplementedError('dsym debug format is not supported yet.') + cflags.append('-gdwarf-2') else: raise NotImplementedError('Unknown debug format %s' % dbg_format) @@ -850,15 +877,17 @@ class XcodeSettings(object): # TODO: self._WarnUnimplemented('ARCHS') - self._WarnUnimplemented('COPY_PHASE_STRIP') - self._WarnUnimplemented('DEPLOYMENT_POSTPROCESSING') + if self._Test('COPY_PHASE_STRIP', 'YES', default='NO'): + self._WarnUnimplemented('COPY_PHASE_STRIP') self._WarnUnimplemented('GCC_DEBUGGING_SYMBOLS') self._WarnUnimplemented('GCC_ENABLE_OBJC_EXCEPTIONS') self._WarnUnimplemented('GCC_ENABLE_OBJC_GC') self._WarnUnimplemented('INFOPLIST_PREPROCESS') self._WarnUnimplemented('INFOPLIST_PREPROCESSOR_DEFINITIONS') - self._WarnUnimplemented('STRIPFLAGS') - self._WarnUnimplemented('STRIP_INSTALLED_PRODUCT') + + # TODO: This is exported correctly, but assigning to it is not supported. + self._WarnUnimplemented('MACH_O_TYPE') + self._WarnUnimplemented('PRODUCT_TYPE') # TODO: Do not hardcode arch. Supporting fat binaries will be annoying. cflags.append('-arch i386') @@ -1040,6 +1069,64 @@ class XcodeSettings(object): return default return result + def _GetStripPostbuilds(self, configname, output_binary): + """Returns a list of shell commands that contain the shell commands + neccessary to strip this target's binary. These should be run as postbuilds + before the actual postbuilds run.""" + self.configname = configname + + result = [] + if (self._Test('DEPLOYMENT_POSTPROCESSING', 'YES', default='NO') and + self._Test('STRIP_INSTALLED_PRODUCT', 'YES', default='NO')): + + default_strip_style = 'debugging' + if self._IsBundle(): + default_strip_style = 'non-global' + elif self.spec['type'] == 'executable': + default_strip_style = 'all' + + strip_style = self._Settings().get('STRIP_STYLE', default_strip_style) + strip_flags = { + 'all': '', + 'non-global': '-x', + 'debugging': '-S', + }[strip_style] + + explicit_strip_flags = self._Settings().get('STRIPFLAGS', '') + if explicit_strip_flags: + strip_flags += ' ' + explicit_strip_flags + + result.append('echo STRIP\\(%s\\)' % self.spec['target_name']) + result.append('strip %s %s' % (strip_flags, output_binary)) + + self.configname = None + return result + + def _GetDebugPostbuilds(self, configname, output, output_binary): + """Returns a list of shell commands that contain the shell commands + neccessary to massage this target's debug information. These should be run + as postbuilds before the actual postbuilds run.""" + self.configname = configname + + # For static libraries, no dSYMs are created. + result = [] + if (self._Test('GCC_GENERATE_DEBUGGING_SYMBOLS', 'YES', default='YES') and + self._Test( + 'DEBUG_INFORMATION_FORMAT', 'dwarf-with-dsym', default='dwarf') and + self.spec['type'] != 'static_library'): + result.append('echo DSYMUTIL\\(%s\\)' % self.spec['target_name']) + result.append('dsymutil %s -o %s' % (output_binary, output + '.dSYM')) + + self.configname = None + return result + + def GetTargetPostbuilds(self, configname, output, output_binary): + """Returns a list of shell commands that contain the shell commands + to run as postbuilds for this target, before the actual postbuilds.""" + # dSYMs need to build before stripping happens. + return (self._GetDebugPostbuilds(configname, output, output_binary) + + self._GetStripPostbuilds(configname, output_binary)) + class MacPrefixHeader(object): """A class that helps with emulating Xcode's GCC_PREFIX_HEADER feature. If @@ -1204,6 +1291,15 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD self.type = spec['type'] self.toolset = spec['toolset'] + if self.type == 'settings': + # TODO: 'settings' is not actually part of gyp; it was + # accidentally introduced somehow into just the Linux build files. + # Remove this (or make it an error) once all the users are fixed. + print ("WARNING: %s uses invalid type 'settings'. " % self.target + + "Please fix the source gyp file to use type 'none'.") + print "See http://code.google.com/p/chromium/issues/detail?id=96629 ." + self.type = 'none' + # Bundles are directories with a certain subdirectory structure, instead of # just a single file. Bundle rules do not produce a binary but also package # resources into that directory. @@ -1446,12 +1542,20 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD for rule_source in rule.get('rule_sources', []): dirs = set() - rule_source_basename = os.path.basename(rule_source) + (rule_source_dirname, rule_source_basename) = os.path.split(rule_source) (rule_source_root, rule_source_ext) = \ os.path.splitext(rule_source_basename) - outputs = [self.ExpandInputRoot(out, rule_source_root) + outputs = [self.ExpandInputRoot(out, rule_source_root, + rule_source_dirname) for out in rule['outputs']] + + # If an output is just the file name, turn it into a path so + # FixupArgPath() will know to Absolutify() it. + outputs = map( + lambda x : os.path.dirname(x) and x or os.path.join('.', x), + outputs) + for out in outputs: dir = os.path.dirname(out) if dir: @@ -1486,7 +1590,8 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD self.WriteLn('all_deps += %s' % ' '.join(outputs)) self._num_outputs += len(outputs) - action = [self.ExpandInputRoot(ac, rule_source_root) + action = [self.ExpandInputRoot(ac, rule_source_root, + rule_source_dirname) for ac in rule['action']] mkdirs = '' if len(dirs) > 0: @@ -1789,9 +1894,6 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD """ assert not self.is_mac_bundle - if self.type == 'settings': - return '' # Doesn't have any output. - path = os.path.join('$(obj).' + self.toolset, self.path) if self.type == 'executable' or self._InstallImmediately(): path = '$(builddir)' @@ -1860,11 +1962,22 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD order_only = True, multiple_output_trick = False) - if self.type not in ('settings', 'none'): + has_target_postbuilds = False + if self.type != 'none': for configname in sorted(configs.keys()): config = configs[configname] if self.flavor == 'mac': ldflags = self.xcode_settings.GetLdflags(self, configname) + + # TARGET_POSTBUILDS_$(BUILDTYPE) is added to postbuilds later on. + target_postbuilds = self.xcode_settings.GetTargetPostbuilds( + configname, self.output, self.output_binary) + if target_postbuilds: + has_target_postbuilds = True + self.WriteLn('%s: TARGET_POSTBUILDS_%s := %s' % + (self.output, + configname, + gyp.common.EncodePOSIXShellList(target_postbuilds))) else: ldflags = config.get('ldflags', []) # Compute an rpath for this output if needed. @@ -1890,6 +2003,8 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD postbuilds = [] if self.flavor == 'mac': + if has_target_postbuilds: + postbuilds.append('$(TARGET_POSTBUILDS_$(BUILDTYPE))') # Postbuild actions. Like actions, but implicitly depend on the target's # output. for postbuild in spec.get('postbuilds', []): @@ -1901,14 +2016,40 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD # absolutified. Else, it's in the PATH (e.g. install_name_tool, ln). if os.path.sep in shell_list[0]: shell_list[0] = self.Absolutify(shell_list[0]) - postbuilds.append('%s' % gyp.common.EncodePOSIXShellList(shell_list)) + + # "script.sh" -> "./script.sh" + if not os.path.sep in shell_list[0]: + shell_list[0] = os.path.join('.', shell_list[0]) + postbuilds.append(gyp.common.EncodePOSIXShellList(shell_list)) + + if postbuilds: + # Write envvars for postbuilds. + extra_settings = {} + + # CHROMIUM_STRIP_SAVE_FILE is a chromium-specific hack. + # TODO(thakis): It would be nice to have some general mechanism instead. + strip_save_file = self.xcode_settings.GetPerTargetSetting( + 'CHROMIUM_STRIP_SAVE_FILE') + if strip_save_file: + strip_save_file = self.Absolutify(strip_save_file) + else: + # Explicitly clear this out, else a postbuild might pick up an export + # from an earlier target. + strip_save_file = '' + extra_settings['CHROMIUM_STRIP_SAVE_FILE'] = strip_save_file + + self.WriteXcodeEnv(self.output, spec, additional_settings=extra_settings) + + for i in xrange(len(postbuilds)): + if not postbuilds[i].startswith('$'): + postbuilds[i] = EscapeShellArgument(postbuilds[i]) + self.WriteLn('%s: builddir := $(abs_builddir)' % self.output) + self.WriteLn('%s: POSTBUILDS := %s' % (self.output, ' '.join(postbuilds))) # A bundle directory depends on its dependencies such as bundle resources # and bundle binary. When all dependencies have been built, the bundle # needs to be packaged. if self.is_mac_bundle: - self.WriteXcodeEnv(self.output, spec) # For postbuilds - # If the framework doesn't contain a binary, then nothing depends # on the actions -- make the framework depend on them directly too. self.WriteDependencyOnExtraOutputs(self.output, extra_outputs) @@ -1926,8 +2067,8 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD # Bundle postbuilds can depend on the whole bundle, so run them after # the bundle is packaged, not already after the bundle binary is done. - for postbuild in postbuilds: - self.WriteLn('\t@' + postbuild) + if postbuilds: + self.WriteLn('\t@$(call do_postbuilds)') postbuilds = [] # Don't write postbuilds for target's output. # Needed by test/mac/gyptest-rebuild.py. @@ -1945,11 +2086,6 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD 'on the bundle, not the binary (target \'%s\')' % self.target) assert 'product_dir' not in spec, ('Postbuilds do not work with ' 'custom product_dir') - self.WriteXcodeEnv(self.output_binary, spec) # For postbuilds - postbuilds = [EscapeShellArgument(p) for p in postbuilds] - self.WriteLn('%s: builddir := $(abs_builddir)' % self.output_binary) - self.WriteLn('%s: POSTBUILDS := %s' % ( - self.output_binary, ' '.join(postbuilds))) if self.type == 'executable': self.WriteLn( @@ -1987,9 +2123,6 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD # Write a stamp line. self.WriteDoCmd([self.output_binary], deps, 'touch', part_of_all, postbuilds=postbuilds) - elif self.type == 'settings': - # Only used for passing flags around. - pass else: print "WARNING: no output for", self.type, target @@ -2259,11 +2392,15 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD 'TARGET_BUILD_DIR' : built_products_dir, 'TEMP_DIR' : '$(TMPDIR)', } - if self.type in ('executable', 'shared_library'): + if self.type in ('executable', 'shared_library', 'loadable_module'): env['EXECUTABLE_NAME'] = os.path.basename(self.output_binary) if self.type in ( 'executable', 'static_library', 'shared_library', 'loadable_module'): env['EXECUTABLE_PATH'] = self.xcode_settings.GetExecutablePath() + mach_o_type = self.xcode_settings.GetMachOType() + if mach_o_type: + env['MACH_O_TYPE'] = mach_o_type + env['PRODUCT_TYPE'] = self.xcode_settings.GetProductType() if self.is_mac_bundle: env['CONTENTS_FOLDER_PATH'] = \ self.xcode_settings.GetBundleContentsFolderPath() @@ -2347,14 +2484,13 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD return arg - def ExpandInputRoot(self, template, expansion): - if '%(INPUT_ROOT)s' not in template: + def ExpandInputRoot(self, template, expansion, dirname): + if '%(INPUT_ROOT)s' not in template and '%(INPUT_DIRNAME)s' not in template: return template - path = template % { 'INPUT_ROOT': expansion } - if not os.path.dirname(path): - # If it's just the file name, turn it into a path so FixupArgPath() - # will know to Absolutify() it. - path = os.path.join('.', path) + path = template % { + 'INPUT_ROOT': expansion, + 'INPUT_DIRNAME': dirname, + } return path @@ -2440,31 +2576,17 @@ def RunSystemTests(flavor): 'LINK_flags': link_flags } -def CopyTool(flavor, out_path): - """Finds (mac|sun)_tool.gyp in the gyp directory and copies it to |out_path|.""" - prefix = { 'solaris': 'sun', 'mac': 'mac' }.get(flavor, None) - if not prefix: - return - - tool_path = os.path.join(out_path, 'gyp-%s-tool' % prefix) - if os.path.exists(tool_path): - os.remove(tool_path) - - # Slurp input file. +def CopyMacTool(out_path): + """Finds mac_tool.gyp in the gyp directory and copies it to |out_path|.""" source_path = os.path.join( - os.path.dirname(os.path.abspath(__file__)), '..', '%s_tool.py' % prefix) + os.path.dirname(os.path.abspath(__file__)), '..', 'mac_tool.py') source_file = open(source_path) source = source_file.readlines() source_file.close() - - # Add header and write it out. - tool_file = open(tool_path, 'w') - tool_file.write( + mactool_file = open(out_path, 'w') + mactool_file.write( ''.join([source[0], '# Generated by gyp. Do not edit.\n'] + source[1:])) - tool_file.close() - - # Make file executable. - os.chmod(tool_path, 0o755) + mactool_file.close() def GenerateOutput(target_list, target_dicts, data, params): @@ -2512,33 +2634,24 @@ def GenerateOutput(target_list, target_dicts, data, params): srcdir = gyp.common.RelativePath(srcdir, options.generator_output) srcdir_prefix = '$(srcdir)/' + flock_command= 'flock' header_params = { 'builddir': builddir_name, 'default_configuration': default_configuration, - 'flock': 'flock', + 'flock': flock_command, 'flock_index': 1, 'link_commands': LINK_COMMANDS_LINUX, - 'extra_commands': '', + 'mac_commands': '', 'srcdir': srcdir, } if flavor == 'mac': + flock_command = './gyp-mac-tool flock' header_params.update({ - 'flock': './gyp-mac-tool flock', + 'flock': flock_command, 'flock_index': 2, 'link_commands': LINK_COMMANDS_MAC, - 'extra_commands': SHARED_HEADER_MAC_COMMANDS, - }) - elif flavor == 'solaris': - header_params.update({ - 'flock': './gyp-sun-tool flock', - 'flock_index': 2, - 'extra_commands': SHARED_HEADER_SUN_COMMANDS, + 'mac_commands': SHARED_HEADER_MAC_COMMANDS, }) - elif flavor == 'freebsd': - header_params.update({ - 'flock': 'lockf', - }) - if flavor == 'android': header_params.update({ 'link_commands': LINK_COMMANDS_ANDROID, @@ -2552,7 +2665,7 @@ def GenerateOutput(target_list, target_dicts, data, params): if value[0] != '$': value = '$(abspath %s)' % value if key == 'LINK': - make_global_settings += '%s ?= $(FLOCK) %s\n' % (key, value) + make_global_settings += '%s ?= %s %s\n' % (flock_command, key, value) elif key in ['CC', 'CXX']: make_global_settings += ( 'ifneq (,$(filter $(origin %s), undefined default))\n' % key) @@ -2579,9 +2692,14 @@ def GenerateOutput(target_list, target_dicts, data, params): root_makefile.write('TOOLSET := %s\n' % toolset) WriteRootHeaderSuffixRules(root_makefile) - # Put platform tool next to the root Makefile. - dest_path = os.path.dirname(makefile_path) - CopyTool(flavor, dest_path) + # Put mac_tool next to the root Makefile. + if flavor == 'mac': + mactool_path = os.path.join(os.path.dirname(makefile_path), 'gyp-mac-tool') + if os.path.exists(mactool_path): + os.remove(mactool_path) + CopyMacTool(mactool_path) + # Make file executable. + os.chmod(mactool_path, 0755) # Find the list of targets that derive from the gyp file(s) being built. needed_targets = set() diff --git a/tools/gyp/pylib/gyp/generator/msvs.py b/tools/gyp/pylib/gyp/generator/msvs.py index 38ea3a271f..0efea70470 100644 --- a/tools/gyp/pylib/gyp/generator/msvs.py +++ b/tools/gyp/pylib/gyp/generator/msvs.py @@ -58,6 +58,7 @@ generator_default_variables = { # TODO(jeanluc) I had: 'LIB_DIR': '$(OutDir)lib', 'LIB_DIR': '$(OutDir)/lib', 'RULE_INPUT_ROOT': '$(InputName)', + 'RULE_INPUT_DIRNAME': '$(InputDir)', 'RULE_INPUT_EXT': '$(InputExt)', 'RULE_INPUT_NAME': '$(InputFileName)', 'RULE_INPUT_PATH': '$(InputPath)', @@ -254,6 +255,16 @@ def _ConfigFullName(config_name, config_data): def _BuildCommandLineForRuleRaw(spec, cmd, cygwin_shell, has_input_path, quote_cmd): + + if [x for x in cmd if '$(InputDir)' in x]: + input_dir_preamble = ( + 'set INPUTDIR=$(InputDir)\n' + 'set INPUTDIR=%INPUTDIR:$(ProjectDir)=%\n' + 'set INPUTDIR=%INPUTDIR:~0,-1%\n' + ) + else: + input_dir_preamble = '' + if cygwin_shell: # Find path to cygwin. cygwin_dir = _FixPath(spec.get('msvs_cygwin_dirs', ['.'])[0]) @@ -263,6 +274,8 @@ def _BuildCommandLineForRuleRaw(spec, cmd, cygwin_shell, has_input_path, '`cygpath -m "${INTDIR}"`') for i in direct_cmd] direct_cmd = [i.replace('$(OutDir)', '`cygpath -m "${OUTDIR}"`') for i in direct_cmd] + direct_cmd = [i.replace('$(InputDir)', + '`cygpath -m "${INPUTDIR}"`') for i in direct_cmd] if has_input_path: direct_cmd = [i.replace('$(InputPath)', '`cygpath -m "${INPUTPATH}"`') @@ -286,7 +299,7 @@ def _BuildCommandLineForRuleRaw(spec, cmd, cygwin_shell, has_input_path, cmd += 'bash -c "%(cmd)s"' cmd = cmd % {'cygwin_dir': cygwin_dir, 'cmd': direct_cmd} - return cmd + return input_dir_preamble + cmd else: # Convert cat --> type to mimic unix. if cmd[0] == 'cat': @@ -296,13 +309,14 @@ def _BuildCommandLineForRuleRaw(spec, cmd, cygwin_shell, has_input_path, # Fix the paths # If the argument starts with a slash, it's probably a command line switch arguments = [i.startswith('/') and i or _FixPath(i) for i in cmd[1:]] + arguments = [i.replace('$(InputDir)','%INPUTDIR%') for i in arguments] if quote_cmd: # Support a mode for using cmd directly. # Convert any paths to native form (first element is used directly). # TODO(quote): regularize quoting path names throughout the module arguments = ['"%s"' % i for i in arguments] # Collapse into a single command. - return ' '.join(command + arguments) + return input_dir_preamble + ' '.join(command + arguments) def _BuildCommandLineForRule(spec, rule, has_input_path): @@ -427,6 +441,7 @@ def _RuleExpandPath(path, input_file): """ path = path.replace('$(InputName)', os.path.splitext(os.path.split(input_file)[1])[0]) + path = path.replace('$(InputDir)', os.path.dirname(input_file)) path = path.replace('$(InputExt)', os.path.splitext(os.path.split(input_file)[1])[1]) path = path.replace('$(InputFileName)', os.path.split(input_file)[1]) @@ -547,7 +562,8 @@ def _GenerateExternalRules(rules, output_dir, spec, # Write out all: target, including mkdir for each output directory. mk_file.write('all: %s\n' % ' '.join(first_outputs_cyg)) for od in all_output_dirs: - mk_file.write('\tmkdir -p `cygpath -u "%s"`\n' % od) + if od: + mk_file.write('\tmkdir -p `cygpath -u "%s"`\n' % od) mk_file.write('\n') # Define how each output is generated. for rule in rules: @@ -855,30 +871,29 @@ def _GenerateMSVSProject(project, options, version): project.guid, platforms) # Get directory project file is in. - gyp_dir = os.path.split(project.path)[0] - gyp_file = posixpath.split(project.build_file)[1] - gyp_path = _NormalizedSource(gyp_file) - relative_path_of_gyp_file = gyp.common.RelativePath(gyp_path, gyp_dir) + project_dir = os.path.split(project.path)[0] + gyp_path = _NormalizedSource(project.build_file) + relative_path_of_gyp_file = gyp.common.RelativePath(gyp_path, project_dir) config_type = _GetMSVSConfigurationType(spec, project.build_file) for config_name, config in spec['configurations'].iteritems(): _AddConfigurationToMSVSProject(p, spec, config_type, config_name, config) # Prepare list of sources and excluded sources. - sources, excluded_sources = _PrepareListOfSources(spec, - relative_path_of_gyp_file) + gyp_file = os.path.split(project.build_file)[1] + sources, excluded_sources = _PrepareListOfSources(spec, gyp_file) # Add rules. actions_to_add = {} - _GenerateRulesForMSVS(p, gyp_dir, options, spec, + _GenerateRulesForMSVS(p, project_dir, options, spec, sources, excluded_sources, actions_to_add) sources, excluded_sources, excluded_idl = ( _AdjustSourcesAndConvertToFilterHierarchy( - spec, options, gyp_dir, sources, excluded_sources)) + spec, options, project_dir, sources, excluded_sources)) # Add in files. - _VerifySourcesExist(sources, gyp_dir) + _VerifySourcesExist(sources, project_dir) p.AddFiles(sources) _AddToolFilesToMSVS(p, spec) @@ -1013,7 +1028,7 @@ def _AddConfigurationToMSVSProject(p, spec, config_type, config_name, config): defines) # Change program database directory to prevent collisions. _ToolAppend(tools, 'VCCLCompilerTool', 'ProgramDataBaseFileName', - '$(IntDir)\\$(ProjectName)\\vc80.pdb') + '$(IntDir)\\$(ProjectName)\\vc80.pdb', only_if_unset=True) # Add disabled warnings. _ToolAppend(tools, 'VCCLCompilerTool', 'DisableSpecificWarnings', disabled_warnings) @@ -1236,7 +1251,7 @@ def _AddNormalizedSources(sources_set, sources_array): sources_set.update(set(sources)) -def _PrepareListOfSources(spec, relative_path_of_gyp_file): +def _PrepareListOfSources(spec, gyp_file): """Prepare list of sources and excluded sources. Besides the sources specified directly in the spec, adds the gyp file so @@ -1246,15 +1261,16 @@ def _PrepareListOfSources(spec, relative_path_of_gyp_file): Arguments: spec: The target dictionary containing the properties of the target. - relative_path_of_gyp_file: The relative path of the gyp file. + gyp_file: The name of the gyp file. Returns: - A pair of (list of sources, list of excluded sources) + A pair of (list of sources, list of excluded sources). + The sources will be relative to the gyp file. """ sources = set() _AddNormalizedSources(sources, spec.get('sources', [])) excluded_sources = set() # Add in the gyp file. - sources.add(relative_path_of_gyp_file) + sources.add(gyp_file) # Add in 'action' inputs and outputs. for a in spec.get('actions', []): @@ -1489,7 +1505,9 @@ def _GetCopies(spec): def _GetPathDict(root, path): - if not path: + # |path| will eventually be empty (in the recursive calls) if it was initially + # relative; otherwise it will eventually end up as '\', 'D:\', etc. + if not path or path.endswith(os.sep): return root parent, folder = os.path.split(path) parent_dict = _GetPathDict(root, parent) @@ -2642,7 +2660,8 @@ def _VerifySourcesExist(sources, root_dir): if '$' not in source: full_path = os.path.join(root_dir, source) if not os.path.exists(full_path): - print 'Error: Missing input file ' + full_path + print 'Warning: Missing input file ' + full_path + ' pwd=' +\ + os.getcwd() def _GetMSBuildSources(spec, sources, exclusions, extension_to_rule_name, @@ -2685,15 +2704,16 @@ def _AddSources2(spec, sources, exclusions, grouped_sources, # Add precompile if needed for config_name, configuration in spec['configurations'].iteritems(): precompiled_source = configuration.get('msvs_precompiled_source', '') - precompiled_source = _FixPath(precompiled_source) - if not extensions_excluded_from_precompile: - # If the precompiled header is generated by a C source, we must - # not try to use it for C++ sources, and vice versa. - basename, extension = os.path.splitext(precompiled_source) - if extension == '.c': - extensions_excluded_from_precompile = ['.cc', '.cpp', '.cxx'] - else: - extensions_excluded_from_precompile = ['.c'] + if precompiled_source != '': + precompiled_source = _FixPath(precompiled_source) + if not extensions_excluded_from_precompile: + # If the precompiled header is generated by a C source, we must + # not try to use it for C++ sources, and vice versa. + basename, extension = os.path.splitext(precompiled_source) + if extension == '.c': + extensions_excluded_from_precompile = ['.cc', '.cpp', '.cxx'] + else: + extensions_excluded_from_precompile = ['.c'] if precompiled_source == source: condition = _GetConfigurationCondition(config_name, configuration) @@ -2736,30 +2756,28 @@ def _GetMSBuildProjectReferences(project): def _GenerateMSBuildProject(project, options, version): spec = project.spec configurations = spec['configurations'] - gyp_dir, gyp_file_name = os.path.split(project.path) + project_dir, project_file_name = os.path.split(project.path) msbuildproj_dir = os.path.dirname(project.path) if msbuildproj_dir and not os.path.exists(msbuildproj_dir): os.makedirs(msbuildproj_dir) # Prepare list of sources and excluded sources. - gyp_dir = os.path.split(project.path)[0] - gyp_file = posixpath.split(project.build_file)[1] - gyp_path = _NormalizedSource(gyp_file) - relative_path_of_gyp_file = gyp.common.RelativePath(gyp_path, gyp_dir) + gyp_path = _NormalizedSource(project.build_file) + relative_path_of_gyp_file = gyp.common.RelativePath(gyp_path, project_dir) - sources, excluded_sources = _PrepareListOfSources(spec, - relative_path_of_gyp_file) + gyp_file = os.path.split(project.build_file)[1] + sources, excluded_sources = _PrepareListOfSources(spec, gyp_file) # Add rules. actions_to_add = {} props_files_of_rules = set() targets_files_of_rules = set() extension_to_rule_name = {} - _GenerateRulesForMSBuild(gyp_dir, options, spec, + _GenerateRulesForMSBuild(project_dir, options, spec, sources, excluded_sources, props_files_of_rules, targets_files_of_rules, actions_to_add, extension_to_rule_name) sources, excluded_sources, excluded_idl = ( _AdjustSourcesAndConvertToFilterHierarchy(spec, options, - gyp_dir, sources, + project_dir, sources, excluded_sources)) _AddActions(actions_to_add, spec, project.build_file) _AddCopies(actions_to_add, spec) @@ -2775,7 +2793,7 @@ def _GenerateMSBuildProject(project, options, version): _GenerateMSBuildFiltersFile(project.path + '.filters', sources, extension_to_rule_name) - _VerifySourcesExist(sources, gyp_dir) + _VerifySourcesExist(sources, project_dir) for (_, configuration) in configurations.iteritems(): _FinalizeMSBuildSettings(spec, configuration) @@ -2798,7 +2816,7 @@ def _GenerateMSBuildProject(project, options, version): }] content += _GetMSBuildProjectConfigurations(configurations) - content += _GetMSBuildGlobalProperties(spec, project.guid, gyp_file_name) + content += _GetMSBuildGlobalProperties(spec, project.guid, project_file_name) content += import_default_section content += _GetMSBuildConfigurationDetails(spec, project.build_file) content += import_cpp_props_section diff --git a/tools/gyp/pylib/gyp/generator/ninja.py b/tools/gyp/pylib/gyp/generator/ninja.py index 4e5a12f100..f044f3746c 100644 --- a/tools/gyp/pylib/gyp/generator/ninja.py +++ b/tools/gyp/pylib/gyp/generator/ninja.py @@ -42,6 +42,7 @@ generator_default_variables = { # We generate definitions for these variables on the fly when processing a # rule. 'RULE_INPUT_ROOT': '${root}', + 'RULE_INPUT_DIRNAME': '${dirname}', 'RULE_INPUT_PATH': '${source}', 'RULE_INPUT_EXT': '${ext}', 'RULE_INPUT_NAME': '${name}', @@ -212,13 +213,17 @@ class NinjaWriter: Returns the path to the build output, or None.""" + self.name = spec['target_name'] + self.toolset = spec['toolset'] + if spec['type'] == 'settings': # TODO: 'settings' is not actually part of gyp; it was # accidentally introduced somehow into just the Linux build files. - return None - - self.name = spec['target_name'] - self.toolset = spec['toolset'] + # Remove this (or make it an error) once all the users are fixed. + print ("WARNING: %s uses invalid type 'settings'. " % self.name + + "Please fix the source gyp file to use type 'none'.") + print "See http://code.google.com/p/chromium/issues/detail?id=96629 ." + spec['type'] = 'none' # Compute predepends for all rules. # prebuild is the dependencies this target depends on before @@ -331,7 +336,7 @@ class NinjaWriter: # Rules can potentially make use of some special variables which # must vary per source file. # Compute the list of variables we'll need to provide. - special_locals = ('source', 'root', 'ext', 'name') + special_locals = ('source', 'root', 'dirname', 'ext', 'name') needed_variables = set(['source']) for argument in args: for var in special_locals: @@ -340,14 +345,15 @@ class NinjaWriter: # For each source file, write an edge that generates all the outputs. for source in rule.get('rule_sources', []): - basename = os.path.basename(source) + dirname, basename = os.path.split(source) root, ext = os.path.splitext(basename) # Gather the list of outputs, expanding $vars if possible. outputs = [] for output in rule['outputs']: outputs.append(output.replace( - generator_default_variables['RULE_INPUT_ROOT'], root)) + generator_default_variables['RULE_INPUT_ROOT'], root).replace( + generator_default_variables['RULE_INPUT_DIRNAME'], dirname)) if int(rule.get('process_outputs_as_sources', False)): extra_sources += outputs @@ -356,6 +362,8 @@ class NinjaWriter: for var in needed_variables: if var == 'root': extra_bindings.append(('root', root)) + elif var == 'dirname': + extra_bindings.append(('dirname', dirname)) elif var == 'source': # '$source' is a parameter to the rule action, which means # it shouldn't be converted to a Ninja path. But we don't @@ -466,7 +474,7 @@ class NinjaWriter: command_map = { 'executable': 'link', 'static_library': 'alink', - 'loadable_module': 'solink', + 'loadable_module': 'solink_module', 'shared_library': 'solink', 'none': 'stamp', } @@ -481,7 +489,7 @@ class NinjaWriter: spec.get('libraries', [])))) extra_bindings = [] - if command == 'solink': + if command in ('solink', 'solink_module'): extra_bindings.append(('soname', os.path.split(output)[1])) self.ninja.build(output, command, final_deps, @@ -528,8 +536,6 @@ class NinjaWriter: return '%s%s%s' % (prefix, target, extension) elif spec['type'] == 'none': return '%s.stamp' % target - elif spec['type'] == 'settings': - return None else: raise 'Unhandled output type', spec['type'] @@ -655,6 +661,11 @@ def GenerateOutput(target_list, target_dicts, data, params): 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', diff --git a/tools/gyp/pylib/gyp/generator/scons.py b/tools/gyp/pylib/gyp/generator/scons.py index 073f9e047d..623c6d5a9f 100644 --- a/tools/gyp/pylib/gyp/generator/scons.py +++ b/tools/gyp/pylib/gyp/generator/scons.py @@ -1,6 +1,6 @@ #!/usr/bin/python -# Copyright (c) 2009 Google Inc. All rights reserved. +# Copyright (c) 2011 Google Inc. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -30,6 +30,7 @@ generator_default_variables = { 'SHARED_LIB_DIR': '$LIB_DIR', 'LIB_DIR': '$LIB_DIR', 'RULE_INPUT_ROOT': '${SOURCE.filebase}', + 'RULE_INPUT_DIRNAME': '${SOURCE.dir}', 'RULE_INPUT_EXT': '${SOURCE.suffix}', 'RULE_INPUT_NAME': '${SOURCE.file}', 'RULE_INPUT_PATH': '${SOURCE.abspath}', diff --git a/tools/gyp/pylib/gyp/generator/xcode.py b/tools/gyp/pylib/gyp/generator/xcode.py index 0429b8006c..066bb9f02f 100644 --- a/tools/gyp/pylib/gyp/generator/xcode.py +++ b/tools/gyp/pylib/gyp/generator/xcode.py @@ -53,6 +53,7 @@ generator_default_variables = { 'RULE_INPUT_EXT': '$(INPUT_FILE_SUFFIX)', 'RULE_INPUT_NAME': '$(INPUT_FILE_NAME)', 'RULE_INPUT_PATH': '$(INPUT_FILE_PATH)', + 'RULE_INPUT_DIRNAME': '$(INPUT_FILE_DIRNAME)', 'SHARED_INTERMEDIATE_DIR': '$(%s)' % _shared_intermediate_var, 'CONFIGURATION_NAME': '$(CONFIGURATION)', } @@ -865,7 +866,8 @@ def GenerateOutput(target_list, target_dicts, data, params): actions = [] for rule_source in rule.get('rule_sources', []): - rule_source_basename = posixpath.basename(rule_source) + rule_source_dirname, rule_source_basename = \ + posixpath.split(rule_source) (rule_source_root, rule_source_ext) = \ posixpath.splitext(rule_source_basename) @@ -877,6 +879,7 @@ def GenerateOutput(target_list, target_dicts, data, params): 'INPUT_FILE_SUFFIX': rule_source_ext, 'INPUT_FILE_NAME': rule_source_basename, 'INPUT_FILE_PATH': rule_source, + 'INPUT_FILE_DIRNAME': rule_source_dirname, } concrete_outputs_for_this_rule_source = [] diff --git a/tools/gyp/pylib/gyp/mac_tool.py b/tools/gyp/pylib/gyp/mac_tool.py index b3333c7c4d..b64ea986ae 100644 --- a/tools/gyp/pylib/gyp/mac_tool.py +++ b/tools/gyp/pylib/gyp/mac_tool.py @@ -73,12 +73,14 @@ class MacTool(object): if not plist: return + # Only create PkgInfo for executable types. + package_type = plist['CFBundlePackageType'] + if package_type != 'APPL': + return + # The format of PkgInfo is eight characters, representing the bundle type - # and bundle signature, each four characters. If either is missing, four + # and bundle signature, each four characters. If that is missing, four # '?' characters are used instead. - package_type = plist['CFBundlePackageType'] - if len(package_type) != 4: - package_type = '?' * 4 signature_code = plist['CFBundleSignature'] if len(signature_code) != 4: signature_code = '?' * 4