summaryrefslogtreecommitdiff
path: root/tools/gyp/pylib/gyp/generator/make.py
diff options
context:
space:
mode:
authorRyan Dahl <ry@tinyclouds.org>2011-08-22 17:08:16 -0700
committerRyan Dahl <ry@tinyclouds.org>2011-08-22 17:09:57 -0700
commit80dd8182907314ae99f5572798c86176e2086c47 (patch)
tree3dddb582141ef135a93789a288c25eed543f32f9 /tools/gyp/pylib/gyp/generator/make.py
parentc2ae39b8d60407261d1963461087798458b31358 (diff)
downloadandroid-node-v8-80dd8182907314ae99f5572798c86176e2086c47.tar.gz
android-node-v8-80dd8182907314ae99f5572798c86176e2086c47.tar.bz2
android-node-v8-80dd8182907314ae99f5572798c86176e2086c47.zip
Upgrade GYP to r1010
Diffstat (limited to 'tools/gyp/pylib/gyp/generator/make.py')
-rw-r--r--tools/gyp/pylib/gyp/generator/make.py260
1 files changed, 183 insertions, 77 deletions
diff --git a/tools/gyp/pylib/gyp/generator/make.py b/tools/gyp/pylib/gyp/generator/make.py
index 5ebc5c96c7..b8914785bf 100644
--- a/tools/gyp/pylib/gyp/generator/make.py
+++ b/tools/gyp/pylib/gyp/generator/make.py
@@ -29,7 +29,6 @@ import gyp.system_test
import os.path
import os
import sys
-import stat
# Debugging-related imports -- remove me once we're solid.
import code
@@ -374,6 +373,7 @@ prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?))
# 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.
+# Third argument, if non-zero, makes it do POSTBUILDS processing.
# Note: We intentionally do NOT call dirx for depfile, since it contains """ + \
SPACE_REPLACEMENT + """ for
# spaces already and dirx strips the """ + SPACE_REPLACEMENT + \
@@ -389,6 +389,9 @@ $(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
+ )
)
endef
@@ -422,12 +425,13 @@ quiet_cmd_pch_mm = CXX($(TOOLSET)) $@
cmd_pch_mm = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $<
# gyp-mac-tool is written next to the root Makefile by gyp.
-# Use #(3) for the command, since $(2) is used as flag by do_cmd already.
-quiet_cmd_mac_tool = MACTOOL $(3) $<
-cmd_mac_tool = ./gyp-mac-tool $(3) $< "$@"
+# Use $(4) for the command, since $(2) and $(3) are used as flag by do_cmd
+# already.
+quiet_cmd_mac_tool = MACTOOL $(4) $<
+cmd_mac_tool = ./gyp-mac-tool $(4) $< "$@"
quiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@
-cmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(3)
+cmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(4)
"""
@@ -676,9 +680,9 @@ class XcodeSettings(object):
return os.path.join(self.GetBundleContentsFolderPath(),
'Resources', 'Info.plist')
- def GetBundleBinaryPath(self):
- """Returns the directory name of the bundle represented by this target. E.g.
- Chromium.app/Contents/MacOS/Chromium. Only valid for bundles."""
+ 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'):
path = self.GetBundleContentsFolderPath()
@@ -687,6 +691,53 @@ class XcodeSettings(object):
return os.path.join(path, self.spec.get('product_name',
self.spec['target_name']))
+ def _GetStandaloneExecutableSuffix(self):
+ if 'product_extension' in self.spec:
+ return '.' + self.spec['product_extension']
+ return {
+ 'executable': '',
+ 'static_library': '.a',
+ 'shared_library': '.dylib',
+ 'loadable_module': '.so',
+ }[self.spec['type']]
+
+ def _GetStandaloneExecutablePrefix(self):
+ return self.spec.get('product_prefix', {
+ 'executable': '',
+ 'static_library': 'lib',
+ 'shared_library': 'lib',
+ # Non-bundled loadable_modules are called foo.so for some reason
+ # (that is, .so and no prefix) with the xcode build -- match that.
+ 'loadable_module': '',
+ }[self.spec['type']])
+
+ def _GetStandaloneBinaryPath(self):
+ """Returns the name of the non-bundle binary represented by this target.
+ E.g. hello_world. Only valid for non-bundles."""
+ assert not self._IsBundle()
+ assert self.spec['type'] in (
+ 'executable', 'shared_library', 'static_library', 'loadable_module')
+ target = self.spec['target_name']
+ if self.spec['type'] == 'static_library':
+ if target[:3] == 'lib':
+ target = target[3:]
+ elif self.spec['type'] in ('loadable_module', 'shared_library'):
+ if target[:3] == 'lib':
+ target = target[3:]
+
+ target_prefix = self._GetStandaloneExecutablePrefix()
+ target = self.spec.get('product_name', target)
+ target_ext = self._GetStandaloneExecutableSuffix()
+ return target_prefix + target + target_ext
+
+ def GetExecutablePath(self):
+ """Returns the directory name of the bundle represented by this target. E.g.
+ Chromium.app/Contents/MacOS/Chromium."""
+ if self._IsBundle():
+ return self._GetBundleBinaryPath()
+ else:
+ return self._GetStandaloneBinaryPath()
+
def GetCflags(self, configname):
"""Returns flags that need to be added to .c, .cc, .m, and .mm
compilations."""
@@ -838,6 +889,10 @@ class XcodeSettings(object):
ldflags, 'DYLIB_COMPATIBILITY_VERSION', '-compatibility_version %s')
self._Appendf(
ldflags, 'DYLIB_CURRENT_VERSION', '-current_version %s')
+ self._Appendf(
+ ldflags, 'MACOSX_DEPLOYMENT_TARGET', '-mmacosx-version-min=%s')
+ self._Appendf(
+ ldflags, 'SDKROOT', '-isysroot /Developer/SDKs/%s.sdk')
for library_path in self._Settings().get('LIBRARY_SEARCH_PATHS', []):
ldflags.append('-L' + library_path)
@@ -855,37 +910,47 @@ class XcodeSettings(object):
ldflags.append('-L' + generator_default_variables['PRODUCT_DIR'])
install_name = self.GetPerTargetSetting('LD_DYLIB_INSTALL_NAME')
+ install_base = self.GetPerTargetSetting('DYLIB_INSTALL_NAME_BASE')
+ default_install_name = \
+ '$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)'
+ if not install_name and install_base:
+ install_name = default_install_name
+
if install_name:
# Hardcode support for the variables used in chromium for now, to unblock
# people using the make build.
if '$' in install_name:
- assert install_name == ('$(DYLIB_INSTALL_NAME_BASE:standardizepath)/'
- '$(WRAPPER_NAME)/$(PRODUCT_NAME)'), (
+ assert install_name in ('$(DYLIB_INSTALL_NAME_BASE:standardizepath)/'
+ '$(WRAPPER_NAME)/$(PRODUCT_NAME)', default_install_name), (
'Variables in LD_DYLIB_INSTALL_NAME are not generally supported yet'
' in target \'%s\' (got \'%s\')' %
(self.spec['target_name'], install_name))
- install_base = self.GetPerTargetSetting('DYLIB_INSTALL_NAME_BASE')
# I'm not quite sure what :standardizepath does. Just call normpath(),
- # but don't let @executable_path/../foo collapse to foo
- prefix, rest = '', install_base
- if install_base.startswith('@'):
- prefix, rest = install_base.split('/', 1)
- rest = os.path.normpath(rest) # :standardizepath
- install_base = os.path.join(prefix, rest)
+ # but don't let @executable_path/../foo collapse to foo.
+ if '/' in install_base:
+ prefix, rest = '', install_base
+ if install_base.startswith('@'):
+ prefix, rest = install_base.split('/', 1)
+ rest = os.path.normpath(rest) # :standardizepath
+ install_base = os.path.join(prefix, rest)
install_name = install_name.replace(
'$(DYLIB_INSTALL_NAME_BASE:standardizepath)', install_base)
+ if self._IsBundle():
+ # These are only valid for bundles, hence the |if|.
+ install_name = install_name.replace(
+ '$(WRAPPER_NAME)', self.GetWrapperName())
+ install_name = install_name.replace(
+ '$(PRODUCT_NAME)', self.GetProductName())
+ else:
+ assert '$(WRAPPER_NAME)' not in install_name
+ assert '$(PRODUCT_NAME)' not in install_name
+
install_name = install_name.replace(
- '$(WRAPPER_NAME)', self.GetWrapperName())
- install_name = install_name.replace(
- '$(PRODUCT_NAME)', self.GetProductName())
+ '$(EXECUTABLE_PATH)', self.GetExecutablePath())
install_name = QuoteSpaces(install_name)
ldflags.append('-install_name ' + install_name)
- elif self.GetPerTargetSetting('DYLIB_INSTALL_NAME_BASE'):
- # LD_DYLIB_INSTALL_NAME defaults to
- # $(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH).
- print 'Warning: DYLIB_INSTALL_NAME_BASE is not fully implemented.'
self.configname = None
return ldflags
@@ -1453,7 +1518,7 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
if output.endswith('.xib'):
output = output[0:-3] + 'nib'
- self.WriteDoCmd([output], [path], 'mac_tool,,copy-bundle-resource',
+ self.WriteDoCmd([output], [path], 'mac_tool,,,copy-bundle-resource',
part_of_all=True)
bundle_deps.append(output)
@@ -1467,7 +1532,7 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
dest_plist = os.path.join(path, self.xcode_settings.GetBundlePlistPath())
dest_plist = QuoteSpaces(dest_plist)
self.WriteXcodeEnv(dest_plist, spec) # plists can contain envvars.
- self.WriteDoCmd([dest_plist], [info_plist], 'mac_tool,,copy-info-plist',
+ self.WriteDoCmd([dest_plist], [info_plist], 'mac_tool,,,copy-info-plist',
part_of_all=True)
bundle_deps.append(dest_plist)
@@ -1593,18 +1658,21 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
self.WriteLn()
- def ComputeOutput(self, spec):
- """Return the 'output' (full output path) of a gyp spec.
+ def ComputeOutputBasename(self, spec):
+ """Return the 'output basename' of a gyp spec.
E.g., the loadable module 'foobar' in directory 'baz' will produce
- '$(obj)/baz/libfoobar.so'
+ 'libfoobar.so'
"""
assert not self.is_mac_bundle
+ if self.flavor == 'mac' and self.type in (
+ 'static_library', 'executable', 'shared_library', 'loadable_module'):
+ return self.xcode_settings.GetExecutablePath()
+
target = spec['target_name']
target_prefix = ''
target_ext = ''
- path = os.path.join('$(obj).' + self.toolset, self.path)
if self.type == 'static_library':
if target[:3] == 'lib':
target = target[3:]
@@ -1615,31 +1683,37 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
target = target[3:]
target_prefix = 'lib'
target_ext = '.so'
- if self.flavor == 'mac':
- if self.type == 'shared_library':
- target_ext = '.dylib'
- else:
- # Non-bundled loadable_modules are called foo.so for some reason
- # (that is, .so and no prefix) with the xcode build -- match that.
- target_prefix = ''
elif self.type == 'none':
target = '%s.stamp' % target
- elif self.type == 'settings':
- return '' # Doesn't have any output.
- elif self.type == 'executable':
- path = os.path.join('$(builddir)')
- else:
+ elif self.type != 'executable':
print ("ERROR: What output file should be generated?",
"type", self.type, "target", target)
- path = spec.get('product_dir', path)
target_prefix = spec.get('product_prefix', target_prefix)
target = spec.get('product_name', target)
product_ext = spec.get('product_extension')
if product_ext:
target_ext = '.' + product_ext
- return os.path.join(path, target_prefix + target + target_ext)
+ return target_prefix + target + target_ext
+
+
+ def ComputeOutput(self, spec):
+ """Return the 'output' (full output path) of a gyp spec.
+
+ E.g., the loadable module 'foobar' in directory 'baz' will produce
+ '$(obj)/baz/libfoobar.so'
+ """
+ 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':
+ path = '$(builddir)'
+ path = spec.get('product_dir', path)
+ return os.path.join(path, self.ComputeOutputBasename(spec))
def ComputeMacBundleOutput(self, spec):
@@ -1652,7 +1726,7 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
def ComputeMacBundleBinaryOutput(self, spec):
"""Return the 'output' (full output path) to the binary in a bundle."""
path = generator_default_variables['PRODUCT_DIR']
- return os.path.join(path, self.xcode_settings.GetBundleBinaryPath())
+ return os.path.join(path, self.xcode_settings.GetExecutablePath())
def ComputeDeps(self, spec):
@@ -1731,6 +1805,21 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
'%s: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))' % self.output_binary)
self.WriteLn('%s: LIBS := $(LIBS)' % self.output_binary)
+ postbuilds = []
+ if self.flavor == 'mac':
+ # Postbuild actions. Like actions, but implicitly depend on the target's
+ # output.
+ for postbuild in spec.get('postbuilds', []):
+ postbuilds.append('echo POSTBUILD\\(%s\\) %s' % (
+ self.target, postbuild['postbuild_name']))
+ shell_list = postbuild['action']
+ # The first element is the command. If it's a relative path, it's
+ # a script in the source tree relative to the gyp file and needs to be
+ # 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))
+
# 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.
@@ -1749,22 +1838,14 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
# After the framework is built, package it. Needs to happen before
# postbuilds, since postbuilds depend on this.
if self.type in ('shared_library', 'loadable_module'):
- self.WriteLn('\t@$(call do_cmd,mac_package_framework,0,%s)' %
+ self.WriteLn('\t@$(call do_cmd,mac_package_framework,0,0,%s)' %
self.xcode_settings.GetFrameworkVersion())
- # Postbuild actions. Like actions, but implicitly depend on the output
- # framework.
- for postbuild in spec.get('postbuilds', []):
- self.WriteLn('\t@echo POSTBUILD %s' % postbuild['postbuild_name'])
- shell_list = postbuild['action']
- # The first element is the command. If it's a relative path, it's
- # a script in the source tree relative to the gyp file and needs to be
- # 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])
- # TODO: Honor V=1 etc. Not using do_cmd because since this is part of
- # the framework rule, there's no need for .d file processing here.
- self.WriteLn('\t@%s' % gyp.common.EncodePOSIXShellList(shell_list))
+ # 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)
+ postbuilds = [] # Don't write postbuilds for target's output.
# Needed by test/mac/gyptest-rebuild.py.
self.WriteLn('\t@true # No-op, used by tests')
@@ -1775,32 +1856,43 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
# on every build (expensive, especially with postbuilds), expliclity
# update the time on the framework directory.
self.WriteLn('\t@touch -c %s' % self.output)
- elif 'postbuilds' in spec:
- print ("Warning: 'postbuild' support for non-bundles "
- "isn't implemented yet (target '%s)'." % self.target)
+
+ if postbuilds:
+ assert not self.is_mac_bundle, ('Postbuilds for bundles should be done '
+ 'on the bundle, not the binary (target \'%s\')' % self.target)
+ 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(
'%s: LD_INPUTS := %s' % (self.output_binary, ' '.join(link_deps)))
- self.WriteDoCmd([self.output_binary], link_deps, 'link', part_of_all)
+ self.WriteDoCmd([self.output_binary], link_deps, 'link', part_of_all,
+ postbuilds=postbuilds)
elif self.type == 'static_library':
for link_dep in link_deps:
assert ' ' not in link_dep, (
"Spaces in alink input filenames not supported (%s)" % link_dep)
- self.WriteDoCmd([self.output_binary], link_deps, 'alink', part_of_all)
+ self.WriteDoCmd([self.output_binary], link_deps, 'alink', part_of_all,
+ postbuilds=postbuilds)
elif self.type == 'shared_library':
self.WriteLn(
'%s: LD_INPUTS := %s' % (self.output_binary, ' '.join(link_deps)))
- self.WriteDoCmd([self.output_binary], link_deps, 'solink', part_of_all)
+ self.WriteDoCmd([self.output_binary], link_deps, 'solink', part_of_all,
+ postbuilds=postbuilds)
elif self.type == 'loadable_module':
for link_dep in link_deps:
assert ' ' not in link_dep, (
"Spaces in module input filenames not supported (%s)" % link_dep)
self.WriteDoCmd(
- [self.output_binary], link_deps, 'solink_module', part_of_all)
+ [self.output_binary], link_deps, 'solink_module', part_of_all,
+ postbuilds=postbuilds)
elif self.type == 'none':
# Write a stamp line.
- self.WriteDoCmd([self.output_binary], deps, 'touch', part_of_all)
+ self.WriteDoCmd([self.output_binary], deps, 'touch', part_of_all,
+ postbuilds=postbuilds)
elif self.type == 'settings':
# Only used for passing flags around.
pass
@@ -1867,14 +1959,19 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
self.fp.write("\n\n")
- def WriteDoCmd(self, outputs, inputs, command, part_of_all, comment=None):
+ def WriteDoCmd(self, outputs, inputs, command, part_of_all, comment=None,
+ postbuilds=False):
"""Write a Makefile rule that uses do_cmd.
This makes the outputs dependent on the command line that was run,
as well as support the V= make command line flag.
"""
+ suffix = ''
+ if postbuilds:
+ assert ',' not in command
+ suffix = ',,1' # Tell do_cmd to honor $POSTBUILDS
self.WriteMakeRule(outputs, inputs,
- actions = ['$(call do_cmd,%s)' % command],
+ actions = ['$(call do_cmd,%s%s)' % (command, suffix)],
comment = comment,
force = True)
# Add our outputs to the list of targets we read depfiles from.
@@ -2042,6 +2139,18 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
product_name = spec.get('product_name', self.output)
+ # Some postbuilds try to read a build output file at
+ # ""${BUILT_PRODUCTS_DIR}/${FULL_PRODUCT_NAME}". Static libraries end up
+ # "$(obj).target", so
+ # BUILT_PRODUCTS_DIR is $(builddir)
+ # FULL_PRODUCT_NAME is $(out).target/path/to/lib.a
+ # Since $(obj) contains out/Debug already, the postbuild
+ # would get out/Debug/out/Debug/obj.target/path/to/lib.a. To prevent this,
+ # remove the "out/Debug" prefix from $(obj).
+ if product_name.startswith('$(obj)'):
+ product_name = (
+ '$(subst $(builddir)/,,$(obj))' + product_name[len('$(obj)'):])
+
built_products_dir = generator_default_variables['PRODUCT_DIR']
srcroot = self.path
if target_relative_path:
@@ -2052,6 +2161,8 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
'BUILT_PRODUCTS_DIR' : built_products_dir,
'CONFIGURATION' : '$(BUILDTYPE)',
'PRODUCT_NAME' : product_name,
+ # See /Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/Specifications/MacOSX\ Product\ Types.xcspec for FULL_PRODUCT_NAME
+ 'FULL_PRODUCT_NAME' : product_name,
'SRCROOT' : srcroot,
# This is not true for static libraries, but currently the env is only
# written for bundles:
@@ -2060,13 +2171,9 @@ $(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
}
if self.type in ('executable', 'shared_library'):
env['EXECUTABLE_NAME'] = os.path.basename(self.output_binary)
- # Can't use self.output_binary here because it's not in the products dir.
- # We really care about the final location of the dylib anyway.
- env['EXECUTABLE_PATH'] = StripProductDir(
- self._InstallableTargetInstallPath())
+ if self.type in ('executable', 'shared_library', 'loadable_module'):
+ env['EXECUTABLE_PATH'] = self.xcode_settings.GetExecutablePath()
if self.is_mac_bundle:
- # Overwrite this to point to the binary _in_ the bundle.
- env['EXECUTABLE_PATH'] = self.xcode_settings.GetBundleBinaryPath()
env['CONTENTS_FOLDER_PATH'] = \
self.xcode_settings.GetBundleContentsFolderPath()
env['INFOPLIST_PATH'] = self.xcode_settings.GetBundlePlistPath()
@@ -2312,8 +2419,7 @@ def GenerateOutput(target_list, target_dicts, data, params):
if os.path.exists(mactool_path):
os.remove(mactool_path)
CopyMacTool(mactool_path)
- os.chmod(mactool_path, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP |
- stat.S_IROTH | stat.S_IXOTH) # Make file executable.
+ os.chmod(mactool_path, 0o755) # Make file executable.
# Find the list of targets that derive from the gyp file(s) being built.
needed_targets = set()