mirror of https://github.com/lukechilds/node.git
130 changed files with 3936 additions and 1529 deletions
File diff suppressed because it is too large
File diff suppressed because it is too large
@ -0,0 +1,42 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2012 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. |
|||
|
|||
""" Unit tests for the ninja.py file. """ |
|||
|
|||
import gyp.generator.ninja as ninja |
|||
import unittest |
|||
import StringIO |
|||
import TestCommon |
|||
|
|||
|
|||
class TestPrefixesAndSuffixes(unittest.TestCase): |
|||
def test_BinaryNamesWindows(self): |
|||
writer = ninja.NinjaWriter('wee', '.', '.', 'ninja.build', 'win') |
|||
spec = { 'target_name': 'wee' } |
|||
self.assertTrue(writer.ComputeOutputFileName(spec, 'executable'). |
|||
endswith('.exe')) |
|||
self.assertTrue(writer.ComputeOutputFileName(spec, 'shared_library'). |
|||
endswith('.dll')) |
|||
self.assertTrue(writer.ComputeOutputFileName(spec, 'static_library'). |
|||
endswith('.lib')) |
|||
|
|||
def test_BinaryNamesLinux(self): |
|||
writer = ninja.NinjaWriter('wee', '.', '.', 'ninja.build', 'linux') |
|||
spec = { |
|||
'target_name': 'wee' |
|||
} |
|||
self.assertTrue('.' not in writer.ComputeOutputFileName(spec, 'executable')) |
|||
self.assertTrue(writer.ComputeOutputFileName(spec, 'shared_library'). |
|||
startswith('lib')) |
|||
self.assertTrue(writer.ComputeOutputFileName(spec, 'static_library'). |
|||
startswith('lib')) |
|||
self.assertTrue(writer.ComputeOutputFileName(spec, 'shared_library'). |
|||
endswith('.so')) |
|||
self.assertTrue(writer.ComputeOutputFileName(spec, 'static_library'). |
|||
endswith('.a')) |
|||
|
|||
if __name__ == '__main__': |
|||
unittest.main() |
@ -0,0 +1,972 @@ |
|||
# Copyright (c) 2012 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. |
|||
|
|||
""" |
|||
This module contains classes that help to emulate xcodebuild behavior on top of |
|||
other build systems, such as make and ninja. |
|||
""" |
|||
|
|||
import gyp.common |
|||
import os.path |
|||
import re |
|||
import shlex |
|||
|
|||
class XcodeSettings(object): |
|||
"""A class that understands the gyp 'xcode_settings' object.""" |
|||
|
|||
def __init__(self, spec): |
|||
self.spec = spec |
|||
|
|||
# Per-target 'xcode_settings' are pushed down into configs earlier by gyp. |
|||
# This means self.xcode_settings[config] always contains all settings |
|||
# for that config -- the per-target settings as well. Settings that are |
|||
# the same for all configs are implicitly per-target settings. |
|||
self.xcode_settings = {} |
|||
configs = spec['configurations'] |
|||
for configname, config in configs.iteritems(): |
|||
self.xcode_settings[configname] = config.get('xcode_settings', {}) |
|||
|
|||
# This is only non-None temporarily during the execution of some methods. |
|||
self.configname = None |
|||
|
|||
# Used by _AdjustLibrary to match .a and .dylib entries in libraries. |
|||
self.library_re = re.compile(r'^lib([^/]+)\.(a|dylib)$') |
|||
|
|||
def _Settings(self): |
|||
assert self.configname |
|||
return self.xcode_settings[self.configname] |
|||
|
|||
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, 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(): |
|||
print 'Warning: Ignoring not yet implemented key "%s".' % test_key |
|||
|
|||
def _IsBundle(self): |
|||
return int(self.spec.get('mac_bundle', 0)) != 0 |
|||
|
|||
def GetFrameworkVersion(self): |
|||
"""Returns the framework version of the current target. Only valid for |
|||
bundles.""" |
|||
assert self._IsBundle() |
|||
return self.GetPerTargetSetting('FRAMEWORK_VERSION', default='A') |
|||
|
|||
def GetWrapperExtension(self): |
|||
"""Returns the bundle extension (.app, .framework, .plugin, etc). Only |
|||
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=default_wrapper_extension) |
|||
return '.' + self.spec.get('product_extension', wrapper_extension) |
|||
elif self.spec['type'] == 'executable': |
|||
return '.app' |
|||
else: |
|||
assert False, "Don't know extension for '%s', target '%s'" % ( |
|||
self.spec['type'], self.spec['target_name']) |
|||
|
|||
def GetProductName(self): |
|||
"""Returns PRODUCT_NAME.""" |
|||
return self.spec.get('product_name', self.spec['target_name']) |
|||
|
|||
def GetFullProductName(self): |
|||
"""Returns FULL_PRODUCT_NAME.""" |
|||
if self._IsBundle(): |
|||
return self.GetWrapperName() |
|||
else: |
|||
return self._GetStandaloneBinaryPath() |
|||
|
|||
def GetWrapperName(self): |
|||
"""Returns the directory name of the bundle represented by this target. |
|||
Only valid for bundles.""" |
|||
assert self._IsBundle() |
|||
return self.GetProductName() + self.GetWrapperExtension() |
|||
|
|||
def GetBundleContentsFolderPath(self): |
|||
"""Returns the qualified path to the bundle's contents folder. E.g. |
|||
Chromium.app/Contents or Foo.bundle/Versions/A. Only valid for bundles.""" |
|||
assert self._IsBundle() |
|||
if self.spec['type'] == 'shared_library': |
|||
return os.path.join( |
|||
self.GetWrapperName(), 'Versions', self.GetFrameworkVersion()) |
|||
else: |
|||
# loadable_modules have a 'Contents' folder like executables. |
|||
return os.path.join(self.GetWrapperName(), 'Contents') |
|||
|
|||
def GetBundleResourceFolder(self): |
|||
"""Returns the qualified path to the bundle's resource folder. E.g. |
|||
Chromium.app/Contents/Resources. Only valid for bundles.""" |
|||
assert self._IsBundle() |
|||
return os.path.join(self.GetBundleContentsFolderPath(), 'Resources') |
|||
|
|||
def GetBundlePlistPath(self): |
|||
"""Returns the qualified path to the bundle's plist file. E.g. |
|||
Chromium.app/Contents/Info.plist. Only valid for bundles.""" |
|||
assert self._IsBundle() |
|||
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 ('shared_library'): |
|||
path = self.GetBundleContentsFolderPath() |
|||
elif self.spec['type'] in ('executable', 'loadable_module'): |
|||
path = os.path.join(self.GetBundleContentsFolderPath(), 'MacOS') |
|||
return os.path.join(path, self.GetExecutableName()) |
|||
|
|||
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'), ( |
|||
'Unexpected type %s' % self.spec['type']) |
|||
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 GetExecutableName(self): |
|||
"""Returns the executable name of the bundle represented by this target. |
|||
E.g. Chromium.""" |
|||
if self._IsBundle(): |
|||
return self.spec.get('product_name', self.spec['target_name']) |
|||
else: |
|||
return self._GetStandaloneBinaryPath() |
|||
|
|||
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 _SdkPath(self): |
|||
sdk_root = self.GetPerTargetSetting('SDKROOT', default='macosx10.5') |
|||
if sdk_root.startswith('macosx'): |
|||
sdk_root = 'MacOSX' + sdk_root[len('macosx'):] |
|||
return '/Developer/SDKs/%s.sdk' % sdk_root |
|||
|
|||
def GetCflags(self, configname): |
|||
"""Returns flags that need to be added to .c, .cc, .m, and .mm |
|||
compilations.""" |
|||
# This functions (and the similar ones below) do not offer complete |
|||
# emulation of all xcode_settings keys. They're implemented on demand. |
|||
|
|||
self.configname = configname |
|||
cflags = [] |
|||
|
|||
sdk_root = self._SdkPath() |
|||
if 'SDKROOT' in self._Settings(): |
|||
cflags.append('-isysroot %s' % sdk_root) |
|||
|
|||
if self._Test('GCC_CHAR_IS_UNSIGNED_CHAR', 'YES', default='NO'): |
|||
cflags.append('-funsigned-char') |
|||
|
|||
if self._Test('GCC_CW_ASM_SYNTAX', 'YES', default='YES'): |
|||
cflags.append('-fasm-blocks') |
|||
|
|||
if 'GCC_DYNAMIC_NO_PIC' in self._Settings(): |
|||
if self._Settings()['GCC_DYNAMIC_NO_PIC'] == 'YES': |
|||
cflags.append('-mdynamic-no-pic') |
|||
else: |
|||
pass |
|||
# TODO: In this case, it depends on the target. xcode passes |
|||
# mdynamic-no-pic by default for executable and possibly static lib |
|||
# according to mento |
|||
|
|||
if self._Test('GCC_ENABLE_PASCAL_STRINGS', 'YES', default='YES'): |
|||
cflags.append('-mpascal-strings') |
|||
|
|||
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') |
|||
if dbg_format == 'dwarf': |
|||
cflags.append('-gdwarf-2') |
|||
elif dbg_format == 'stabs': |
|||
raise NotImplementedError('stabs debug format is not supported yet.') |
|||
elif dbg_format == 'dwarf-with-dsym': |
|||
cflags.append('-gdwarf-2') |
|||
else: |
|||
raise NotImplementedError('Unknown debug format %s' % dbg_format) |
|||
|
|||
if self._Test('GCC_SYMBOLS_PRIVATE_EXTERN', 'YES', default='NO'): |
|||
cflags.append('-fvisibility=hidden') |
|||
|
|||
if self._Test('GCC_TREAT_WARNINGS_AS_ERRORS', 'YES', default='NO'): |
|||
cflags.append('-Werror') |
|||
|
|||
if self._Test('GCC_WARN_ABOUT_MISSING_NEWLINE', 'YES', default='NO'): |
|||
cflags.append('-Wnewline-eof') |
|||
|
|||
self._Appendf(cflags, 'MACOSX_DEPLOYMENT_TARGET', '-mmacosx-version-min=%s') |
|||
|
|||
# TODO: |
|||
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') |
|||
|
|||
# TODO: This is exported correctly, but assigning to it is not supported. |
|||
self._WarnUnimplemented('MACH_O_TYPE') |
|||
self._WarnUnimplemented('PRODUCT_TYPE') |
|||
|
|||
archs = self._Settings().get('ARCHS', ['i386']) |
|||
if len(archs) != 1: |
|||
# TODO: Supporting fat binaries will be annoying. |
|||
self._WarnUnimplemented('ARCHS') |
|||
archs = ['i386'] |
|||
cflags.append('-arch ' + archs[0]) |
|||
|
|||
if archs[0] in ('i386', 'x86_64'): |
|||
if self._Test('GCC_ENABLE_SSE3_EXTENSIONS', 'YES', default='NO'): |
|||
cflags.append('-msse3') |
|||
if self._Test('GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS', 'YES', |
|||
default='NO'): |
|||
cflags.append('-mssse3') # Note 3rd 's'. |
|||
if self._Test('GCC_ENABLE_SSE41_EXTENSIONS', 'YES', default='NO'): |
|||
cflags.append('-msse4.1') |
|||
if self._Test('GCC_ENABLE_SSE42_EXTENSIONS', 'YES', default='NO'): |
|||
cflags.append('-msse4.2') |
|||
|
|||
cflags += self._Settings().get('OTHER_CFLAGS', []) |
|||
cflags += self._Settings().get('WARNING_CFLAGS', []) |
|||
|
|||
config = self.spec['configurations'][self.configname] |
|||
framework_dirs = config.get('mac_framework_dirs', []) |
|||
for directory in framework_dirs: |
|||
cflags.append('-F ' + directory.replace('$(SDKROOT)', sdk_root)) |
|||
|
|||
self.configname = None |
|||
return cflags |
|||
|
|||
def GetCflagsC(self, configname): |
|||
"""Returns flags that need to be added to .c, and .m compilations.""" |
|||
self.configname = configname |
|||
cflags_c = [] |
|||
self._Appendf(cflags_c, 'GCC_C_LANGUAGE_STANDARD', '-std=%s') |
|||
self.configname = None |
|||
return cflags_c |
|||
|
|||
def GetCflagsCC(self, configname): |
|||
"""Returns flags that need to be added to .cc, and .mm compilations.""" |
|||
self.configname = configname |
|||
cflags_cc = [] |
|||
if self._Test('GCC_ENABLE_CPP_RTTI', 'NO', default='YES'): |
|||
cflags_cc.append('-fno-rtti') |
|||
if self._Test('GCC_ENABLE_CPP_EXCEPTIONS', 'NO', default='YES'): |
|||
cflags_cc.append('-fno-exceptions') |
|||
if self._Test('GCC_INLINES_ARE_PRIVATE_EXTERN', 'YES', default='NO'): |
|||
cflags_cc.append('-fvisibility-inlines-hidden') |
|||
if self._Test('GCC_THREADSAFE_STATICS', 'NO', default='YES'): |
|||
cflags_cc.append('-fno-threadsafe-statics') |
|||
self.configname = None |
|||
return cflags_cc |
|||
|
|||
def GetCflagsObjC(self, configname): |
|||
"""Returns flags that need to be added to .m compilations.""" |
|||
self.configname = configname |
|||
self.configname = None |
|||
return [] |
|||
|
|||
def GetCflagsObjCC(self, configname): |
|||
"""Returns flags that need to be added to .mm compilations.""" |
|||
self.configname = configname |
|||
cflags_objcc = [] |
|||
if self._Test('GCC_OBJC_CALL_CXX_CDTORS', 'YES', default='NO'): |
|||
cflags_objcc.append('-fobjc-call-cxx-cdtors') |
|||
self.configname = None |
|||
return cflags_objcc |
|||
|
|||
def GetLdflags(self, configname, product_dir, gyp_to_build_path): |
|||
"""Returns flags that need to be passed to the linker. |
|||
|
|||
Args: |
|||
configname: The name of the configuration to get ld flags for. |
|||
product_dir: The directory where products such static and dynamic |
|||
libraries are placed. This is added to the library search path. |
|||
gyp_to_build_path: A function that converts paths relative to the |
|||
current gyp file to paths relative to the build direcotry. |
|||
""" |
|||
self.configname = configname |
|||
ldflags = [] |
|||
|
|||
# The xcode build is relative to a gyp file's directory, and OTHER_LDFLAGS |
|||
# contains two entries that depend on this. Explicitly absolutify for these |
|||
# two cases. |
|||
def MapGypPathWithPrefix(flag, prefix): |
|||
if flag.startswith(prefix): |
|||
flag = prefix + gyp_to_build_path(flag[len(prefix):]) |
|||
return flag |
|||
for ldflag in self._Settings().get('OTHER_LDFLAGS', []): |
|||
# Required for ffmpeg (no idea why they don't use LIBRARY_SEARCH_PATHS, |
|||
# TODO(thakis): Update ffmpeg.gyp): |
|||
ldflag = MapGypPathWithPrefix(ldflag, '-L') |
|||
# Required for the nacl plugin: |
|||
ldflag = MapGypPathWithPrefix(ldflag, '-Wl,-exported_symbols_list ') |
|||
ldflags.append(ldflag) |
|||
|
|||
if self._Test('DEAD_CODE_STRIPPING', 'YES', default='NO'): |
|||
ldflags.append('-Wl,-dead_strip') |
|||
|
|||
if self._Test('PREBINDING', 'YES', default='NO'): |
|||
ldflags.append('-Wl,-prebind') |
|||
|
|||
self._Appendf( |
|||
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') |
|||
if 'SDKROOT' in self._Settings(): |
|||
ldflags.append('-isysroot ' + self._SdkPath()) |
|||
|
|||
for library_path in self._Settings().get('LIBRARY_SEARCH_PATHS', []): |
|||
ldflags.append('-L' + gyp_to_build_path(library_path)) |
|||
|
|||
if 'ORDER_FILE' in self._Settings(): |
|||
ldflags.append('-Wl,-order_file ' + |
|||
'-Wl,' + gyp_to_build_path( |
|||
self._Settings()['ORDER_FILE'])) |
|||
|
|||
archs = self._Settings().get('ARCHS', ['i386']) |
|||
if len(archs) != 1: |
|||
# TODO: Supporting fat binaries will be annoying. |
|||
self._WarnUnimplemented('ARCHS') |
|||
archs = ['i386'] |
|||
ldflags.append('-arch ' + archs[0]) |
|||
|
|||
# Xcode adds the product directory by default. |
|||
ldflags.append('-L' + 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 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)) |
|||
# I'm not quite sure what :standardizepath does. Just call normpath(), |
|||
# 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( |
|||
'$(EXECUTABLE_PATH)', self.GetExecutablePath()) |
|||
|
|||
install_name = install_name.replace(' ', r'\ ') |
|||
ldflags.append('-install_name ' + install_name) |
|||
|
|||
self.configname = None |
|||
return ldflags |
|||
|
|||
def GetPerTargetSettings(self): |
|||
"""Gets a list of all the per-target settings. This will only fetch keys |
|||
whose values are the same across all configurations.""" |
|||
first_pass = True |
|||
result = {} |
|||
for configname in sorted(self.xcode_settings.keys()): |
|||
if first_pass: |
|||
result = dict(self.xcode_settings[configname]) |
|||
first_pass = False |
|||
else: |
|||
for key, value in self.xcode_settings[configname].iteritems(): |
|||
if key not in result: |
|||
continue |
|||
elif result[key] != value: |
|||
del result[key] |
|||
return result |
|||
|
|||
def GetPerTargetSetting(self, setting, default=None): |
|||
"""Tries to get xcode_settings.setting from spec. Assumes that the setting |
|||
has the same value in all configurations and throws otherwise.""" |
|||
first_pass = True |
|||
result = None |
|||
for configname in sorted(self.xcode_settings.keys()): |
|||
if first_pass: |
|||
result = self.xcode_settings[configname].get(setting, None) |
|||
first_pass = False |
|||
else: |
|||
assert result == self.xcode_settings[configname].get(setting, None), ( |
|||
"Expected per-target setting for '%s', got per-config setting " |
|||
"(target %s)" % (setting, spec['target_name'])) |
|||
if result is None: |
|||
return default |
|||
return result |
|||
|
|||
def _GetStripPostbuilds(self, configname, output_binary, quiet): |
|||
"""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 += ' ' + _NormalizeEnvVarReferences(explicit_strip_flags) |
|||
|
|||
if not quiet: |
|||
result.append('echo STRIP\\(%s\\)' % self.spec['target_name']) |
|||
result.append('strip %s %s' % (strip_flags, output_binary)) |
|||
|
|||
self.configname = None |
|||
return result |
|||
|
|||
def _GetDebugInfoPostbuilds(self, configname, output, output_binary, quiet): |
|||
"""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'): |
|||
if not quiet: |
|||
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, quiet=False): |
|||
"""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._GetDebugInfoPostbuilds(configname, output, output_binary, quiet) + |
|||
self._GetStripPostbuilds(configname, output_binary, quiet)) |
|||
|
|||
def _AdjustLibrary(self, library): |
|||
if library.endswith('.framework'): |
|||
l = '-framework ' + os.path.splitext(os.path.basename(library))[0] |
|||
else: |
|||
m = self.library_re.match(library) |
|||
if m: |
|||
l = '-l' + m.group(1) |
|||
else: |
|||
l = library |
|||
return l.replace('$(SDKROOT)', self._SdkPath()) |
|||
|
|||
def AdjustLibraries(self, libraries): |
|||
"""Transforms entries like 'Cocoa.framework' in libraries into entries like |
|||
'-framework Cocoa', 'libcrypto.dylib' into '-lcrypto', etc. |
|||
""" |
|||
libraries = [ self._AdjustLibrary(library) for library in libraries] |
|||
return libraries |
|||
|
|||
|
|||
class MacPrefixHeader(object): |
|||
"""A class that helps with emulating Xcode's GCC_PREFIX_HEADER feature. |
|||
|
|||
This feature consists of several pieces: |
|||
* If GCC_PREFIX_HEADER is present, all compilations in that project get an |
|||
additional |-include path_to_prefix_header| cflag. |
|||
* If GCC_PRECOMPILE_PREFIX_HEADER is present too, then the prefix header is |
|||
instead compiled, and all other compilations in the project get an |
|||
additional |-include path_to_compiled_header| instead. |
|||
+ Compiled prefix headers have the extension gch. There is one gch file for |
|||
every language used in the project (c, cc, m, mm), since gch files for |
|||
different languages aren't compatible. |
|||
+ gch files themselves are built with the target's normal cflags, but they |
|||
obviously don't get the |-include| flag. Instead, they need a -x flag that |
|||
describes their language. |
|||
+ All o files in the target need to depend on the gch file, to make sure |
|||
it's built before any o file is built. |
|||
|
|||
This class helps with some of these tasks, but it needs help from the build |
|||
system for writing dependencies to the gch files, for writing build commands |
|||
for the gch files, and for figuring out the location of the gch files. |
|||
""" |
|||
def __init__(self, xcode_settings, |
|||
gyp_path_to_build_path, gyp_path_to_build_output): |
|||
"""If xcode_settings is None, all methods on this class are no-ops. |
|||
|
|||
Args: |
|||
gyp_path_to_build_path: A function that takes a gyp-relative path, |
|||
and returns a path relative to the build directory. |
|||
gyp_path_to_build_output: A function that takes a gyp-relative path and |
|||
a language code ('c', 'cc', 'm', or 'mm'), and that returns a path |
|||
to where the output of precompiling that path for that language |
|||
should be placed (without the trailing '.gch'). |
|||
""" |
|||
# This doesn't support per-configuration prefix headers. Good enough |
|||
# for now. |
|||
self.header = None |
|||
self.compile_headers = False |
|||
if xcode_settings: |
|||
self.header = xcode_settings.GetPerTargetSetting('GCC_PREFIX_HEADER') |
|||
self.compile_headers = xcode_settings.GetPerTargetSetting( |
|||
'GCC_PRECOMPILE_PREFIX_HEADER', default='NO') != 'NO' |
|||
self.compiled_headers = {} |
|||
if self.header: |
|||
if self.compile_headers: |
|||
for lang in ['c', 'cc', 'm', 'mm']: |
|||
self.compiled_headers[lang] = gyp_path_to_build_output( |
|||
self.header, lang) |
|||
self.header = gyp_path_to_build_path(self.header) |
|||
|
|||
def GetInclude(self, lang): |
|||
"""Gets the cflags to include the prefix header for language |lang|.""" |
|||
if self.compile_headers and lang in self.compiled_headers: |
|||
return '-include %s' % self.compiled_headers[lang] |
|||
elif self.header: |
|||
return '-include %s' % self.header |
|||
else: |
|||
return '' |
|||
|
|||
def _Gch(self, lang): |
|||
"""Returns the actual file name of the prefix header for language |lang|.""" |
|||
assert self.compile_headers |
|||
return self.compiled_headers[lang] + '.gch' |
|||
|
|||
def GetObjDependencies(self, sources, objs): |
|||
"""Given a list of source files and the corresponding object files, returns |
|||
a list of (source, object, gch) tuples, where |gch| is the build-directory |
|||
relative path to the gch file each object file depends on. |compilable[i]| |
|||
has to be the source file belonging to |objs[i]|.""" |
|||
if not self.header or not self.compile_headers: |
|||
return [] |
|||
|
|||
result = [] |
|||
for source, obj in zip(sources, objs): |
|||
ext = os.path.splitext(source)[1] |
|||
lang = { |
|||
'.c': 'c', |
|||
'.cpp': 'cc', '.cc': 'cc', '.cxx': 'cc', |
|||
'.m': 'm', |
|||
'.mm': 'mm', |
|||
}.get(ext, None) |
|||
if lang: |
|||
result.append((source, obj, self._Gch(lang))) |
|||
return result |
|||
|
|||
def GetGchBuildCommands(self): |
|||
"""Returns [(path_to_gch, language_flag, language, header)]. |
|||
|path_to_gch| and |header| are relative to the build directory. |
|||
""" |
|||
if not self.header or not self.compile_headers: |
|||
return [] |
|||
return [ |
|||
(self._Gch('c'), '-x c-header', 'c', self.header), |
|||
(self._Gch('cc'), '-x c++-header', 'cc', self.header), |
|||
(self._Gch('m'), '-x objective-c-header', 'm', self.header), |
|||
(self._Gch('mm'), '-x objective-c++-header', 'mm', self.header), |
|||
] |
|||
|
|||
|
|||
def MergeGlobalXcodeSettingsToSpec(global_dict, spec): |
|||
"""Merges the global xcode_settings dictionary into each configuration of the |
|||
target represented by spec. For keys that are both in the global and the local |
|||
xcode_settings dict, the local key gets precendence. |
|||
""" |
|||
# The xcode generator special-cases global xcode_settings and does something |
|||
# that amounts to merging in the global xcode_settings into each local |
|||
# xcode_settings dict. |
|||
global_xcode_settings = global_dict.get('xcode_settings', {}) |
|||
for config in spec['configurations'].values(): |
|||
if 'xcode_settings' in config: |
|||
new_settings = global_xcode_settings.copy() |
|||
new_settings.update(config['xcode_settings']) |
|||
config['xcode_settings'] = new_settings |
|||
|
|||
|
|||
def IsMacBundle(flavor, spec): |
|||
"""Returns if |spec| should be treated as a bundle. |
|||
|
|||
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.""" |
|||
is_mac_bundle = (int(spec.get('mac_bundle', 0)) != 0 and flavor == 'mac') |
|||
if is_mac_bundle: |
|||
assert spec['type'] != 'none', ( |
|||
'mac_bundle targets cannot have type none (target "%s")' % |
|||
spec['target_name']) |
|||
return is_mac_bundle |
|||
|
|||
|
|||
def GetMacBundleResources(product_dir, xcode_settings, resources): |
|||
"""Yields (output, resource) pairs for every resource in |resources|. |
|||
Only call this for mac bundle targets. |
|||
|
|||
Args: |
|||
product_dir: Path to the directory containing the output bundle, |
|||
relative to the build directory. |
|||
xcode_settings: The XcodeSettings of the current target. |
|||
resources: A list of bundle resources, relative to the build directory. |
|||
""" |
|||
dest = os.path.join(product_dir, |
|||
xcode_settings.GetBundleResourceFolder()) |
|||
for res in resources: |
|||
output = dest |
|||
|
|||
# The make generator doesn't support it, so forbid it everywhere |
|||
# to keep the generators more interchangable. |
|||
assert ' ' not in res, ( |
|||
"Spaces in resource filenames not supported (%s)" % res) |
|||
|
|||
# Split into (path,file). |
|||
res_parts = os.path.split(res) |
|||
|
|||
# Now split the path into (prefix,maybe.lproj). |
|||
lproj_parts = os.path.split(res_parts[0]) |
|||
# If the resource lives in a .lproj bundle, add that to the destination. |
|||
if lproj_parts[1].endswith('.lproj'): |
|||
output = os.path.join(output, lproj_parts[1]) |
|||
|
|||
output = os.path.join(output, res_parts[1]) |
|||
# Compiled XIB files are referred to by .nib. |
|||
if output.endswith('.xib'): |
|||
output = output[0:-3] + 'nib' |
|||
|
|||
yield output, res |
|||
|
|||
|
|||
def GetMacInfoPlist(product_dir, xcode_settings, gyp_path_to_build_path): |
|||
"""Returns (info_plist, dest_plist, defines, extra_env), where: |
|||
* |info_plist| is the sourc plist path, relative to the |
|||
build directory, |
|||
* |dest_plist| is the destination plist path, relative to the |
|||
build directory, |
|||
* |defines| is a list of preprocessor defines (empty if the plist |
|||
shouldn't be preprocessed, |
|||
* |extra_env| is a dict of env variables that should be exported when |
|||
invoking |mac_tool copy-info-plist|. |
|||
|
|||
Only call this for mac bundle targets. |
|||
|
|||
Args: |
|||
product_dir: Path to the directory containing the output bundle, |
|||
relative to the build directory. |
|||
xcode_settings: The XcodeSettings of the current target. |
|||
gyp_to_build_path: A function that converts paths relative to the |
|||
current gyp file to paths relative to the build direcotry. |
|||
""" |
|||
info_plist = xcode_settings.GetPerTargetSetting('INFOPLIST_FILE') |
|||
if not info_plist: |
|||
return None, None, [], {} |
|||
|
|||
# The make generator doesn't support it, so forbid it everywhere |
|||
# to keep the generators more interchangable. |
|||
assert ' ' not in info_plist, ( |
|||
"Spaces in Info.plist filenames not supported (%s)" % info_plist) |
|||
|
|||
info_plist = gyp_path_to_build_path(info_plist) |
|||
|
|||
# If explicitly set to preprocess the plist, invoke the C preprocessor and |
|||
# specify any defines as -D flags. |
|||
if xcode_settings.GetPerTargetSetting( |
|||
'INFOPLIST_PREPROCESS', default='NO') == 'YES': |
|||
# Create an intermediate file based on the path. |
|||
defines = shlex.split(xcode_settings.GetPerTargetSetting( |
|||
'INFOPLIST_PREPROCESSOR_DEFINITIONS', default='')) |
|||
else: |
|||
defines = [] |
|||
|
|||
dest_plist = os.path.join(product_dir, xcode_settings.GetBundlePlistPath()) |
|||
extra_env = xcode_settings.GetPerTargetSettings() |
|||
|
|||
return info_plist, dest_plist, defines, extra_env |
|||
|
|||
|
|||
def GetXcodeEnv(xcode_settings, built_products_dir, srcroot, configuration, |
|||
additional_settings=None): |
|||
"""Return the environment variables that Xcode would set. See |
|||
http://developer.apple.com/library/mac/#documentation/DeveloperTools/Reference/XcodeBuildSettingRef/1-Build_Setting_Reference/build_setting_ref.html#//apple_ref/doc/uid/TP40003931-CH3-SW153 |
|||
for a full list. |
|||
|
|||
Args: |
|||
xcode_settings: An XcodeSettings object. If this is None, this function |
|||
returns an empty dict. |
|||
built_products_dir: Absolute path to the built products dir. |
|||
srcroot: Absolute path to the source root. |
|||
configuration: The build configuration name. |
|||
additional_settings: An optional dict with more values to add to the |
|||
result. |
|||
""" |
|||
if not xcode_settings: return {} |
|||
|
|||
# This function is considered a friend of XcodeSettings, so let it reach into |
|||
# its implementation details. |
|||
spec = xcode_settings.spec |
|||
|
|||
# These are filled in on a as-needed basis. |
|||
env = { |
|||
'BUILT_PRODUCTS_DIR' : built_products_dir, |
|||
'CONFIGURATION' : configuration, |
|||
'PRODUCT_NAME' : xcode_settings.GetProductName(), |
|||
# See /Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/Specifications/MacOSX\ Product\ Types.xcspec for FULL_PRODUCT_NAME |
|||
'SRCROOT' : srcroot, |
|||
'SOURCE_ROOT': '${SRCROOT}', |
|||
# This is not true for static libraries, but currently the env is only |
|||
# written for bundles: |
|||
'TARGET_BUILD_DIR' : built_products_dir, |
|||
'TEMP_DIR' : '${TMPDIR}', |
|||
} |
|||
if spec['type'] in ( |
|||
'executable', 'static_library', 'shared_library', 'loadable_module'): |
|||
env['EXECUTABLE_NAME'] = xcode_settings.GetExecutableName() |
|||
env['EXECUTABLE_PATH'] = xcode_settings.GetExecutablePath() |
|||
env['FULL_PRODUCT_NAME'] = xcode_settings.GetFullProductName() |
|||
mach_o_type = xcode_settings.GetMachOType() |
|||
if mach_o_type: |
|||
env['MACH_O_TYPE'] = mach_o_type |
|||
env['PRODUCT_TYPE'] = xcode_settings.GetProductType() |
|||
if xcode_settings._IsBundle(): |
|||
env['CONTENTS_FOLDER_PATH'] = \ |
|||
xcode_settings.GetBundleContentsFolderPath() |
|||
env['UNLOCALIZED_RESOURCES_FOLDER_PATH'] = \ |
|||
xcode_settings.GetBundleResourceFolder() |
|||
env['INFOPLIST_PATH'] = xcode_settings.GetBundlePlistPath() |
|||
env['WRAPPER_NAME'] = xcode_settings.GetWrapperName() |
|||
|
|||
if not additional_settings: |
|||
additional_settings = {} |
|||
else: |
|||
# Flatten lists to strings. |
|||
for k in additional_settings: |
|||
if not isinstance(additional_settings[k], str): |
|||
additional_settings[k] = ' '.join(additional_settings[k]) |
|||
additional_settings.update(env) |
|||
|
|||
for k in additional_settings: |
|||
additional_settings[k] = _NormalizeEnvVarReferences(additional_settings[k]) |
|||
|
|||
return additional_settings |
|||
|
|||
|
|||
def _NormalizeEnvVarReferences(str): |
|||
"""Takes a string containing variable references in the form ${FOO}, $(FOO), |
|||
or $FOO, and returns a string with all variable references in the form ${FOO}. |
|||
""" |
|||
# $FOO -> ${FOO} |
|||
str = re.sub(r'\$([a-zA-Z_][a-zA-Z0-9_]*)', r'${\1}', str) |
|||
|
|||
# $(FOO) -> ${FOO} |
|||
matches = re.findall(r'(\$\(([a-zA-Z0-9\-_]+)\))', str) |
|||
for match in matches: |
|||
to_replace, variable = match |
|||
assert '$(' not in match, '$($(FOO)) variables not supported: ' + match |
|||
str = str.replace(to_replace, '${' + variable + '}') |
|||
|
|||
return str |
|||
|
|||
|
|||
def ExpandEnvVars(string, expansions): |
|||
"""Expands ${VARIABLES}, $(VARIABLES), and $VARIABLES in string per the |
|||
expansions dict. If the variable expands to something that references |
|||
another variable, this variable is expanded as well if it's in env -- |
|||
until no variables present in env are left.""" |
|||
for k in reversed(TopologicallySortedEnvVarKeys(expansions)): |
|||
string = string.replace('${' + k + '}', expansions[k]) |
|||
string = string.replace('$(' + k + ')', expansions[k]) |
|||
string = string.replace('$' + k, expansions[k]) |
|||
return string |
|||
|
|||
|
|||
def TopologicallySortedEnvVarKeys(env): |
|||
"""Takes a dict |env| whose values are strings that can refer to other keys, |
|||
for example env['foo'] = '$(bar) and $(baz)'. Returns a list L of all keys of |
|||
env such that key2 is after key1 in L if env[key2] refers to env[key1]. |
|||
|
|||
Throws an Exception in case of dependency cycles. |
|||
""" |
|||
# Since environment variables can refer to other variables, the evaluation |
|||
# order is important. Below is the logic to compute the dependency graph |
|||
# and sort it. |
|||
regex = re.compile(r'\$\{([a-zA-Z0-9\-_]+)\}') |
|||
|
|||
# First sort the list of keys. |
|||
key_list = sorted(env.keys()) |
|||
|
|||
# Phase 1: Create a set of edges of (DEPENDEE, DEPENDER) where in the graph, |
|||
# DEPENDEE -> DEPENDER. Also create sets of dependers and dependees. |
|||
edges = set() |
|||
dependees = set() |
|||
dependers = set() |
|||
for k in key_list: |
|||
matches = regex.findall(env[k]) |
|||
if not len(matches): |
|||
continue |
|||
|
|||
depends_on_other_var = False |
|||
for dependee in matches: |
|||
assert '${' not in dependee, 'Nested variables not supported: ' + dependee |
|||
if dependee in env: |
|||
edges.add((dependee, k)) |
|||
dependees.add(dependee) |
|||
depends_on_other_var = True |
|||
if depends_on_other_var: |
|||
dependers.add(k) |
|||
|
|||
# Phase 2: Create a list of graph nodes with no incoming edges. |
|||
sorted_nodes = [] |
|||
edgeless_nodes = dependees - dependers |
|||
|
|||
# Phase 3: Perform Kahn topological sort. |
|||
while len(edgeless_nodes): |
|||
# Find a node with no incoming edges, add it to the sorted list, and |
|||
# remove it from the list of nodes that aren't part of the graph. |
|||
node = edgeless_nodes.pop() |
|||
sorted_nodes.append(node) |
|||
key_list.remove(node) |
|||
|
|||
# Find all the edges between |node| and other nodes. |
|||
edges_to_node = [e for e in edges if e[0] == node] |
|||
for edge in edges_to_node: |
|||
edges.remove(edge) |
|||
# If the node connected to |node| by |edge| has no other incoming edges, |
|||
# add it to |edgeless_nodes|. |
|||
if not len([e for e in edges if e[1] == edge[1]]): |
|||
edgeless_nodes.add(edge[1]) |
|||
|
|||
# Any remaining edges indicate a cycle. |
|||
if len(edges): |
|||
raise Exception('Xcode environment variables are cyclically dependent: ' + |
|||
str(edges)) |
|||
|
|||
# Append the "nodes" not in the graph to those that were just sorted. |
|||
sorted_nodes.extend(key_list) |
|||
|
|||
return sorted_nodes |
|||
|
|||
def GetSpecPostbuildCommands(spec, gyp_path_to_build_path, quiet=False): |
|||
"""Returns the list of postbuilds explicitly defined on |spec|, in a form |
|||
executable by a shell.""" |
|||
postbuilds = [] |
|||
for postbuild in spec.get('postbuilds', []): |
|||
if not quiet: |
|||
postbuilds.append('echo POSTBUILD\\(%s\\) %s' % ( |
|||
spec['target_name'], 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] = gyp_path_to_build_path(shell_list[0]) |
|||
|
|||
# "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)) |
|||
|
|||
return postbuilds |
@ -0,0 +1,34 @@ |
|||
# Copyright (c) 2012 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. |
|||
{ |
|||
'targets': [ |
|||
{ |
|||
'target_name': 'action', |
|||
'type': 'none', |
|||
'actions': [ |
|||
{ |
|||
'inputs': [ ], |
|||
'outputs': [ |
|||
'<(PRODUCT_DIR)/result', |
|||
'<(SHARED_INTERMEDIATE_DIR)/tempfile', |
|||
], |
|||
'action_name': 'Test action', |
|||
'action': ['./action.sh', '<(SHARED_INTERMEDIATE_DIR)/tempfile' ], |
|||
}, |
|||
{ |
|||
'inputs': [ |
|||
'<(SHARED_INTERMEDIATE_DIR)/tempfile', |
|||
], |
|||
'outputs': [ |
|||
'<(PRODUCT_DIR)/other_result', |
|||
], |
|||
'action_name': 'Other test action', |
|||
'action': ['cp', '<(SHARED_INTERMEDIATE_DIR)/tempfile', |
|||
'<(PRODUCT_DIR)/other_result' ], |
|||
}, |
|||
], |
|||
}, |
|||
], |
|||
} |
|||
|
@ -0,0 +1,8 @@ |
|||
# Copyright (c) 2012 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. |
|||
|
|||
set -e |
|||
|
|||
echo 'Test output' > "${BUILT_PRODUCTS_DIR}/result" |
|||
echo 'Other output' > "$1" |
@ -0,0 +1,4 @@ |
|||
/* Copyright (c) 2012 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. */ |
|||
int x = 1; |
@ -0,0 +1,9 @@ |
|||
/* Copyright (c) 2012 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. */ |
|||
#include <stdio.h> |
|||
extern int x; |
|||
int main() { |
|||
printf("hello, world %d\n", x); |
|||
} |
|||
|
@ -0,0 +1,27 @@ |
|||
# Copyright (c) 2012 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. |
|||
|
|||
{ |
|||
'targets': [ |
|||
{ |
|||
'target_name': 'lib', |
|||
'product_name': 'Test64', |
|||
'type': 'static_library', |
|||
'sources': [ 'my_file.cc' ], |
|||
'xcode_settings': { |
|||
'ARCHS': [ 'x86_64' ], |
|||
}, |
|||
}, |
|||
{ |
|||
'target_name': 'exe', |
|||
'product_name': 'Test64', |
|||
'type': 'executable', |
|||
'dependencies': [ 'lib' ], |
|||
'sources': [ 'my_main_file.cc' ], |
|||
'xcode_settings': { |
|||
'ARCHS': [ 'x86_64' ], |
|||
}, |
|||
}, |
|||
] |
|||
} |
@ -0,0 +1,21 @@ |
|||
# Copyright (c) 2012 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. |
|||
|
|||
{ |
|||
'targets': [ |
|||
{ |
|||
'target_name': 'lib', |
|||
'product_name': 'Test', |
|||
'type': 'static_library', |
|||
'sources': [ 'my_file.cc' ], |
|||
}, |
|||
{ |
|||
'target_name': 'exe', |
|||
'product_name': 'Test', |
|||
'type': 'executable', |
|||
'dependencies': [ 'lib' ], |
|||
'sources': [ 'my_main_file.cc' ], |
|||
}, |
|||
] |
|||
} |
@ -0,0 +1 @@ |
|||
int main() {} |
@ -0,0 +1,31 @@ |
|||
# Copyright (c) 2012 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. |
|||
{ |
|||
'targets': [ |
|||
{ |
|||
'target_name': 'my_dylib', |
|||
'type': 'shared_library', |
|||
'sources': [ 'empty.c', ], |
|||
}, |
|||
{ |
|||
'target_name': 'test_app', |
|||
'product_name': 'Test App', |
|||
'type': 'executable', |
|||
'mac_bundle': 1, |
|||
'dependencies': [ 'my_dylib', ], |
|||
'sources': [ |
|||
'empty.c', |
|||
], |
|||
'copies': [ |
|||
{ |
|||
'destination': '<(PRODUCT_DIR)/Test App.app/Contents/Resources', |
|||
'files': [ |
|||
'<(PRODUCT_DIR)/libmy_dylib.dylib', |
|||
], |
|||
}, |
|||
], |
|||
}, |
|||
], |
|||
} |
|||
|
@ -0,0 +1 @@ |
|||
/* Localized versions of Info.plist keys */ |
@ -0,0 +1,28 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|||
<plist version="1.0"> |
|||
<dict> |
|||
<key>CFBundleDevelopmentRegion</key> |
|||
<string>English</string> |
|||
<key>CFBundleExecutable</key> |
|||
<string>${EXECUTABLE_NAME}</string> |
|||
<key>CFBundleIconFile</key> |
|||
<string></string> |
|||
<key>CFBundleIdentifier</key> |
|||
<string>com.yourcompany.${PRODUCT_NAME}</string> |
|||
<key>CFBundleInfoDictionaryVersion</key> |
|||
<string>6.0</string> |
|||
<key>CFBundleName</key> |
|||
<string>${PRODUCT_NAME}</string> |
|||
<key>CFBundlePackageType</key> |
|||
<string>FMWK</string> |
|||
<key>CFBundleShortVersionString</key> |
|||
<string>1.0</string> |
|||
<key>CFBundleSignature</key> |
|||
<string>????</string> |
|||
<key>CFBundleVersion</key> |
|||
<string>1</string> |
|||
<key>NSPrincipalClass</key> |
|||
<string></string> |
|||
</dict> |
|||
</plist> |
@ -0,0 +1 @@ |
|||
int f() { return 42; } |
@ -0,0 +1,4 @@ |
|||
int f(); |
|||
int main() { |
|||
return f(); |
|||
} |
@ -0,0 +1,28 @@ |
|||
# Copyright (c) 2012 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. |
|||
{ |
|||
'targets': [ |
|||
{ |
|||
'target_name': 'my_bundle', |
|||
'type': 'shared_library', |
|||
'mac_bundle': 1, |
|||
'sources': [ 'bundle.c' ], |
|||
'mac_bundle_resources': [ |
|||
'English.lproj/InfoPlist.strings', |
|||
], |
|||
'xcode_settings': { |
|||
'INFOPLIST_FILE': 'Info.plist', |
|||
} |
|||
}, |
|||
{ |
|||
'target_name': 'dependent_on_bundle', |
|||
'type': 'executable', |
|||
'sources': [ 'executable.c' ], |
|||
'dependencies': [ |
|||
'my_bundle', |
|||
], |
|||
}, |
|||
], |
|||
} |
|||
|
@ -0,0 +1,11 @@ |
|||
# Copyright (c) 2012 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. |
|||
{ |
|||
'targets': [ |
|||
{ |
|||
'target_name': 'dir1_target', |
|||
'type': 'none', |
|||
}, |
|||
], |
|||
} |
@ -0,0 +1,22 @@ |
|||
# Copyright (c) 2012 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. |
|||
{ |
|||
'targets': [ |
|||
{ |
|||
'target_name': 'dir2_target', |
|||
'type': 'none', |
|||
'dependencies': [ |
|||
'../dir1/dir1.gyp:dir1_target', |
|||
], |
|||
'actions': [ |
|||
{ |
|||
'inputs': [ ], |
|||
'outputs': [ '<(PRODUCT_DIR)/file.txt' ], |
|||
'action_name': 'Test action', |
|||
'action': ['cp', 'file.txt', '${BUILT_PRODUCTS_DIR}/file.txt' ], |
|||
}, |
|||
], |
|||
}, |
|||
], |
|||
} |
@ -0,0 +1 @@ |
|||
File. |
@ -0,0 +1,30 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2012 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. |
|||
|
|||
""" |
|||
Verifies that env vars work with actions, with relative directory paths. |
|||
""" |
|||
|
|||
import TestGyp |
|||
|
|||
import sys |
|||
|
|||
if sys.platform == 'darwin': |
|||
test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) |
|||
|
|||
CHDIR = 'action-envvars' |
|||
test.run_gyp('action/action.gyp', chdir=CHDIR) |
|||
test.build('action/action.gyp', 'action', chdir=CHDIR, SYMROOT='../build') |
|||
|
|||
result_file = test.built_file_path('result', chdir=CHDIR) |
|||
test.must_exist(result_file) |
|||
test.must_contain(result_file, 'Test output') |
|||
|
|||
other_result_file = test.built_file_path('other_result', chdir=CHDIR) |
|||
test.must_exist(other_result_file) |
|||
test.must_contain(other_result_file, 'Other output') |
|||
|
|||
test.pass_test() |
@ -0,0 +1,37 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2012 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. |
|||
|
|||
""" |
|||
Tests things related to ARCHS. |
|||
""" |
|||
|
|||
import TestGyp |
|||
|
|||
import subprocess |
|||
import sys |
|||
|
|||
if sys.platform == 'darwin': |
|||
test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) |
|||
|
|||
def CheckFileType(file, expected): |
|||
proc = subprocess.Popen(['file', '-b', file], stdout=subprocess.PIPE) |
|||
o = proc.communicate()[0].strip() |
|||
assert not proc.returncode |
|||
if o != expected: |
|||
print 'File: Expected %s, got %s' % (expected, o) |
|||
test.fail_test() |
|||
|
|||
test.run_gyp('test-no-archs.gyp', chdir='archs') |
|||
test.build('test-no-archs.gyp', test.ALL, chdir='archs') |
|||
result_file = test.built_file_path('Test', chdir='archs') |
|||
test.must_exist(result_file) |
|||
CheckFileType(result_file, 'Mach-O executable i386') |
|||
|
|||
test.run_gyp('test-archs-x86_64.gyp', chdir='archs') |
|||
test.build('test-archs-x86_64.gyp', test.ALL, chdir='archs') |
|||
result_file = test.built_file_path('Test64', chdir='archs') |
|||
test.must_exist(result_file) |
|||
CheckFileType(result_file, 'Mach-O 64-bit executable x86_64') |
@ -0,0 +1,25 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2012 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. |
|||
|
|||
""" |
|||
Verifies that dylibs can be copied into app bundles. |
|||
""" |
|||
|
|||
import TestGyp |
|||
|
|||
import sys |
|||
|
|||
if sys.platform == 'darwin': |
|||
test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) |
|||
|
|||
test.run_gyp('test.gyp', chdir='copy-dylib') |
|||
|
|||
test.build('test.gyp', 'test_app', chdir='copy-dylib') |
|||
|
|||
test.built_file_must_exist( |
|||
'Test App.app/Contents/Resources/libmy_dylib.dylib', chdir='copy-dylib') |
|||
|
|||
test.pass_test() |
@ -0,0 +1,40 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2012 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. |
|||
|
|||
""" |
|||
Verifies that a dependency on a bundle causes the whole bundle to be built. |
|||
""" |
|||
|
|||
import TestGyp |
|||
|
|||
import sys |
|||
|
|||
if sys.platform == 'darwin': |
|||
test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) |
|||
|
|||
test.run_gyp('test.gyp', chdir='depend-on-bundle') |
|||
|
|||
test.build('test.gyp', 'dependent_on_bundle', chdir='depend-on-bundle') |
|||
|
|||
# Binary itself. |
|||
test.built_file_must_exist('dependent_on_bundle', chdir='depend-on-bundle') |
|||
|
|||
# Bundle dependency. |
|||
test.built_file_must_exist( |
|||
'my_bundle.framework/Versions/A/my_bundle', |
|||
chdir='depend-on-bundle') |
|||
test.built_file_must_exist( # package_framework |
|||
'my_bundle.framework/my_bundle', |
|||
chdir='depend-on-bundle') |
|||
test.built_file_must_exist( # plist |
|||
'my_bundle.framework/Versions/A/Resources/Info.plist', |
|||
chdir='depend-on-bundle') |
|||
test.built_file_must_exist( |
|||
'my_bundle.framework/Versions/A/Resources/English.lproj/' # Resources |
|||
'InfoPlist.strings', |
|||
chdir='depend-on-bundle') |
|||
|
|||
test.pass_test() |
@ -0,0 +1,26 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2012 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. |
|||
|
|||
""" |
|||
Verifies that the global xcode_settings processing doesn't throw. |
|||
Regression test for http://crbug.com/109163 |
|||
""" |
|||
|
|||
import TestGyp |
|||
|
|||
import sys |
|||
|
|||
if sys.platform == 'darwin': |
|||
test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) |
|||
test.run_gyp('src/dir2/dir2.gyp', chdir='global-settings', depth='src') |
|||
# run_gyp shouldn't throw. |
|||
|
|||
# Check that BUILT_PRODUCTS_DIR was set correctly, too. |
|||
test.build('dir2/dir2.gyp', 'dir2_target', chdir='global-settings/src', |
|||
SYMROOT='../build') |
|||
test.built_file_must_exist('file.txt', chdir='global-settings/src') |
|||
|
|||
test.pass_test() |
@ -0,0 +1,22 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2012 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. |
|||
|
|||
""" |
|||
Verifies libraries (in link_settings) are properly found. |
|||
""" |
|||
|
|||
import TestGyp |
|||
|
|||
import sys |
|||
|
|||
if sys.platform == 'darwin': |
|||
test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) |
|||
|
|||
test.run_gyp('subdir/test.gyp', chdir='libraries') |
|||
|
|||
test.build('subdir/test.gyp', test.ALL, chdir='libraries') |
|||
|
|||
test.pass_test() |
@ -0,0 +1,33 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2012 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. |
|||
|
|||
""" |
|||
Verifies that list xcode_settings are flattened before being exported to the |
|||
environment. |
|||
""" |
|||
|
|||
import TestGyp |
|||
|
|||
import sys |
|||
|
|||
if sys.platform == 'darwin': |
|||
test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) |
|||
|
|||
CHDIR = 'non-strs-flattened-to-env' |
|||
INFO_PLIST_PATH = 'Test.app/Contents/Info.plist' |
|||
|
|||
test.run_gyp('test.gyp', chdir=CHDIR) |
|||
test.build('test.gyp', test.ALL, chdir=CHDIR) |
|||
info_plist = test.built_file_path(INFO_PLIST_PATH, chdir=CHDIR) |
|||
test.must_exist(info_plist) |
|||
test.must_contain(info_plist, '''\ |
|||
\t<key>My Variable</key> |
|||
\t<string>some expansion</string>''') |
|||
test.must_contain(info_plist, '''\ |
|||
\t<key>CFlags</key> |
|||
\t<string>-fstack-protector-all -fno-strict-aliasing -DS="A Space"</string>''') |
|||
|
|||
test.pass_test() |
@ -0,0 +1,62 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2012 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. |
|||
|
|||
""" |
|||
Verifies that a postbuild copying a dependend framework into an app bundle is |
|||
rerun if the resources in the framework change. |
|||
""" |
|||
|
|||
import TestGyp |
|||
|
|||
import os.path |
|||
import sys |
|||
|
|||
if sys.platform == 'darwin': |
|||
# TODO(thakis): Make this pass with the make generator, http://crbug.com/95529 |
|||
test = TestGyp.TestGyp(formats=['ninja', 'xcode']) |
|||
|
|||
CHDIR = 'postbuild-copy-bundle' |
|||
test.run_gyp('test.gyp', chdir=CHDIR) |
|||
|
|||
app_bundle_dir = test.built_file_path('Test app.app', chdir=CHDIR) |
|||
bundled_framework_dir = os.path.join( |
|||
app_bundle_dir, 'Contents', 'My Framework.framework', 'Resources') |
|||
final_plist_path = os.path.join(bundled_framework_dir, 'Info.plist') |
|||
final_resource_path = os.path.join(bundled_framework_dir, 'resource_file.sb') |
|||
|
|||
# Check that the dependency was built and copied into the app bundle: |
|||
test.build('test.gyp', 'test_app', chdir=CHDIR) |
|||
test.must_exist(final_resource_path) |
|||
test.must_match(final_resource_path, |
|||
'This is included in the framework bundle.\n') |
|||
|
|||
test.must_exist(final_plist_path) |
|||
test.must_contain(final_plist_path, '''\ |
|||
\t<key>RandomKey</key> |
|||
\t<string>RandomValue</string>''') |
|||
|
|||
# Touch the dependency's bundle resource, and check that the modification |
|||
# makes it all the way into the app bundle: |
|||
test.sleep() |
|||
test.write('postbuild-copy-bundle/resource_file.sb', 'New text\n') |
|||
test.build('test.gyp', 'test_app', chdir=CHDIR) |
|||
|
|||
test.must_exist(final_resource_path) |
|||
test.must_match(final_resource_path, 'New text\n') |
|||
|
|||
# Check the same for the plist file. |
|||
test.sleep() |
|||
contents = test.read('postbuild-copy-bundle/Framework-Info.plist') |
|||
contents = contents.replace('RandomValue', 'NewRandomValue') |
|||
test.write('postbuild-copy-bundle/Framework-Info.plist', contents) |
|||
test.build('test.gyp', 'test_app', chdir=CHDIR) |
|||
|
|||
test.must_exist(final_plist_path) |
|||
test.must_contain(final_plist_path, '''\ |
|||
\t<key>RandomKey</key> |
|||
\t<string>NewRandomValue</string>''') |
|||
|
|||
test.pass_test() |
@ -0,0 +1,29 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2012 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. |
|||
|
|||
""" |
|||
Verifies that a postbuild invoking |defaults| works. |
|||
""" |
|||
|
|||
import TestGyp |
|||
|
|||
import sys |
|||
|
|||
if sys.platform == 'darwin': |
|||
test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) |
|||
|
|||
CHDIR = 'postbuild-defaults' |
|||
test.run_gyp('test.gyp', chdir=CHDIR) |
|||
test.build('test.gyp', test.ALL, chdir=CHDIR) |
|||
|
|||
result_file = test.built_file_path('result', chdir=CHDIR) |
|||
test.must_exist(result_file) |
|||
test.must_contain(result_file, '''\ |
|||
Test |
|||
${PRODUCT_NAME} |
|||
''') |
|||
|
|||
test.pass_test() |
@ -0,0 +1,26 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2012 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. |
|||
|
|||
""" |
|||
Verifies that a postbuild work in projects with multiple configurations. |
|||
""" |
|||
|
|||
import TestGyp |
|||
|
|||
import sys |
|||
|
|||
if sys.platform == 'darwin': |
|||
test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) |
|||
|
|||
CHDIR = 'postbuild-multiple-configurations' |
|||
test.run_gyp('test.gyp', chdir=CHDIR) |
|||
|
|||
for configuration in ['Debug', 'Release']: |
|||
test.set_configuration(configuration) |
|||
test.build('test.gyp', test.ALL, chdir=CHDIR) |
|||
test.built_file_must_exist('postbuild-file', chdir=CHDIR) |
|||
|
|||
test.pass_test() |
@ -0,0 +1,28 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2012 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. |
|||
|
|||
""" |
|||
Verifies that a postbuilds on static libraries work, and that sourceless |
|||
libraries don't cause failures at gyp time. |
|||
""" |
|||
|
|||
import TestGyp |
|||
|
|||
import sys |
|||
|
|||
if sys.platform == 'darwin': |
|||
test = TestGyp.TestGyp(formats=['make', 'xcode']) |
|||
|
|||
CHDIR = 'postbuild-static-library' |
|||
test.run_gyp('test.gyp', chdir=CHDIR) |
|||
test.build('test.gyp', 'my_lib', chdir=CHDIR) |
|||
# Building my_sourceless_lib doesn't work with make. gyp should probably |
|||
# forbid sourceless static libraries, since they're pretty pointless. |
|||
# But they shouldn't cause gyp time exceptions. |
|||
|
|||
test.built_file_must_exist('postbuild-file', chdir=CHDIR) |
|||
|
|||
test.pass_test() |
@ -0,0 +1,46 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2012 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. |
|||
|
|||
""" |
|||
Verifies that bundles that have no 'sources' (pure resource containers) work. |
|||
""" |
|||
|
|||
import TestGyp |
|||
|
|||
import sys |
|||
|
|||
if sys.platform == 'darwin': |
|||
test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode']) |
|||
|
|||
test.run_gyp('test.gyp', chdir='sourceless-module') |
|||
|
|||
# Just needs to build without errors. |
|||
test.build('test.gyp', 'empty_bundle', chdir='sourceless-module') |
|||
test.built_file_must_not_exist( |
|||
'empty_bundle.bundle', chdir='sourceless-module') |
|||
|
|||
# Needs to build, and contain a resource. |
|||
test.build('test.gyp', 'resource_bundle', chdir='sourceless-module') |
|||
|
|||
test.built_file_must_exist( |
|||
'resource_bundle.bundle/Contents/Resources/foo.manifest', |
|||
chdir='sourceless-module') |
|||
test.built_file_must_not_exist( |
|||
'resource_bundle.bundle/Contents/MacOS/resource_bundle', |
|||
chdir='sourceless-module') |
|||
|
|||
# Needs to build and cause the bundle to be built. |
|||
test.build( |
|||
'test.gyp', 'dependent_on_resource_bundle', chdir='sourceless-module') |
|||
|
|||
test.built_file_must_exist( |
|||
'resource_bundle.bundle/Contents/Resources/foo.manifest', |
|||
chdir='sourceless-module') |
|||
test.built_file_must_not_exist( |
|||
'resource_bundle.bundle/Contents/MacOS/resource_bundle', |
|||
chdir='sourceless-module') |
|||
|
|||
test.pass_test() |
@ -0,0 +1 @@ |
|||
Make things live in a subdirectory, to make sure that DEPTH works correctly. |
@ -0,0 +1,10 @@ |
|||
// Copyright (c) 2012 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.
|
|||
|
|||
#include <iostream> |
|||
|
|||
int main() { |
|||
std::cout << "Hello, world!" << std::endl; |
|||
return 0; |
|||
} |
@ -0,0 +1,7 @@ |
|||
// Copyright (c) 2012 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.
|
|||
|
|||
int my_foo(int x) { |
|||
return x + 1; |
|||
} |
@ -0,0 +1,66 @@ |
|||
# Copyright (c) 2012 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. |
|||
|
|||
{ |
|||
'targets': [ |
|||
{ |
|||
'target_name': 'libraries-test', |
|||
'type': 'executable', |
|||
'sources': [ |
|||
'hello.cc', |
|||
], |
|||
'link_settings': { |
|||
'libraries': [ |
|||
'libcrypto.dylib', |
|||
'libfl.a', |
|||
], |
|||
}, |
|||
}, |
|||
{ |
|||
# This creates a static library and puts it in a nonstandard location for |
|||
# libraries-search-path-test. |
|||
'target_name': 'mylib', |
|||
'type': 'static_library', |
|||
'sources': [ |
|||
'mylib.c', |
|||
], |
|||
'postbuilds': [ |
|||
{ |
|||
'postbuild_name': 'Make a secret location', |
|||
'action': [ |
|||
'mkdir', |
|||
'-p', |
|||
'${SRCROOT}/../secret_location', |
|||
], |
|||
}, |
|||
{ |
|||
'postbuild_name': 'Copy to secret location, with secret name', |
|||
'action': [ |
|||
'cp', |
|||
'${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}', |
|||
'${SRCROOT}/../secret_location/libmysecretlib.a', |
|||
], |
|||
}, |
|||
], |
|||
}, |
|||
{ |
|||
'target_name': 'libraries-search-path-test', |
|||
'type': 'executable', |
|||
'dependencies': [ 'mylib' ], |
|||
'sources': [ |
|||
'hello.cc', |
|||
], |
|||
'xcode_settings': { |
|||
'LIBRARY_SEARCH_PATHS': [ |
|||
'<(DEPTH)/secret_location', |
|||
], |
|||
}, |
|||
'link_settings': { |
|||
'libraries': [ |
|||
'libmysecretlib.a', |
|||
], |
|||
}, |
|||
}, |
|||
], |
|||
} |
@ -0,0 +1,15 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|||
<plist version="1.0"> |
|||
<dict> |
|||
<!-- Not a valid plist file since it's missing so much. That's fine. --> |
|||
<key>CFBundlePackageType</key> |
|||
<string>APPL</string> |
|||
<key>CFBundleSignature</key> |
|||
<string>????</string> |
|||
<key>My Variable</key> |
|||
<string>${MY_VAR}</string> |
|||
<key>CFlags</key> |
|||
<string>${OTHER_CFLAGS}</string> |
|||
</dict> |
|||
</plist> |
@ -0,0 +1,7 @@ |
|||
// Copyright (c) 2012 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.
|
|||
|
|||
int main() { |
|||
return 0; |
|||
} |
@ -0,0 +1,24 @@ |
|||
# Copyright (c) 2012 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. |
|||
{ |
|||
'targets': [ |
|||
{ |
|||
'target_name': 'test_app', |
|||
'product_name': 'Test', |
|||
'type': 'executable', |
|||
'mac_bundle': 1, |
|||
'sources': [ 'main.c', ], |
|||
'xcode_settings': { |
|||
'INFOPLIST_FILE': 'Info.plist', |
|||
'MY_VAR': 'some expansion', |
|||
'OTHER_CFLAGS': [ |
|||
# Just some (more than one) random flags. |
|||
'-fstack-protector-all', |
|||
'-fno-strict-aliasing', |
|||
'-DS="A Space"', # Would normally be in 'defines' |
|||
], |
|||
}, |
|||
}, |
|||
], |
|||
} |
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|||
<plist version="1.0"> |
|||
<dict> |
|||
<key>CFBundleDevelopmentRegion</key> |
|||
<string>English</string> |
|||
<key>CFBundleExecutable</key> |
|||
<string>${EXECUTABLE_NAME}</string> |
|||
<key>CFBundleIconFile</key> |
|||
<string></string> |
|||
<key>CFBundleIdentifier</key> |
|||
<string>com.yourcompany.${PRODUCT_NAME}</string> |
|||
<key>CFBundleInfoDictionaryVersion</key> |
|||
<string>6.0</string> |
|||
<key>CFBundleName</key> |
|||
<string>${PRODUCT_NAME}</string> |
|||
<key>CFBundlePackageType</key> |
|||
<string>FMWK</string> |
|||
<key>CFBundleShortVersionString</key> |
|||
<string>1.0</string> |
|||
<key>CFBundleSignature</key> |
|||
<string>????</string> |
|||
<key>CFBundleVersion</key> |
|||
<string>1</string> |
|||
<key>NSPrincipalClass</key> |
|||
<string></string> |
|||
<key>RandomKey</key> |
|||
<string>RandomValue</string> |
|||
</dict> |
|||
</plist> |
@ -0,0 +1,32 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|||
<plist version="1.0"> |
|||
<dict> |
|||
<key>CFBundleDevelopmentRegion</key> |
|||
<string>English</string> |
|||
<key>CFBundleExecutable</key> |
|||
<string>${EXECUTABLE_NAME}</string> |
|||
<key>CFBundleIconFile</key> |
|||
<string></string> |
|||
<key>CFBundleIdentifier</key> |
|||
<string>com.google.${PRODUCT_NAME}</string> |
|||
<key>CFBundleInfoDictionaryVersion</key> |
|||
<string>6.0</string> |
|||
<key>CFBundleName</key> |
|||
<string>${PRODUCT_NAME}</string> |
|||
<key>CFBundlePackageType</key> |
|||
<string>APPL</string> |
|||
<key>CFBundleShortVersionString</key> |
|||
<string>1.0</string> |
|||
<key>CFBundleSignature</key> |
|||
<string>????</string> |
|||
<key>CFBundleVersion</key> |
|||
<string>1</string> |
|||
<key>LSMinimumSystemVersion</key> |
|||
<string>${MACOSX_DEPLOYMENT_TARGET}</string> |
|||
<key>NSMainNibFile</key> |
|||
<string>MainMenu</string> |
|||
<key>NSPrincipalClass</key> |
|||
<string>NSApplication</string> |
|||
</dict> |
|||
</plist> |
@ -0,0 +1,4 @@ |
|||
// Copyright (c) 2012 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.
|
|||
int main() {} |
@ -0,0 +1,9 @@ |
|||
#!/bin/bash |
|||
|
|||
# Copyright (c) 2012 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. |
|||
|
|||
set -e |
|||
|
|||
rsync -acC --delete "$1" "$2" |
@ -0,0 +1 @@ |
|||
This is included in the framework bundle. |
@ -0,0 +1,43 @@ |
|||
# Copyright (c) 2012 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. |
|||
{ |
|||
'targets': [ |
|||
{ |
|||
'target_name': 'test_bundle', |
|||
'product_name': 'My Framework', |
|||
'type': 'shared_library', |
|||
'mac_bundle': 1, |
|||
'sources': [ 'empty.c', ], |
|||
'xcode_settings': { |
|||
'INFOPLIST_FILE': 'Framework-Info.plist', |
|||
}, |
|||
'mac_bundle_resources': [ |
|||
'resource_file.sb', |
|||
], |
|||
}, |
|||
{ |
|||
'target_name': 'test_app', |
|||
'product_name': 'Test App', |
|||
'type': 'executable', |
|||
'mac_bundle': 1, |
|||
'dependencies': [ |
|||
'test_bundle', |
|||
], |
|||
'sources': [ 'main.c', ], |
|||
'xcode_settings': { |
|||
'INFOPLIST_FILE': 'TestApp-Info.plist', |
|||
}, |
|||
'postbuilds': [ |
|||
{ |
|||
'postbuild_name': 'Copy dependent framework into app', |
|||
'action': [ |
|||
'./postbuild-copy-framework.sh', |
|||
'${BUILT_PRODUCTS_DIR}/My Framework.framework', |
|||
'${BUILT_PRODUCTS_DIR}/${CONTENTS_FOLDER_PATH}/', |
|||
], |
|||
}, |
|||
], |
|||
}, |
|||
], |
|||
} |
@ -0,0 +1,13 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|||
<plist version="1.0"> |
|||
<dict> |
|||
<!-- Not a valid plist file since it's missing so much. That's fine. --> |
|||
<key>CFBundlePackageType</key> |
|||
<string>APPL</string> |
|||
<key>CFBundleSignature</key> |
|||
<string>????</string> |
|||
<key>CFBundleName</key> |
|||
<string>${PRODUCT_NAME}</string> |
|||
</dict> |
|||
</plist> |
@ -0,0 +1,7 @@ |
|||
// Copyright (c) 2012 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.
|
|||
|
|||
int main() { |
|||
return 0; |
|||
} |
@ -0,0 +1,15 @@ |
|||
#!/bin/bash |
|||
# Copyright (c) 2012 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. |
|||
|
|||
set -e |
|||
|
|||
# This is the built Info.plist in the output directory. |
|||
PLIST="${BUILT_PRODUCTS_DIR}"/Test.app/Contents/Info # No trailing .plist |
|||
echo $(defaults read "${PLIST}" "CFBundleName") > "${BUILT_PRODUCTS_DIR}/result" |
|||
|
|||
# This is the source Info.plist next to this script file. |
|||
PLIST="${SRCROOT}"/Info # No trailing .plist |
|||
echo $(defaults read "${PLIST}" "CFBundleName") \ |
|||
>> "${BUILT_PRODUCTS_DIR}/result" |
@ -0,0 +1,26 @@ |
|||
# Copyright (c) 2012 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. |
|||
{ |
|||
'targets': [ |
|||
{ |
|||
'target_name': 'test_app', |
|||
'product_name': 'Test', |
|||
'type': 'executable', |
|||
'mac_bundle': 1, |
|||
'sources': [ 'main.c', ], |
|||
'xcode_settings': { |
|||
'INFOPLIST_FILE': 'Info.plist', |
|||
}, |
|||
'postbuilds': [ |
|||
{ |
|||
'postbuild_name': 'Postbuild that calls defaults', |
|||
'action': [ |
|||
'./postbuild-defaults.sh', |
|||
'${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}', |
|||
], |
|||
}, |
|||
], |
|||
}, |
|||
], |
|||
} |
@ -0,0 +1,4 @@ |
|||
// Copyright (c) 2012 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.
|
|||
int main() {} |
@ -0,0 +1,7 @@ |
|||
#!/bin/bash |
|||
|
|||
# Copyright (c) 2012 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. |
|||
|
|||
touch "${BUILT_PRODUCTS_DIR}/postbuild-file" |
@ -0,0 +1,26 @@ |
|||
# Copyright (c) 2012 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. |
|||
{ |
|||
'target_defaults': { |
|||
'configurations': { |
|||
'Debug': {}, |
|||
'Release': {}, |
|||
}, |
|||
}, |
|||
'targets': [ |
|||
{ |
|||
'target_name': 'random_target', |
|||
'type': 'executable', |
|||
'sources': [ 'main.c', ], |
|||
'postbuilds': [ |
|||
{ |
|||
'postbuild_name': 'Touch a file.', |
|||
'action': [ |
|||
'./postbuild-touch-file.sh', |
|||
], |
|||
}, |
|||
], |
|||
}, |
|||
], |
|||
} |
@ -0,0 +1,4 @@ |
|||
// Copyright (c) 2012 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.
|
|||
void f() {} |
@ -0,0 +1,7 @@ |
|||
#!/bin/bash |
|||
|
|||
# Copyright (c) 2012 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. |
|||
|
|||
touch "${BUILT_PRODUCTS_DIR}/$1" |
@ -0,0 +1,34 @@ |
|||
# Copyright (c) 2012 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. |
|||
{ |
|||
'targets': [ |
|||
{ |
|||
'target_name': 'my_lib', |
|||
'type': 'static_library', |
|||
'sources': [ 'empty.c', ], |
|||
'postbuilds': [ |
|||
{ |
|||
'postbuild_name': 'Postbuild that touches a file', |
|||
'action': [ |
|||
'./postbuild-touch-file.sh', 'postbuild-file' |
|||
], |
|||
}, |
|||
], |
|||
}, |
|||
|
|||
{ |
|||
'target_name': 'my_sourceless_lib', |
|||
'type': 'static_library', |
|||
'dependencies': [ 'my_lib' ], |
|||
'postbuilds': [ |
|||
{ |
|||
'postbuild_name': 'Postbuild that touches a file', |
|||
'action': [ |
|||
'./postbuild-touch-file.sh', 'postbuild-file-sourceless' |
|||
], |
|||
}, |
|||
], |
|||
}, |
|||
], |
|||
} |
@ -0,0 +1 @@ |
|||
MyInt f() { return 0; } |
@ -0,0 +1 @@ |
|||
MyInt f() { return 0; } |
@ -0,0 +1 @@ |
|||
MyInt f() { return 0; } |
@ -0,0 +1,32 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
|||
<plist version="1.0"> |
|||
<dict> |
|||
<key>CFBundleDevelopmentRegion</key> |
|||
<string>English</string> |
|||
<key>CFBundleExecutable</key> |
|||
<string>${EXECUTABLE_NAME}</string> |
|||
<key>CFBundleIconFile</key> |
|||
<string></string> |
|||
<key>CFBundleIdentifier</key> |
|||
<string>com.google.${PRODUCT_NAME}</string> |
|||
<key>CFBundleInfoDictionaryVersion</key> |
|||
<string>6.0</string> |
|||
<key>CFBundleName</key> |
|||
<string>${PRODUCT_NAME}</string> |
|||
<key>CFBundlePackageType</key> |
|||
<string>APPL</string> |
|||
<key>CFBundleShortVersionString</key> |
|||
<string>1.0</string> |
|||
<key>CFBundleSignature</key> |
|||
<string>????</string> |
|||
<key>CFBundleVersion</key> |
|||
<string>1</string> |
|||
<key>LSMinimumSystemVersion</key> |
|||
<string>${MACOSX_DEPLOYMENT_TARGET}</string> |
|||
<key>NSMainNibFile</key> |
|||
<string>MainMenu</string> |
|||
<key>NSPrincipalClass</key> |
|||
<string>NSApplication</string> |
|||
</dict> |
|||
</plist> |
@ -0,0 +1,6 @@ |
|||
#!/bin/bash |
|||
|
|||
set -e |
|||
|
|||
sleep 1 # mtime resolution is 1 sec on unix. |
|||
touch "$1" |
@ -0,0 +1 @@ |
|||
int main() {} |
@ -0,0 +1,56 @@ |
|||
# 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. |
|||
{ |
|||
'targets': [ |
|||
{ |
|||
'target_name': 'test_app', |
|||
'product_name': 'Test App', |
|||
'type': 'executable', |
|||
'mac_bundle': 1, |
|||
'sources': [ |
|||
'main.c', |
|||
], |
|||
'xcode_settings': { |
|||
'INFOPLIST_FILE': 'TestApp-Info.plist', |
|||
}, |
|||
}, |
|||
{ |
|||
'target_name': 'test_app_postbuilds', |
|||
'product_name': 'Test App 2', |
|||
'type': 'executable', |
|||
'mac_bundle': 1, |
|||
'sources': [ |
|||
'main.c', |
|||
], |
|||
'xcode_settings': { |
|||
'INFOPLIST_FILE': 'TestApp-Info.plist', |
|||
}, |
|||
'postbuilds': [ |
|||
{ |
|||
'postbuild_name': 'Postbuild that touches the app binary', |
|||
'action': [ |
|||
'./delay-touch.sh', '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}', |
|||
], |
|||
}, |
|||
], |
|||
}, |
|||
{ |
|||
'target_name': 'test_framework_postbuilds', |
|||
'product_name': 'Test Framework', |
|||
'type': 'shared_library', |
|||
'mac_bundle': 1, |
|||
'sources': [ |
|||
'empty.c', |
|||
], |
|||
'postbuilds': [ |
|||
{ |
|||
'postbuild_name': 'Postbuild that touches the framework binary', |
|||
'action': [ |
|||
'./delay-touch.sh', '${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}', |
|||
], |
|||
}, |
|||
], |
|||
}, |
|||
], |
|||
} |
@ -0,0 +1 @@ |
|||
int main() {} |
@ -0,0 +1,39 @@ |
|||
# Copyright (c) 2012 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. |
|||
{ |
|||
'targets': [ |
|||
{ |
|||
'target_name': 'empty_bundle', |
|||
'type': 'loadable_module', |
|||
'mac_bundle': 1, |
|||
}, |
|||
{ |
|||
'target_name': 'resource_bundle', |
|||
'type': 'loadable_module', |
|||
'mac_bundle': 1, |
|||
'actions': [ |
|||
{ |
|||
'action_name': 'Add Resource', |
|||
'inputs': [], |
|||
'outputs': [ |
|||
'<(INTERMEDIATE_DIR)/app_manifest/foo.manifest', |
|||
], |
|||
'action': [ |
|||
'touch', '<(INTERMEDIATE_DIR)/app_manifest/foo.manifest', |
|||
], |
|||
'process_outputs_as_mac_bundle_resources': 1, |
|||
}, |
|||
], |
|||
}, |
|||
{ |
|||
'target_name': 'dependent_on_resource_bundle', |
|||
'type': 'executable', |
|||
'sources': [ 'empty.c' ], |
|||
'dependencies': [ |
|||
'resource_bundle', |
|||
], |
|||
}, |
|||
], |
|||
} |
|||
|
@ -0,0 +1,16 @@ |
|||
#!/bin/bash |
|||
# Copyright (c) 2012 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. |
|||
|
|||
set -e |
|||
|
|||
# Check for "not set", not just "empty": |
|||
[[ ! $MACH_O_TYPE && ${MACH_O_TYPE-_} ]] |
|||
[[ ! $PRODUCT_TYPE && ${PRODUCT_TYPE-_} ]] |
|||
test $PRODUCT_NAME = nonbundle_none |
|||
[[ ! $FULL_PRODUCT_NAME && ${FULL_PRODUCT_NAME-_} ]] |
|||
|
|||
[[ ! $EXECUTABLE_NAME && ${EXECUTABLE_NAME-_} ]] |
|||
[[ ! $EXECUTABLE_PATH && ${EXECUTABLE_PATH-_} ]] |
|||
[[ ! $WRAPPER_NAME && ${WRAPPER_NAME-_} ]] |
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue