mirror of https://github.com/lukechilds/node.git
Ben Noordhuis
13 years ago
611 changed files with 2983 additions and 22714 deletions
@ -0,0 +1,44 @@ |
|||
#!/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 common.py file.""" |
|||
|
|||
import gyp.common |
|||
import unittest |
|||
|
|||
|
|||
class TestTopologicallySorted(unittest.TestCase): |
|||
def test_Valid(self): |
|||
"""Test that sorting works on a valid graph with one possible order.""" |
|||
graph = { |
|||
'a': ['b', 'c'], |
|||
'b': [], |
|||
'c': ['d'], |
|||
'd': ['b'], |
|||
} |
|||
def GetEdge(node): |
|||
return tuple(graph[node]) |
|||
self.assertEqual( |
|||
gyp.common.TopologicallySorted(graph.keys(), GetEdge), |
|||
['a', 'c', 'd', 'b']) |
|||
|
|||
def test_Cycle(self): |
|||
"""Test that an exception is thrown on a cyclic graph.""" |
|||
graph = { |
|||
'a': ['b'], |
|||
'b': ['c'], |
|||
'c': ['d'], |
|||
'd': ['a'], |
|||
} |
|||
def GetEdge(node): |
|||
return tuple(graph[node]) |
|||
self.assertRaises( |
|||
gyp.common.CycleError, gyp.common.TopologicallySorted, |
|||
graph.keys(), GetEdge) |
|||
|
|||
|
|||
if __name__ == '__main__': |
|||
unittest.main() |
@ -0,0 +1,271 @@ |
|||
# 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. |
|||
|
|||
"""GYP backend that generates Eclipse CDT settings files. |
|||
|
|||
This backend DOES NOT generate Eclipse CDT projects. Instead, it generates XML |
|||
files that can be imported into an Eclipse CDT project. The XML file contains a |
|||
list of include paths and symbols (i.e. defines). |
|||
|
|||
Because a full .cproject definition is not created by this generator, it's not |
|||
possible to properly define the include dirs and symbols for each file |
|||
individually. Instead, one set of includes/symbols is generated for the entire |
|||
project. This works fairly well (and is a vast improvement in general), but may |
|||
still result in a few indexer issues here and there. |
|||
|
|||
This generator has no automated tests, so expect it to be broken. |
|||
""" |
|||
|
|||
import os.path |
|||
import subprocess |
|||
import gyp |
|||
import gyp.common |
|||
import shlex |
|||
|
|||
generator_wants_static_library_dependencies_adjusted = False |
|||
|
|||
generator_default_variables = { |
|||
} |
|||
|
|||
for dirname in ['INTERMEDIATE_DIR', 'PRODUCT_DIR', 'LIB_DIR', 'SHARED_LIB_DIR']: |
|||
# Some gyp steps fail if these are empty(!). |
|||
generator_default_variables[dirname] = 'dir' |
|||
|
|||
for unused in ['RULE_INPUT_PATH', 'RULE_INPUT_ROOT', 'RULE_INPUT_NAME', |
|||
'RULE_INPUT_DIRNAME', 'RULE_INPUT_EXT', |
|||
'EXECUTABLE_PREFIX', 'EXECUTABLE_SUFFIX', |
|||
'STATIC_LIB_PREFIX', 'STATIC_LIB_SUFFIX', |
|||
'SHARED_LIB_PREFIX', 'SHARED_LIB_SUFFIX']: |
|||
generator_default_variables[unused] = '' |
|||
|
|||
# Include dirs will occasionaly use the SHARED_INTERMEDIATE_DIR variable as |
|||
# part of the path when dealing with generated headers. This value will be |
|||
# replaced dynamically for each configuration. |
|||
generator_default_variables['SHARED_INTERMEDIATE_DIR'] = \ |
|||
'$SHARED_INTERMEDIATES_DIR' |
|||
|
|||
|
|||
def CalculateVariables(default_variables, params): |
|||
generator_flags = params.get('generator_flags', {}) |
|||
for key, val in generator_flags.items(): |
|||
default_variables.setdefault(key, val) |
|||
default_variables.setdefault('OS', gyp.common.GetFlavor(params)) |
|||
|
|||
|
|||
def CalculateGeneratorInputInfo(params): |
|||
"""Calculate the generator specific info that gets fed to input (called by |
|||
gyp).""" |
|||
generator_flags = params.get('generator_flags', {}) |
|||
if generator_flags.get('adjust_static_libraries', False): |
|||
global generator_wants_static_library_dependencies_adjusted |
|||
generator_wants_static_library_dependencies_adjusted = True |
|||
|
|||
|
|||
def GetAllIncludeDirectories(target_list, target_dicts, |
|||
shared_intermediates_dir, config_name): |
|||
"""Calculate the set of include directories to be used. |
|||
|
|||
Returns: |
|||
A list including all the include_dir's specified for every target followed |
|||
by any include directories that were added as cflag compiler options. |
|||
""" |
|||
|
|||
gyp_includes_set = set() |
|||
compiler_includes_list = [] |
|||
|
|||
for target_name in target_list: |
|||
target = target_dicts[target_name] |
|||
if config_name in target['configurations']: |
|||
config = target['configurations'][config_name] |
|||
|
|||
# Look for any include dirs that were explicitly added via cflags. This |
|||
# may be done in gyp files to force certain includes to come at the end. |
|||
# TODO(jgreenwald): Change the gyp files to not abuse cflags for this, and |
|||
# remove this. |
|||
cflags = config['cflags'] |
|||
for cflag in cflags: |
|||
include_dir = '' |
|||
if cflag.startswith('-I'): |
|||
include_dir = cflag[2:] |
|||
if include_dir and not include_dir in compiler_includes_list: |
|||
compiler_includes_list.append(include_dir) |
|||
|
|||
# Find standard gyp include dirs. |
|||
if config.has_key('include_dirs'): |
|||
include_dirs = config['include_dirs'] |
|||
for include_dir in include_dirs: |
|||
include_dir = include_dir.replace('$SHARED_INTERMEDIATES_DIR', |
|||
shared_intermediates_dir) |
|||
if not os.path.isabs(include_dir): |
|||
base_dir = os.path.dirname(target_name) |
|||
|
|||
include_dir = base_dir + '/' + include_dir |
|||
include_dir = os.path.abspath(include_dir) |
|||
|
|||
if not include_dir in gyp_includes_set: |
|||
gyp_includes_set.add(include_dir) |
|||
|
|||
|
|||
# Generate a list that has all the include dirs. |
|||
all_includes_list = list(gyp_includes_set) |
|||
all_includes_list.sort() |
|||
for compiler_include in compiler_includes_list: |
|||
if not compiler_include in gyp_includes_set: |
|||
all_includes_list.append(compiler_include) |
|||
|
|||
# All done. |
|||
return all_includes_list |
|||
|
|||
|
|||
def GetCompilerPath(target_list, target_dicts, data): |
|||
"""Determine a command that can be used to invoke the compiler. |
|||
|
|||
Returns: |
|||
If this is a gyp project that has explicit make settings, try to determine |
|||
the compiler from that. Otherwise, see if a compiler was specified via the |
|||
CC_target environment variable. |
|||
""" |
|||
|
|||
# First, see if the compiler is configured in make's settings. |
|||
build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0]) |
|||
make_global_settings_dict = data[build_file].get('make_global_settings', {}) |
|||
for key, value in make_global_settings_dict: |
|||
if key in ['CC', 'CXX']: |
|||
return value |
|||
|
|||
# Check to see if the compiler was specified as an environment variable. |
|||
for key in ['CC_target', 'CC', 'CXX']: |
|||
compiler = os.environ.get(key) |
|||
if compiler: |
|||
return compiler |
|||
|
|||
return 'gcc' |
|||
|
|||
|
|||
def GetAllDefines(target_list, target_dicts, data, config_name): |
|||
"""Calculate the defines for a project. |
|||
|
|||
Returns: |
|||
A dict that includes explict defines declared in gyp files along with all of |
|||
the default defines that the compiler uses. |
|||
""" |
|||
|
|||
# Get defines declared in the gyp files. |
|||
all_defines = {} |
|||
for target_name in target_list: |
|||
target = target_dicts[target_name] |
|||
|
|||
if config_name in target['configurations']: |
|||
config = target['configurations'][config_name] |
|||
for define in config['defines']: |
|||
split_define = define.split('=', 1) |
|||
if len(split_define) == 1: |
|||
split_define.append('1') |
|||
if split_define[0].strip() in all_defines: |
|||
# Already defined |
|||
continue |
|||
|
|||
all_defines[split_define[0].strip()] = split_define[1].strip() |
|||
|
|||
# Get default compiler defines (if possible). |
|||
cc_target = GetCompilerPath(target_list, target_dicts, data) |
|||
if cc_target: |
|||
command = shlex.split(cc_target) |
|||
command.extend(['-E', '-dM', '-']) |
|||
cpp_proc = subprocess.Popen(args=command, cwd='.', |
|||
stdin=subprocess.PIPE, stdout=subprocess.PIPE) |
|||
cpp_output = cpp_proc.communicate()[0] |
|||
cpp_lines = cpp_output.split('\n') |
|||
for cpp_line in cpp_lines: |
|||
if not cpp_line.strip(): |
|||
continue |
|||
cpp_line_parts = cpp_line.split(' ', 2) |
|||
key = cpp_line_parts[1] |
|||
if len(cpp_line_parts) >= 3: |
|||
val = cpp_line_parts[2] |
|||
else: |
|||
val = '1' |
|||
all_defines[key] = val |
|||
|
|||
return all_defines |
|||
|
|||
|
|||
def WriteIncludePaths(out, eclipse_langs, include_dirs): |
|||
"""Write the includes section of a CDT settings export file.""" |
|||
|
|||
out.write(' <section name="org.eclipse.cdt.internal.ui.wizards.' \ |
|||
'settingswizards.IncludePaths">\n') |
|||
out.write(' <language name="holder for library settings"></language>\n') |
|||
for lang in eclipse_langs: |
|||
out.write(' <language name="%s">\n' % lang) |
|||
for include_dir in include_dirs: |
|||
out.write(' <includepath workspace_path="false">%s</includepath>\n' % |
|||
include_dir) |
|||
out.write(' </language>\n') |
|||
out.write(' </section>\n') |
|||
|
|||
|
|||
def WriteMacros(out, eclipse_langs, defines): |
|||
"""Write the macros section of a CDT settings export file.""" |
|||
|
|||
out.write(' <section name="org.eclipse.cdt.internal.ui.wizards.' \ |
|||
'settingswizards.Macros">\n') |
|||
out.write(' <language name="holder for library settings"></language>\n') |
|||
for lang in eclipse_langs: |
|||
out.write(' <language name="%s">\n' % lang) |
|||
for key in sorted(defines.iterkeys()): |
|||
out.write(' <macro><name>%s</name><value>%s</value></macro>\n' % |
|||
(key, defines[key])) |
|||
out.write(' </language>\n') |
|||
out.write(' </section>\n') |
|||
|
|||
|
|||
def GenerateOutputForConfig(target_list, target_dicts, data, params, |
|||
config_name): |
|||
options = params['options'] |
|||
generator_flags = params.get('generator_flags', {}) |
|||
|
|||
# build_dir: relative path from source root to our output files. |
|||
# e.g. "out/Debug" |
|||
build_dir = os.path.join(generator_flags.get('output_dir', 'out'), |
|||
config_name) |
|||
|
|||
toplevel_build = os.path.join(options.toplevel_dir, build_dir) |
|||
shared_intermediate_dir = os.path.join(toplevel_build, 'obj', 'gen') |
|||
|
|||
if not os.path.exists(toplevel_build): |
|||
os.makedirs(toplevel_build) |
|||
out = open(os.path.join(toplevel_build, 'eclipse-cdt-settings.xml'), 'w') |
|||
|
|||
out.write('<?xml version="1.0" encoding="UTF-8"?>\n') |
|||
out.write('<cdtprojectproperties>\n') |
|||
|
|||
eclipse_langs = ['C++ Source File', 'C Source File', 'Assembly Source File', |
|||
'GNU C++', 'GNU C', 'Assembly'] |
|||
include_dirs = GetAllIncludeDirectories(target_list, target_dicts, |
|||
shared_intermediate_dir, config_name) |
|||
WriteIncludePaths(out, eclipse_langs, include_dirs) |
|||
defines = GetAllDefines(target_list, target_dicts, data, config_name) |
|||
WriteMacros(out, eclipse_langs, defines) |
|||
|
|||
out.write('</cdtprojectproperties>\n') |
|||
out.close() |
|||
|
|||
|
|||
def GenerateOutput(target_list, target_dicts, data, params): |
|||
"""Generate an XML settings file that can be imported into a CDT project.""" |
|||
|
|||
if params['options'].generator_output: |
|||
raise NotImplementedError, "--generator_output not implemented for eclipse" |
|||
|
|||
user_config = params.get('generator_flags', {}).get('config', None) |
|||
if user_config: |
|||
GenerateOutputForConfig(target_list, target_dicts, data, params, |
|||
user_config) |
|||
else: |
|||
config_names = target_dicts[target_list[0]]['configurations'].keys() |
|||
for config_name in config_names: |
|||
GenerateOutputForConfig(target_list, target_dicts, data, params, |
|||
config_name) |
|||
|
File diff suppressed because it is too large
@ -0,0 +1,642 @@ |
|||
# 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 helps emulate Visual Studio 2008 behavior on top of other |
|||
build systems, primarily ninja. |
|||
""" |
|||
|
|||
import os |
|||
import re |
|||
import subprocess |
|||
import sys |
|||
|
|||
import gyp.MSVSVersion |
|||
|
|||
windows_quoter_regex = re.compile(r'(\\*)"') |
|||
|
|||
def QuoteForRspFile(arg): |
|||
"""Quote a command line argument so that it appears as one argument when |
|||
processed via cmd.exe and parsed by CommandLineToArgvW (as is typical for |
|||
Windows programs).""" |
|||
# See http://goo.gl/cuFbX and http://goo.gl/dhPnp including the comment |
|||
# threads. This is actually the quoting rules for CommandLineToArgvW, not |
|||
# for the shell, because the shell doesn't do anything in Windows. This |
|||
# works more or less because most programs (including the compiler, etc.) |
|||
# use that function to handle command line arguments. |
|||
|
|||
# For a literal quote, CommandLineToArgvW requires 2n+1 backslashes |
|||
# preceding it, and results in n backslashes + the quote. So we substitute |
|||
# in 2* what we match, +1 more, plus the quote. |
|||
arg = windows_quoter_regex.sub(lambda mo: 2 * mo.group(1) + '\\"', arg) |
|||
|
|||
# %'s also need to be doubled otherwise they're interpreted as batch |
|||
# positional arguments. Also make sure to escape the % so that they're |
|||
# passed literally through escaping so they can be singled to just the |
|||
# original %. Otherwise, trying to pass the literal representation that |
|||
# looks like an environment variable to the shell (e.g. %PATH%) would fail. |
|||
arg = arg.replace('%', '%%') |
|||
|
|||
# These commands are used in rsp files, so no escaping for the shell (via ^) |
|||
# is necessary. |
|||
|
|||
# Finally, wrap the whole thing in quotes so that the above quote rule |
|||
# applies and whitespace isn't a word break. |
|||
return '"' + arg + '"' |
|||
|
|||
|
|||
def EncodeRspFileList(args): |
|||
"""Process a list of arguments using QuoteCmdExeArgument.""" |
|||
# Note that the first argument is assumed to be the command. Don't add |
|||
# quotes around it because then built-ins like 'echo', etc. won't work. |
|||
# Take care to normpath only the path in the case of 'call ../x.bat' because |
|||
# otherwise the whole thing is incorrectly interpreted as a path and not |
|||
# normalized correctly. |
|||
if not args: return '' |
|||
if args[0].startswith('call '): |
|||
call, program = args[0].split(' ', 1) |
|||
program = call + ' ' + os.path.normpath(program) |
|||
else: |
|||
program = os.path.normpath(args[0]) |
|||
return program + ' ' + ' '.join(QuoteForRspFile(arg) for arg in args[1:]) |
|||
|
|||
|
|||
def _GenericRetrieve(root, default, path): |
|||
"""Given a list of dictionary keys |path| and a tree of dicts |root|, find |
|||
value at path, or return |default| if any of the path doesn't exist.""" |
|||
if not root: |
|||
return default |
|||
if not path: |
|||
return root |
|||
return _GenericRetrieve(root.get(path[0]), default, path[1:]) |
|||
|
|||
|
|||
def _AddPrefix(element, prefix): |
|||
"""Add |prefix| to |element| or each subelement if element is iterable.""" |
|||
if element is None: |
|||
return element |
|||
# Note, not Iterable because we don't want to handle strings like that. |
|||
if isinstance(element, list) or isinstance(element, tuple): |
|||
return [prefix + e for e in element] |
|||
else: |
|||
return prefix + element |
|||
|
|||
|
|||
def _DoRemapping(element, map): |
|||
"""If |element| then remap it through |map|. If |element| is iterable then |
|||
each item will be remapped. Any elements not found will be removed.""" |
|||
if map is not None and element is not None: |
|||
if not callable(map): |
|||
map = map.get # Assume it's a dict, otherwise a callable to do the remap. |
|||
if isinstance(element, list) or isinstance(element, tuple): |
|||
element = filter(None, [map(elem) for elem in element]) |
|||
else: |
|||
element = map(element) |
|||
return element |
|||
|
|||
|
|||
def _AppendOrReturn(append, element): |
|||
"""If |append| is None, simply return |element|. If |append| is not None, |
|||
then add |element| to it, adding each item in |element| if it's a list or |
|||
tuple.""" |
|||
if append is not None and element is not None: |
|||
if isinstance(element, list) or isinstance(element, tuple): |
|||
append.extend(element) |
|||
else: |
|||
append.append(element) |
|||
else: |
|||
return element |
|||
|
|||
|
|||
def _FindDirectXInstallation(): |
|||
"""Try to find an installation location for the DirectX SDK. Check for the |
|||
standard environment variable, and if that doesn't exist, try to find |
|||
via the registry. May return None if not found in either location.""" |
|||
dxsdk_dir = os.environ.get('DXSDK_DIR') |
|||
if not dxsdk_dir: |
|||
# Setup params to pass to and attempt to launch reg.exe. |
|||
cmd = ['reg.exe', 'query', r'HKLM\Software\Microsoft\DirectX', '/s'] |
|||
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
|||
for line in p.communicate()[0].splitlines(): |
|||
if 'InstallPath' in line: |
|||
dxsdk_dir = line.split(' ')[3] + "\\" |
|||
return dxsdk_dir |
|||
|
|||
|
|||
class MsvsSettings(object): |
|||
"""A class that understands the gyp 'msvs_...' values (especially the |
|||
msvs_settings field). They largely correpond to the VS2008 IDE DOM. This |
|||
class helps map those settings to command line options.""" |
|||
|
|||
def __init__(self, spec, generator_flags): |
|||
self.spec = spec |
|||
self.vs_version = GetVSVersion(generator_flags) |
|||
self.dxsdk_dir = _FindDirectXInstallation() |
|||
|
|||
# Try to find an installation location for the Windows DDK by checking |
|||
# the WDK_DIR environment variable, may be None. |
|||
self.wdk_dir = os.environ.get('WDK_DIR') |
|||
|
|||
supported_fields = [ |
|||
('msvs_configuration_attributes', dict), |
|||
('msvs_settings', dict), |
|||
('msvs_system_include_dirs', list), |
|||
('msvs_disabled_warnings', list), |
|||
('msvs_precompiled_header', str), |
|||
('msvs_precompiled_source', str), |
|||
('msvs_target_platform', str), |
|||
] |
|||
configs = spec['configurations'] |
|||
for field, default in supported_fields: |
|||
setattr(self, field, {}) |
|||
for configname, config in configs.iteritems(): |
|||
getattr(self, field)[configname] = config.get(field, default()) |
|||
|
|||
self.msvs_cygwin_dirs = spec.get('msvs_cygwin_dirs', ['.']) |
|||
|
|||
def GetVSMacroEnv(self, base_to_build=None, config=None): |
|||
"""Get a dict of variables mapping internal VS macro names to their gyp |
|||
equivalents.""" |
|||
target_platform = self.GetTargetPlatform(config) |
|||
target_platform = {'x86': 'Win32'}.get(target_platform, target_platform) |
|||
replacements = { |
|||
'$(VSInstallDir)': self.vs_version.Path(), |
|||
'$(VCInstallDir)': os.path.join(self.vs_version.Path(), 'VC') + '\\', |
|||
'$(OutDir)\\': base_to_build + '\\' if base_to_build else '', |
|||
'$(IntDir)': '$!INTERMEDIATE_DIR', |
|||
'$(InputPath)': '${source}', |
|||
'$(InputName)': '${root}', |
|||
'$(ProjectName)': self.spec['target_name'], |
|||
'$(PlatformName)': target_platform, |
|||
} |
|||
# Chromium uses DXSDK_DIR in include/lib paths, but it may or may not be |
|||
# set. This happens when the SDK is sync'd via src-internal, rather than |
|||
# by typical end-user installation of the SDK. If it's not set, we don't |
|||
# want to leave the unexpanded variable in the path, so simply strip it. |
|||
replacements['$(DXSDK_DIR)'] = self.dxsdk_dir if self.dxsdk_dir else '' |
|||
replacements['$(WDK_DIR)'] = self.wdk_dir if self.wdk_dir else '' |
|||
return replacements |
|||
|
|||
def ConvertVSMacros(self, s, base_to_build=None, config=None): |
|||
"""Convert from VS macro names to something equivalent.""" |
|||
env = self.GetVSMacroEnv(base_to_build, config=config) |
|||
return ExpandMacros(s, env) |
|||
|
|||
def AdjustLibraries(self, libraries): |
|||
"""Strip -l from library if it's specified with that.""" |
|||
return [lib[2:] if lib.startswith('-l') else lib for lib in libraries] |
|||
|
|||
def _GetAndMunge(self, field, path, default, prefix, append, map): |
|||
"""Retrieve a value from |field| at |path| or return |default|. If |
|||
|append| is specified, and the item is found, it will be appended to that |
|||
object instead of returned. If |map| is specified, results will be |
|||
remapped through |map| before being returned or appended.""" |
|||
result = _GenericRetrieve(field, default, path) |
|||
result = _DoRemapping(result, map) |
|||
result = _AddPrefix(result, prefix) |
|||
return _AppendOrReturn(append, result) |
|||
|
|||
class _GetWrapper(object): |
|||
def __init__(self, parent, field, base_path, append=None): |
|||
self.parent = parent |
|||
self.field = field |
|||
self.base_path = [base_path] |
|||
self.append = append |
|||
def __call__(self, name, map=None, prefix='', default=None): |
|||
return self.parent._GetAndMunge(self.field, self.base_path + [name], |
|||
default=default, prefix=prefix, append=self.append, map=map) |
|||
|
|||
def GetTargetPlatform(self, config): |
|||
target_platform = self.msvs_target_platform.get(config, '') |
|||
if not target_platform: |
|||
target_platform = 'Win32' |
|||
return {'Win32': 'x86'}.get(target_platform, target_platform) |
|||
|
|||
def _RealConfig(self, config): |
|||
target_platform = self.GetTargetPlatform(config) |
|||
if target_platform == 'x64' and not config.endswith('_x64'): |
|||
config += '_x64' |
|||
return config |
|||
|
|||
def _Setting(self, path, config, |
|||
default=None, prefix='', append=None, map=None): |
|||
"""_GetAndMunge for msvs_settings.""" |
|||
config = self._RealConfig(config) |
|||
return self._GetAndMunge( |
|||
self.msvs_settings[config], path, default, prefix, append, map) |
|||
|
|||
def _ConfigAttrib(self, path, config, |
|||
default=None, prefix='', append=None, map=None): |
|||
"""_GetAndMunge for msvs_configuration_attributes.""" |
|||
config = self._RealConfig(config) |
|||
return self._GetAndMunge( |
|||
self.msvs_configuration_attributes[config], |
|||
path, default, prefix, append, map) |
|||
|
|||
def AdjustIncludeDirs(self, include_dirs, config): |
|||
"""Updates include_dirs to expand VS specific paths, and adds the system |
|||
include dirs used for platform SDK and similar.""" |
|||
config = self._RealConfig(config) |
|||
includes = include_dirs + self.msvs_system_include_dirs[config] |
|||
includes.extend(self._Setting( |
|||
('VCCLCompilerTool', 'AdditionalIncludeDirectories'), config, default=[])) |
|||
return [self.ConvertVSMacros(p, config=config) for p in includes] |
|||
|
|||
def GetComputedDefines(self, config): |
|||
"""Returns the set of defines that are injected to the defines list based |
|||
on other VS settings.""" |
|||
config = self._RealConfig(config) |
|||
defines = [] |
|||
if self._ConfigAttrib(['CharacterSet'], config) == '1': |
|||
defines.extend(('_UNICODE', 'UNICODE')) |
|||
if self._ConfigAttrib(['CharacterSet'], config) == '2': |
|||
defines.append('_MBCS') |
|||
defines.extend(self._Setting( |
|||
('VCCLCompilerTool', 'PreprocessorDefinitions'), config, default=[])) |
|||
return defines |
|||
|
|||
def GetOutputName(self, config, expand_special): |
|||
"""Gets the explicitly overridden output name for a target or returns None |
|||
if it's not overridden.""" |
|||
config = self._RealConfig(config) |
|||
type = self.spec['type'] |
|||
root = 'VCLibrarianTool' if type == 'static_library' else 'VCLinkerTool' |
|||
# TODO(scottmg): Handle OutputDirectory without OutputFile. |
|||
output_file = self._Setting((root, 'OutputFile'), config) |
|||
if output_file: |
|||
output_file = expand_special(self.ConvertVSMacros( |
|||
output_file, config=config)) |
|||
return output_file |
|||
|
|||
def GetCflags(self, config): |
|||
"""Returns the flags that need to be added to .c and .cc compilations.""" |
|||
config = self._RealConfig(config) |
|||
cflags = [] |
|||
cflags.extend(['/wd' + w for w in self.msvs_disabled_warnings[config]]) |
|||
cl = self._GetWrapper(self, self.msvs_settings[config], |
|||
'VCCLCompilerTool', append=cflags) |
|||
cl('Optimization', |
|||
map={'0': 'd', '1': '1', '2': '2', '3': 'x'}, prefix='/O') |
|||
cl('InlineFunctionExpansion', prefix='/Ob') |
|||
cl('OmitFramePointers', map={'false': '-', 'true': ''}, prefix='/Oy') |
|||
cl('FavorSizeOrSpeed', map={'1': 't', '2': 's'}, prefix='/O') |
|||
cl('WholeProgramOptimization', map={'true': '/GL'}) |
|||
cl('WarningLevel', prefix='/W') |
|||
cl('WarnAsError', map={'true': '/WX'}) |
|||
cl('DebugInformationFormat', |
|||
map={'1': '7', '3': 'i', '4': 'I'}, prefix='/Z') |
|||
cl('RuntimeTypeInfo', map={'true': '/GR', 'false': '/GR-'}) |
|||
cl('EnableFunctionLevelLinking', map={'true': '/Gy', 'false': '/Gy-'}) |
|||
cl('MinimalRebuild', map={'true': '/Gm'}) |
|||
cl('BufferSecurityCheck', map={'true': '/GS', 'false': '/GS-'}) |
|||
cl('BasicRuntimeChecks', map={'1': 's', '2': 'u', '3': '1'}, prefix='/RTC') |
|||
cl('RuntimeLibrary', |
|||
map={'0': 'T', '1': 'Td', '2': 'D', '3': 'Dd'}, prefix='/M') |
|||
cl('ExceptionHandling', map={'1': 'sc','2': 'a'}, prefix='/EH') |
|||
cl('AdditionalOptions', prefix='') |
|||
# ninja handles parallelism by itself, don't have the compiler do it too. |
|||
cflags = filter(lambda x: not x.startswith('/MP'), cflags) |
|||
return cflags |
|||
|
|||
def GetPrecompiledHeader(self, config, gyp_to_build_path): |
|||
"""Returns an object that handles the generation of precompiled header |
|||
build steps.""" |
|||
config = self._RealConfig(config) |
|||
return _PchHelper(self, config, gyp_to_build_path) |
|||
|
|||
def _GetPchFlags(self, config, extension): |
|||
"""Get the flags to be added to the cflags for precompiled header support. |
|||
""" |
|||
config = self._RealConfig(config) |
|||
# The PCH is only built once by a particular source file. Usage of PCH must |
|||
# only be for the same language (i.e. C vs. C++), so only include the pch |
|||
# flags when the language matches. |
|||
if self.msvs_precompiled_header[config]: |
|||
source_ext = os.path.splitext(self.msvs_precompiled_source[config])[1] |
|||
if _LanguageMatchesForPch(source_ext, extension): |
|||
pch = os.path.split(self.msvs_precompiled_header[config])[1] |
|||
return ['/Yu' + pch, '/FI' + pch, '/Fp${pchprefix}.' + pch + '.pch'] |
|||
return [] |
|||
|
|||
def GetCflagsC(self, config): |
|||
"""Returns the flags that need to be added to .c compilations.""" |
|||
config = self._RealConfig(config) |
|||
return self._GetPchFlags(config, '.c') |
|||
|
|||
def GetCflagsCC(self, config): |
|||
"""Returns the flags that need to be added to .cc compilations.""" |
|||
config = self._RealConfig(config) |
|||
return ['/TP'] + self._GetPchFlags(config, '.cc') |
|||
|
|||
def _GetAdditionalLibraryDirectories(self, root, config, gyp_to_build_path): |
|||
"""Get and normalize the list of paths in AdditionalLibraryDirectories |
|||
setting.""" |
|||
config = self._RealConfig(config) |
|||
libpaths = self._Setting((root, 'AdditionalLibraryDirectories'), |
|||
config, default=[]) |
|||
libpaths = [os.path.normpath( |
|||
gyp_to_build_path(self.ConvertVSMacros(p, config=config))) |
|||
for p in libpaths] |
|||
return ['/LIBPATH:"' + p + '"' for p in libpaths] |
|||
|
|||
def GetLibFlags(self, config, gyp_to_build_path): |
|||
"""Returns the flags that need to be added to lib commands.""" |
|||
config = self._RealConfig(config) |
|||
libflags = [] |
|||
lib = self._GetWrapper(self, self.msvs_settings[config], |
|||
'VCLibrarianTool', append=libflags) |
|||
libflags.extend(self._GetAdditionalLibraryDirectories( |
|||
'VCLibrarianTool', config, gyp_to_build_path)) |
|||
lib('AdditionalOptions') |
|||
return libflags |
|||
|
|||
def _GetDefFileAsLdflags(self, spec, ldflags, gyp_to_build_path): |
|||
""".def files get implicitly converted to a ModuleDefinitionFile for the |
|||
linker in the VS generator. Emulate that behaviour here.""" |
|||
def_file = '' |
|||
if spec['type'] in ('shared_library', 'loadable_module', 'executable'): |
|||
def_files = [s for s in spec.get('sources', []) if s.endswith('.def')] |
|||
if len(def_files) == 1: |
|||
ldflags.append('/DEF:"%s"' % gyp_to_build_path(def_files[0])) |
|||
elif len(def_files) > 1: |
|||
raise Exception("Multiple .def files") |
|||
|
|||
def GetLdflags(self, config, gyp_to_build_path, expand_special): |
|||
"""Returns the flags that need to be added to link commands.""" |
|||
config = self._RealConfig(config) |
|||
ldflags = [] |
|||
ld = self._GetWrapper(self, self.msvs_settings[config], |
|||
'VCLinkerTool', append=ldflags) |
|||
self._GetDefFileAsLdflags(self.spec, ldflags, gyp_to_build_path) |
|||
ld('GenerateDebugInformation', map={'true': '/DEBUG'}) |
|||
ld('TargetMachine', map={'1': 'X86', '17': 'X64'}, prefix='/MACHINE:') |
|||
ldflags.extend(self._GetAdditionalLibraryDirectories( |
|||
'VCLinkerTool', config, gyp_to_build_path)) |
|||
ld('DelayLoadDLLs', prefix='/DELAYLOAD:') |
|||
out = self.GetOutputName(config, expand_special) |
|||
if out: |
|||
ldflags.append('/OUT:' + out) |
|||
ld('AdditionalOptions', prefix='') |
|||
ld('SubSystem', map={'1': 'CONSOLE', '2': 'WINDOWS'}, prefix='/SUBSYSTEM:') |
|||
ld('LinkIncremental', map={'1': ':NO', '2': ''}, prefix='/INCREMENTAL') |
|||
ld('FixedBaseAddress', map={'1': ':NO', '2': ''}, prefix='/FIXED') |
|||
ld('RandomizedBaseAddress', |
|||
map={'1': ':NO', '2': ''}, prefix='/DYNAMICBASE') |
|||
ld('DataExecutionPrevention', |
|||
map={'1': ':NO', '2': ''}, prefix='/NXCOMPAT') |
|||
ld('OptimizeReferences', map={'1': 'NOREF', '2': 'REF'}, prefix='/OPT:') |
|||
ld('EnableCOMDATFolding', map={'1': 'NOICF', '2': 'ICF'}, prefix='/OPT:') |
|||
ld('LinkTimeCodeGeneration', map={'1': '/LTCG'}) |
|||
ld('IgnoreDefaultLibraryNames', prefix='/NODEFAULTLIB:') |
|||
ld('ResourceOnlyDLL', map={'true': '/NOENTRY'}) |
|||
ld('EntryPointSymbol', prefix='/ENTRY:') |
|||
# TODO(scottmg): This should sort of be somewhere else (not really a flag). |
|||
ld('AdditionalDependencies', prefix='') |
|||
# TODO(scottmg): These too. |
|||
ldflags.extend(('kernel32.lib', 'user32.lib', 'gdi32.lib', 'winspool.lib', |
|||
'comdlg32.lib', 'advapi32.lib', 'shell32.lib', 'ole32.lib', |
|||
'oleaut32.lib', 'uuid.lib', 'odbc32.lib', 'DelayImp.lib')) |
|||
|
|||
# If the base address is not specifically controlled, DYNAMICBASE should |
|||
# be on by default. |
|||
base_flags = filter(lambda x: 'DYNAMICBASE' in x or x == '/FIXED', |
|||
ldflags) |
|||
if not base_flags: |
|||
ldflags.append('/DYNAMICBASE') |
|||
|
|||
# If the NXCOMPAT flag has not been specified, default to on. Despite the |
|||
# documentation that says this only defaults to on when the subsystem is |
|||
# Vista or greater (which applies to the linker), the IDE defaults it on |
|||
# unless it's explicitly off. |
|||
if not filter(lambda x: 'NXCOMPAT' in x, ldflags): |
|||
ldflags.append('/NXCOMPAT') |
|||
|
|||
return ldflags |
|||
|
|||
def IsUseLibraryDependencyInputs(self, config): |
|||
"""Returns whether the target should be linked via Use Library Dependency |
|||
Inputs (using component .objs of a given .lib).""" |
|||
config = self._RealConfig(config) |
|||
uldi = self._Setting(('VCLinkerTool', 'UseLibraryDependencyInputs'), config) |
|||
return uldi == 'true' |
|||
|
|||
def GetRcflags(self, config, gyp_to_ninja_path): |
|||
"""Returns the flags that need to be added to invocations of the resource |
|||
compiler.""" |
|||
config = self._RealConfig(config) |
|||
rcflags = [] |
|||
rc = self._GetWrapper(self, self.msvs_settings[config], |
|||
'VCResourceCompilerTool', append=rcflags) |
|||
rc('AdditionalIncludeDirectories', map=gyp_to_ninja_path, prefix='/I') |
|||
rcflags.append('/I' + gyp_to_ninja_path('.')) |
|||
rc('PreprocessorDefinitions', prefix='/d') |
|||
# /l arg must be in hex without leading '0x' |
|||
rc('Culture', prefix='/l', map=lambda x: hex(int(x))[2:]) |
|||
return rcflags |
|||
|
|||
def BuildCygwinBashCommandLine(self, args, path_to_base): |
|||
"""Build a command line that runs args via cygwin bash. We assume that all |
|||
incoming paths are in Windows normpath'd form, so they need to be |
|||
converted to posix style for the part of the command line that's passed to |
|||
bash. We also have to do some Visual Studio macro emulation here because |
|||
various rules use magic VS names for things. Also note that rules that |
|||
contain ninja variables cannot be fixed here (for example ${source}), so |
|||
the outer generator needs to make sure that the paths that are written out |
|||
are in posix style, if the command line will be used here.""" |
|||
cygwin_dir = os.path.normpath( |
|||
os.path.join(path_to_base, self.msvs_cygwin_dirs[0])) |
|||
cd = ('cd %s' % path_to_base).replace('\\', '/') |
|||
args = [a.replace('\\', '/') for a in args] |
|||
args = ["'%s'" % a.replace("'", "\\'") for a in args] |
|||
bash_cmd = ' '.join(args) |
|||
cmd = ( |
|||
'call "%s\\setup_env.bat" && set CYGWIN=nontsec && ' % cygwin_dir + |
|||
'bash -c "%s ; %s"' % (cd, bash_cmd)) |
|||
return cmd |
|||
|
|||
def IsRuleRunUnderCygwin(self, rule): |
|||
"""Determine if an action should be run under cygwin. If the variable is |
|||
unset, or set to 1 we use cygwin.""" |
|||
return int(rule.get('msvs_cygwin_shell', |
|||
self.spec.get('msvs_cygwin_shell', 1))) != 0 |
|||
|
|||
def HasExplicitIdlRules(self, spec): |
|||
"""Determine if there's an explicit rule for idl files. When there isn't we |
|||
need to generate implicit rules to build MIDL .idl files.""" |
|||
for rule in spec.get('rules', []): |
|||
if rule['extension'] == 'idl' and int(rule.get('msvs_external_rule', 0)): |
|||
return True |
|||
return False |
|||
|
|||
def GetIdlBuildData(self, source, config): |
|||
"""Determine the implicit outputs for an idl file. Returns output |
|||
directory, outputs, and variables and flags that are required.""" |
|||
config = self._RealConfig(config) |
|||
midl_get = self._GetWrapper(self, self.msvs_settings[config], 'VCMIDLTool') |
|||
def midl(name, default=None): |
|||
return self.ConvertVSMacros(midl_get(name, default=default), |
|||
config=config) |
|||
tlb = midl('TypeLibraryName', default='${root}.tlb') |
|||
header = midl('HeaderFileName', default='${root}.h') |
|||
dlldata = midl('DLLDataFileName', default='dlldata.c') |
|||
iid = midl('InterfaceIdentifierFileName', default='${root}_i.c') |
|||
proxy = midl('ProxyFileName', default='${root}_p.c') |
|||
# Note that .tlb is not included in the outputs as it is not always |
|||
# generated depending on the content of the input idl file. |
|||
outdir = midl('OutputDirectory', default='') |
|||
output = [header, dlldata, iid, proxy] |
|||
variables = [('tlb', tlb), |
|||
('h', header), |
|||
('dlldata', dlldata), |
|||
('iid', iid), |
|||
('proxy', proxy)] |
|||
# TODO(scottmg): Are there configuration settings to set these flags? |
|||
flags = ['/char', 'signed', '/env', 'win32', '/Oicf'] |
|||
return outdir, output, variables, flags |
|||
|
|||
|
|||
def _LanguageMatchesForPch(source_ext, pch_source_ext): |
|||
c_exts = ('.c',) |
|||
cc_exts = ('.cc', '.cxx', '.cpp') |
|||
return ((source_ext in c_exts and pch_source_ext in c_exts) or |
|||
(source_ext in cc_exts and pch_source_ext in cc_exts)) |
|||
|
|||
class PrecompiledHeader(object): |
|||
"""Helper to generate dependencies and build rules to handle generation of |
|||
precompiled headers. Interface matches the GCH handler in xcode_emulation.py. |
|||
""" |
|||
def __init__(self, settings, config, gyp_to_build_path): |
|||
self.settings = settings |
|||
self.config = config |
|||
self.gyp_to_build_path = gyp_to_build_path |
|||
|
|||
def _PchHeader(self): |
|||
"""Get the header that will appear in an #include line for all source |
|||
files.""" |
|||
return os.path.split(self.settings.msvs_precompiled_header[self.config])[1] |
|||
|
|||
def _PchSource(self): |
|||
"""Get the source file that is built once to compile the pch data.""" |
|||
return self.gyp_to_build_path( |
|||
self.settings.msvs_precompiled_source[self.config]) |
|||
|
|||
def _PchOutput(self): |
|||
"""Get the name of the output of the compiled pch data.""" |
|||
return '${pchprefix}.' + self._PchHeader() + '.pch' |
|||
|
|||
def GetObjDependencies(self, sources, objs): |
|||
"""Given a list of sources files and the corresponding object files, |
|||
returns a list of the pch files that should be depended upon. The |
|||
additional wrapping in the return value is for interface compatability |
|||
with make.py on Mac, and xcode_emulation.py.""" |
|||
if not self._PchHeader(): |
|||
return [] |
|||
source = self._PchSource() |
|||
assert source |
|||
pch_ext = os.path.splitext(self._PchSource())[1] |
|||
for source in sources: |
|||
if _LanguageMatchesForPch(os.path.splitext(source)[1], pch_ext): |
|||
return [(None, None, self._PchOutput())] |
|||
return [] |
|||
|
|||
def GetPchBuildCommands(self): |
|||
"""Returns [(path_to_pch, language_flag, language, header)]. |
|||
|path_to_gch| and |header| are relative to the build directory.""" |
|||
header = self._PchHeader() |
|||
source = self._PchSource() |
|||
if not source or not header: |
|||
return [] |
|||
ext = os.path.splitext(source)[1] |
|||
lang = 'c' if ext == '.c' else 'cc' |
|||
return [(self._PchOutput(), '/Yc' + header, lang, source)] |
|||
|
|||
|
|||
vs_version = None |
|||
def GetVSVersion(generator_flags): |
|||
global vs_version |
|||
if not vs_version: |
|||
vs_version = gyp.MSVSVersion.SelectVisualStudioVersion( |
|||
generator_flags.get('msvs_version', 'auto')) |
|||
return vs_version |
|||
|
|||
def _GetVsvarsSetupArgs(generator_flags, arch): |
|||
vs = GetVSVersion(generator_flags) |
|||
return vs.SetupScript() |
|||
|
|||
def ExpandMacros(string, expansions): |
|||
"""Expand $(Variable) per expansions dict. See MsvsSettings.GetVSMacroEnv |
|||
for the canonical way to retrieve a suitable dict.""" |
|||
if '$' in string: |
|||
for old, new in expansions.iteritems(): |
|||
assert '$(' not in new, new |
|||
string = string.replace(old, new) |
|||
return string |
|||
|
|||
def _ExtractImportantEnvironment(output_of_set): |
|||
"""Extracts environment variables required for the toolchain to run from |
|||
a textual dump output by the cmd.exe 'set' command.""" |
|||
envvars_to_save = ( |
|||
'goma_.*', # TODO(scottmg): This is ugly, but needed for goma. |
|||
'include', |
|||
'lib', |
|||
'libpath', |
|||
'path', |
|||
'pathext', |
|||
'systemroot', |
|||
'temp', |
|||
'tmp', |
|||
) |
|||
env = {} |
|||
for line in output_of_set.splitlines(): |
|||
for envvar in envvars_to_save: |
|||
if re.match(envvar + '=', line.lower()): |
|||
var, setting = line.split('=', 1) |
|||
if envvar == 'path': |
|||
# Our own rules (for running gyp-win-tool) and other actions in |
|||
# Chromium rely on python being in the path. Add the path to this |
|||
# python here so that if it's not in the path when ninja is run |
|||
# later, python will still be found. |
|||
setting = os.path.dirname(sys.executable) + os.pathsep + setting |
|||
env[var.upper()] = setting |
|||
break |
|||
for required in ('SYSTEMROOT', 'TEMP', 'TMP'): |
|||
if required not in env: |
|||
raise Exception('Environment variable "%s" ' |
|||
'required to be set to valid path' % required) |
|||
return env |
|||
|
|||
def _FormatAsEnvironmentBlock(envvar_dict): |
|||
"""Format as an 'environment block' directly suitable for CreateProcess. |
|||
Briefly this is a list of key=value\0, terminated by an additional \0. See |
|||
CreateProcess documentation for more details.""" |
|||
block = '' |
|||
nul = '\0' |
|||
for key, value in envvar_dict.iteritems(): |
|||
block += key + '=' + value + nul |
|||
block += nul |
|||
return block |
|||
|
|||
def GenerateEnvironmentFiles(toplevel_build_dir, generator_flags, open_out): |
|||
"""It's not sufficient to have the absolute path to the compiler, linker, |
|||
etc. on Windows, as those tools rely on .dlls being in the PATH. We also |
|||
need to support both x86 and x64 compilers within the same build (to support |
|||
msvs_target_platform hackery). Different architectures require a different |
|||
compiler binary, and different supporting environment variables (INCLUDE, |
|||
LIB, LIBPATH). So, we extract the environment here, wrap all invocations |
|||
of compiler tools (cl, link, lib, rc, midl, etc.) via win_tool.py which |
|||
sets up the environment, and then we do not prefix the compiler with |
|||
an absolute path, instead preferring something like "cl.exe" in the rule |
|||
which will then run whichever the environment setup has put in the path.""" |
|||
vs = GetVSVersion(generator_flags) |
|||
for arch in ('x86', 'x64'): |
|||
args = vs.SetupScript(arch) |
|||
args.extend(('&&', 'set')) |
|||
popen = subprocess.Popen( |
|||
args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) |
|||
variables, _ = popen.communicate() |
|||
env = _ExtractImportantEnvironment(variables) |
|||
env_block = _FormatAsEnvironmentBlock(env) |
|||
f = open_out(os.path.join(toplevel_build_dir, 'environment.' + arch), 'wb') |
|||
f.write(env_block) |
|||
f.close() |
@ -0,0 +1,161 @@ |
|||
#!/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. |
|||
|
|||
"""Utility functions for Windows builds. |
|||
|
|||
These functions are executed via gyp-win-tool when using the ninja generator. |
|||
""" |
|||
|
|||
import os |
|||
import shutil |
|||
import subprocess |
|||
import sys |
|||
|
|||
|
|||
def main(args): |
|||
executor = WinTool() |
|||
exit_code = executor.Dispatch(args) |
|||
if exit_code is not None: |
|||
sys.exit(exit_code) |
|||
|
|||
|
|||
class WinTool(object): |
|||
"""This class performs all the Windows tooling steps. The methods can either |
|||
be executed directly, or dispatched from an argument list.""" |
|||
|
|||
def Dispatch(self, args): |
|||
"""Dispatches a string command to a method.""" |
|||
if len(args) < 1: |
|||
raise Exception("Not enough arguments") |
|||
|
|||
method = "Exec%s" % self._CommandifyName(args[0]) |
|||
return getattr(self, method)(*args[1:]) |
|||
|
|||
def _CommandifyName(self, name_string): |
|||
"""Transforms a tool name like recursive-mirror to RecursiveMirror.""" |
|||
return name_string.title().replace('-', '') |
|||
|
|||
def _GetEnv(self, arch): |
|||
"""Gets the saved environment from a file for a given architecture.""" |
|||
# The environment is saved as an "environment block" (see CreateProcess |
|||
# and msvs_emulation for details). We convert to a dict here. |
|||
# Drop last 2 NULs, one for list terminator, one for trailing vs. separator. |
|||
pairs = open(arch).read()[:-2].split('\0') |
|||
kvs = [item.split('=', 1) for item in pairs] |
|||
return dict(kvs) |
|||
|
|||
def ExecStamp(self, path): |
|||
"""Simple stamp command.""" |
|||
open(path, 'w').close() |
|||
|
|||
def ExecRecursiveMirror(self, source, dest): |
|||
"""Emulation of rm -rf out && cp -af in out.""" |
|||
if os.path.exists(dest): |
|||
if os.path.isdir(dest): |
|||
shutil.rmtree(dest) |
|||
else: |
|||
os.unlink(dest) |
|||
if os.path.isdir(source): |
|||
shutil.copytree(source, dest) |
|||
else: |
|||
shutil.copy2(source, dest) |
|||
|
|||
def ExecLinkWrapper(self, arch, *args): |
|||
"""Filter diagnostic output from link that looks like: |
|||
' Creating library ui.dll.lib and object ui.dll.exp' |
|||
This happens when there are exports from the dll or exe. |
|||
""" |
|||
env = self._GetEnv(arch) |
|||
popen = subprocess.Popen(args, shell=True, env=env, |
|||
stdout=subprocess.PIPE, stderr=subprocess.STDOUT) |
|||
out, _ = popen.communicate() |
|||
for line in out.splitlines(): |
|||
if not line.startswith(' Creating library '): |
|||
print line |
|||
return popen.returncode |
|||
|
|||
def ExecMidlWrapper(self, arch, outdir, tlb, h, dlldata, iid, proxy, idl, |
|||
*flags): |
|||
"""Filter noisy filenames output from MIDL compile step that isn't |
|||
quietable via command line flags. |
|||
""" |
|||
args = ['midl', '/nologo'] + list(flags) + [ |
|||
'/out', outdir, |
|||
'/tlb', tlb, |
|||
'/h', h, |
|||
'/dlldata', dlldata, |
|||
'/iid', iid, |
|||
'/proxy', proxy, |
|||
idl] |
|||
env = self._GetEnv(arch) |
|||
popen = subprocess.Popen(args, shell=True, env=env, |
|||
stdout=subprocess.PIPE, stderr=subprocess.STDOUT) |
|||
out, _ = popen.communicate() |
|||
# Filter junk out of stdout, and write filtered versions. Output we want |
|||
# to filter is pairs of lines that look like this: |
|||
# Processing C:\Program Files (x86)\Microsoft SDKs\...\include\objidl.idl |
|||
# objidl.idl |
|||
lines = out.splitlines() |
|||
prefix = 'Processing ' |
|||
processing = set(os.path.basename(x) for x in lines if x.startswith(prefix)) |
|||
for line in lines: |
|||
if not line.startswith(prefix) and line not in processing: |
|||
print line |
|||
return popen.returncode |
|||
|
|||
def ExecAsmWrapper(self, arch, *args): |
|||
"""Filter logo banner from invocations of asm.exe.""" |
|||
env = self._GetEnv(arch) |
|||
# MSVS doesn't assemble x64 asm files. |
|||
if arch == 'environment.x64': |
|||
return 0 |
|||
popen = subprocess.Popen(args, shell=True, env=env, |
|||
stdout=subprocess.PIPE, stderr=subprocess.STDOUT) |
|||
out, _ = popen.communicate() |
|||
for line in out.splitlines(): |
|||
if (not line.startswith('Copyright (C) Microsoft Corporation') and |
|||
not line.startswith('Microsoft (R) Macro Assembler') and |
|||
not line.startswith(' Assembling: ') and |
|||
line): |
|||
print line |
|||
return popen.returncode |
|||
|
|||
def ExecRcWrapper(self, arch, *args): |
|||
"""Filter logo banner from invocations of rc.exe. Older versions of RC |
|||
don't support the /nologo flag.""" |
|||
env = self._GetEnv(arch) |
|||
popen = subprocess.Popen(args, shell=True, env=env, |
|||
stdout=subprocess.PIPE, stderr=subprocess.STDOUT) |
|||
out, _ = popen.communicate() |
|||
for line in out.splitlines(): |
|||
if (not line.startswith('Microsoft (R) Windows (R) Resource Compiler') and |
|||
not line.startswith('Copyright (C) Microsoft Corporation') and |
|||
line): |
|||
print line |
|||
return popen.returncode |
|||
|
|||
def ExecClWrapper(self, arch, depname, *args): |
|||
"""Runs cl.exe and filters output through ninja-deplist-helper to get |
|||
dependendency information which is stored in |depname|.""" |
|||
env = self._GetEnv(arch) |
|||
args = ' '.join(args) + \ |
|||
'| ninja-deplist-helper -r . -q -f cl -o ' + depname + '"' |
|||
popen = subprocess.Popen(args, shell=True, env=env) |
|||
popen.wait() |
|||
return popen.returncode |
|||
|
|||
def ExecActionWrapper(self, arch, rspfile, *dir): |
|||
"""Runs an action command line from a response file using the environment |
|||
for |arch|. If |dir| is supplied, use that as the working directory.""" |
|||
env = self._GetEnv(arch) |
|||
args = open(rspfile).read() |
|||
dir = dir[0] if dir else None |
|||
popen = subprocess.Popen(args, shell=True, env=env, cwd=dir) |
|||
popen.wait() |
|||
return popen.returncode |
|||
|
|||
if __name__ == '__main__': |
|||
sys.exit(main(sys.argv[1:])) |
@ -1,23 +0,0 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2009 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 actions which are not depended on by other targets get executed. |
|||
""" |
|||
|
|||
import TestGyp |
|||
|
|||
test = TestGyp.TestGyp() |
|||
|
|||
test.run_gyp('bare.gyp', chdir='src') |
|||
test.relocate('src', 'relocate/src') |
|||
test.build('bare.gyp', chdir='relocate/src') |
|||
|
|||
file_content = 'Hello from bare.py\n' |
|||
|
|||
test.built_file_must_match('out.txt', file_content, chdir='relocate/src') |
|||
|
|||
test.pass_test() |
@ -1,25 +0,0 @@ |
|||
# Copyright (c) 2009 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': 'bare', |
|||
'type': 'none', |
|||
'actions': [ |
|||
{ |
|||
'action_name': 'action1', |
|||
'inputs': [ |
|||
'bare.py', |
|||
], |
|||
'outputs': [ |
|||
'<(PRODUCT_DIR)/out.txt', |
|||
], |
|||
'action': ['python', 'bare.py', '<(PRODUCT_DIR)/out.txt'], |
|||
'msvs_cygwin_shell': 0, |
|||
}, |
|||
], |
|||
}, |
|||
], |
|||
} |
@ -1,11 +0,0 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2009 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. |
|||
|
|||
import sys |
|||
|
|||
f = open(sys.argv[1], 'wb') |
|||
f.write('Hello from bare.py\n') |
|||
f.close() |
@ -1,42 +0,0 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# 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. |
|||
|
|||
""" |
|||
Verifies two actions can be attached to the same input files. |
|||
""" |
|||
|
|||
import TestGyp |
|||
|
|||
test = TestGyp.TestGyp() |
|||
|
|||
test.run_gyp('actions.gyp', chdir='src') |
|||
|
|||
test.relocate('src', 'relocate/src') |
|||
|
|||
# Test that two actions can be attached to the same inputs. |
|||
test.build('actions.gyp', test.ALL, chdir='relocate/src') |
|||
test.must_contain('relocate/src/output1.txt', 'hello there') |
|||
test.must_contain('relocate/src/output2.txt', 'hello there') |
|||
test.must_contain('relocate/src/output3.txt', 'hello there') |
|||
test.must_contain('relocate/src/output4.txt', 'hello there') |
|||
|
|||
# Test that process_outputs_as_sources works in conjuction with merged |
|||
# actions. |
|||
test.run_built_executable( |
|||
'multiple_action_source_filter', |
|||
chdir='relocate/src', |
|||
stdout=( |
|||
'{\n' |
|||
'bar\n' |
|||
'car\n' |
|||
'dar\n' |
|||
'ear\n' |
|||
'}\n' |
|||
), |
|||
) |
|||
|
|||
|
|||
test.pass_test() |
@ -1,165 +0,0 @@ |
|||
# 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. |
|||
|
|||
{ |
|||
'variables': { |
|||
# Have a long string so that actions will exceed xp 512 character |
|||
# command limit on xp. |
|||
'long_string': |
|||
'abcdefghijklmnopqrstuvwxyz0123456789' |
|||
'abcdefghijklmnopqrstuvwxyz0123456789' |
|||
'abcdefghijklmnopqrstuvwxyz0123456789' |
|||
'abcdefghijklmnopqrstuvwxyz0123456789' |
|||
'abcdefghijklmnopqrstuvwxyz0123456789' |
|||
'abcdefghijklmnopqrstuvwxyz0123456789' |
|||
'abcdefghijklmnopqrstuvwxyz0123456789' |
|||
'abcdefghijklmnopqrstuvwxyz0123456789' |
|||
'abcdefghijklmnopqrstuvwxyz0123456789' |
|||
'abcdefghijklmnopqrstuvwxyz0123456789' |
|||
'abcdefghijklmnopqrstuvwxyz0123456789' |
|||
}, |
|||
'targets': [ |
|||
{ |
|||
'target_name': 'multiple_action_target', |
|||
'type': 'none', |
|||
'actions': [ |
|||
{ |
|||
'action_name': 'action1', |
|||
'inputs': [ |
|||
'copy.py', |
|||
'input.txt', |
|||
], |
|||
'outputs': [ |
|||
'output1.txt', |
|||
], |
|||
'action': [ |
|||
'python', '<@(_inputs)', '<(_outputs)', '<(long_string)', |
|||
], |
|||
# Allows the test to run without hermetic cygwin on windows. |
|||
'msvs_cygwin_shell': 0, |
|||
}, |
|||
{ |
|||
'action_name': 'action2', |
|||
'inputs': [ |
|||
'copy.py', |
|||
'input.txt', |
|||
], |
|||
'outputs': [ |
|||
'output2.txt', |
|||
], |
|||
'action': [ |
|||
'python', '<@(_inputs)', '<(_outputs)', '<(long_string)', |
|||
], |
|||
# Allows the test to run without hermetic cygwin on windows. |
|||
'msvs_cygwin_shell': 0, |
|||
}, |
|||
{ |
|||
'action_name': 'action3', |
|||
'inputs': [ |
|||
'copy.py', |
|||
'input.txt', |
|||
], |
|||
'outputs': [ |
|||
'output3.txt', |
|||
], |
|||
'action': [ |
|||
'python', '<@(_inputs)', '<(_outputs)', '<(long_string)', |
|||
], |
|||
# Allows the test to run without hermetic cygwin on windows. |
|||
'msvs_cygwin_shell': 0, |
|||
}, |
|||
{ |
|||
'action_name': 'action4', |
|||
'inputs': [ |
|||
'copy.py', |
|||
'input.txt', |
|||
], |
|||
'outputs': [ |
|||
'output4.txt', |
|||
], |
|||
'action': [ |
|||
'python', '<@(_inputs)', '<(_outputs)', '<(long_string)', |
|||
], |
|||
# Allows the test to run without hermetic cygwin on windows. |
|||
'msvs_cygwin_shell': 0, |
|||
}, |
|||
], |
|||
}, |
|||
{ |
|||
'target_name': 'multiple_action_source_filter', |
|||
'type': 'executable', |
|||
'sources': [ |
|||
'main.c', |
|||
# TODO(bradnelson): add foo.c here once this issue is fixed: |
|||
# http://code.google.com/p/gyp/issues/detail?id=175 |
|||
], |
|||
'actions': [ |
|||
{ |
|||
'action_name': 'action1', |
|||
'inputs': [ |
|||
'foo.c', |
|||
'filter.py', |
|||
], |
|||
'outputs': [ |
|||
'<(INTERMEDIATE_DIR)/output1.c', |
|||
], |
|||
'process_outputs_as_sources': 1, |
|||
'action': [ |
|||
'python', 'filter.py', 'foo', 'bar', 'foo.c', '<@(_outputs)', |
|||
], |
|||
# Allows the test to run without hermetic cygwin on windows. |
|||
'msvs_cygwin_shell': 0, |
|||
}, |
|||
{ |
|||
'action_name': 'action2', |
|||
'inputs': [ |
|||
'foo.c', |
|||
'filter.py', |
|||
], |
|||
'outputs': [ |
|||
'<(INTERMEDIATE_DIR)/output2.c', |
|||
], |
|||
'process_outputs_as_sources': 1, |
|||
'action': [ |
|||
'python', 'filter.py', 'foo', 'car', 'foo.c', '<@(_outputs)', |
|||
], |
|||
# Allows the test to run without hermetic cygwin on windows. |
|||
'msvs_cygwin_shell': 0, |
|||
}, |
|||
{ |
|||
'action_name': 'action3', |
|||
'inputs': [ |
|||
'foo.c', |
|||
'filter.py', |
|||
], |
|||
'outputs': [ |
|||
'<(INTERMEDIATE_DIR)/output3.c', |
|||
], |
|||
'process_outputs_as_sources': 1, |
|||
'action': [ |
|||
'python', 'filter.py', 'foo', 'dar', 'foo.c', '<@(_outputs)', |
|||
], |
|||
# Allows the test to run without hermetic cygwin on windows. |
|||
'msvs_cygwin_shell': 0, |
|||
}, |
|||
{ |
|||
'action_name': 'action4', |
|||
'inputs': [ |
|||
'foo.c', |
|||
'filter.py', |
|||
], |
|||
'outputs': [ |
|||
'<(INTERMEDIATE_DIR)/output4.c', |
|||
], |
|||
'process_outputs_as_sources': 1, |
|||
'action': [ |
|||
'python', 'filter.py', 'foo', 'ear', 'foo.c', '<@(_outputs)', |
|||
], |
|||
# Allows the test to run without hermetic cygwin on windows. |
|||
'msvs_cygwin_shell': 0, |
|||
}, |
|||
], |
|||
}, |
|||
], |
|||
} |
@ -1,9 +0,0 @@ |
|||
#!/usr/bin/env python |
|||
# 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. |
|||
|
|||
import shutil |
|||
import sys |
|||
|
|||
shutil.copyfile(sys.argv[1], sys.argv[2]) |
@ -1,12 +0,0 @@ |
|||
#!/usr/bin/env python |
|||
# 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. |
|||
|
|||
|
|||
import sys |
|||
|
|||
data = open(sys.argv[3], 'r').read() |
|||
fh = open(sys.argv[4], 'w') |
|||
fh.write(data.replace(sys.argv[1], sys.argv[2])) |
|||
fh.close() |
@ -1,11 +0,0 @@ |
|||
/*
|
|||
* 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. |
|||
*/ |
|||
|
|||
#include <stdio.h> |
|||
|
|||
void foo(void) { |
|||
printf("foo\n"); |
|||
} |
@ -1 +0,0 @@ |
|||
hello there |
@ -1,22 +0,0 @@ |
|||
/*
|
|||
* 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. |
|||
*/ |
|||
|
|||
#include <stdio.h> |
|||
|
|||
void bar(void); |
|||
void car(void); |
|||
void dar(void); |
|||
void ear(void); |
|||
|
|||
int main() { |
|||
printf("{\n"); |
|||
bar(); |
|||
car(); |
|||
dar(); |
|||
ear(); |
|||
printf("}\n"); |
|||
return 0; |
|||
} |
@ -1,26 +0,0 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2009 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. |
|||
|
|||
""" |
|||
Test actions that output to PRODUCT_DIR. |
|||
""" |
|||
|
|||
import TestGyp |
|||
|
|||
# TODO fix this for xcode: http://code.google.com/p/gyp/issues/detail?id=88 |
|||
test = TestGyp.TestGyp(formats=['!xcode']) |
|||
|
|||
test.run_gyp('none.gyp', chdir='src') |
|||
|
|||
test.build('none.gyp', test.ALL, chdir='src') |
|||
|
|||
file_content = 'Hello from make-file.py\n' |
|||
subdir_file_content = 'Hello from make-subdir-file.py\n' |
|||
|
|||
test.built_file_must_match('file.out', file_content, chdir='src') |
|||
test.built_file_must_match('subdir_file.out', subdir_file_content, chdir='src') |
|||
|
|||
test.pass_test() |
@ -1,11 +0,0 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2009 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. |
|||
|
|||
import sys |
|||
|
|||
contents = 'Hello from make-file.py\n' |
|||
|
|||
open(sys.argv[1], 'wb').write(contents) |
@ -1,31 +0,0 @@ |
|||
# Copyright (c) 2009 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': 'file', |
|||
'type': 'none', |
|||
'msvs_cygwin_shell': 0, |
|||
'actions': [ |
|||
{ |
|||
'action_name': 'make-file', |
|||
'inputs': [ |
|||
'make-file.py', |
|||
], |
|||
'outputs': [ |
|||
'<(PRODUCT_DIR)/file.out', |
|||
], |
|||
'action': [ |
|||
'python', '<(_inputs)', '<@(_outputs)', |
|||
], |
|||
'process_outputs_as_sources': 1, |
|||
} |
|||
], |
|||
'dependencies': [ |
|||
'subdir/subdir.gyp:subdir_file', |
|||
], |
|||
}, |
|||
], |
|||
} |
@ -1,11 +0,0 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2009 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. |
|||
|
|||
import sys |
|||
|
|||
contents = 'Hello from make-subdir-file.py\n' |
|||
|
|||
open(sys.argv[1], 'wb').write(contents) |
@ -1,28 +0,0 @@ |
|||
# Copyright (c) 2009 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': 'subdir_file', |
|||
'type': 'none', |
|||
'msvs_cygwin_shell': 0, |
|||
'actions': [ |
|||
{ |
|||
'action_name': 'make-subdir-file', |
|||
'inputs': [ |
|||
'make-subdir-file.py', |
|||
], |
|||
'outputs': [ |
|||
'<(PRODUCT_DIR)/subdir_file.out', |
|||
], |
|||
'action': [ |
|||
'python', '<(_inputs)', '<@(_outputs)', |
|||
], |
|||
'process_outputs_as_sources': 1, |
|||
} |
|||
], |
|||
}, |
|||
], |
|||
} |
@ -1,101 +0,0 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2009 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 simple actions when using an explicit build target of 'all'. |
|||
""" |
|||
|
|||
import glob |
|||
import os |
|||
import TestGyp |
|||
|
|||
test = TestGyp.TestGyp(workdir='workarea_all') |
|||
|
|||
test.run_gyp('actions.gyp', chdir='src') |
|||
|
|||
test.relocate('src', 'relocate/src') |
|||
|
|||
# Some gyp files use an action that mentions an output but never |
|||
# writes it as a means to making the action run on every build. That |
|||
# doesn't mesh well with ninja's semantics. TODO(evan): figure out |
|||
# how to work always-run actions in to ninja. |
|||
if test.format == 'ninja': |
|||
test.build('actions.gyp', test.ALL, chdir='relocate/src') |
|||
else: |
|||
# Test that an "always run" action increases a counter on multiple |
|||
# invocations, and that a dependent action updates in step. |
|||
test.build('actions.gyp', test.ALL, chdir='relocate/src') |
|||
test.must_match('relocate/src/subdir1/actions-out/action-counter.txt', '1') |
|||
test.must_match('relocate/src/subdir1/actions-out/action-counter_2.txt', '1') |
|||
test.build('actions.gyp', test.ALL, chdir='relocate/src') |
|||
test.must_match('relocate/src/subdir1/actions-out/action-counter.txt', '2') |
|||
test.must_match('relocate/src/subdir1/actions-out/action-counter_2.txt', '2') |
|||
|
|||
# The "always run" action only counts to 2, but the dependent target |
|||
# will count forever if it's allowed to run. This verifies that the |
|||
# dependent target only runs when the "always run" action generates |
|||
# new output, not just because the "always run" ran. |
|||
test.build('actions.gyp', test.ALL, chdir='relocate/src') |
|||
test.must_match('relocate/src/subdir1/actions-out/action-counter.txt', '2') |
|||
test.must_match('relocate/src/subdir1/actions-out/action-counter_2.txt', '2') |
|||
|
|||
expect = """\ |
|||
Hello from program.c |
|||
Hello from make-prog1.py |
|||
Hello from make-prog2.py |
|||
""" |
|||
|
|||
if test.format == 'xcode': |
|||
chdir = 'relocate/src/subdir1' |
|||
else: |
|||
chdir = 'relocate/src' |
|||
test.run_built_executable('program', chdir=chdir, stdout=expect) |
|||
|
|||
|
|||
test.must_match('relocate/src/subdir2/file.out', "Hello from make-file.py\n") |
|||
|
|||
|
|||
expect = "Hello from generate_main.py\n" |
|||
|
|||
if test.format == 'xcode': |
|||
chdir = 'relocate/src/subdir3' |
|||
else: |
|||
chdir = 'relocate/src' |
|||
test.run_built_executable('null_input', chdir=chdir, stdout=expect) |
|||
|
|||
|
|||
# Clean out files which may have been created if test.ALL was run. |
|||
def clean_dep_files(): |
|||
for file in (glob.glob('relocate/src/dep_*.txt') + |
|||
glob.glob('relocate/src/deps_all_done_*.txt')): |
|||
if os.path.exists(file): |
|||
os.remove(file) |
|||
|
|||
# Confirm our clean. |
|||
clean_dep_files() |
|||
test.must_not_exist('relocate/src/dep_1.txt') |
|||
test.must_not_exist('relocate/src/deps_all_done_first_123.txt') |
|||
|
|||
# Make sure all deps finish before an action is run on a 'None' target. |
|||
# If using the Make builder, add -j to make things more difficult. |
|||
arguments = [] |
|||
if test.format == 'make': |
|||
arguments = ['-j'] |
|||
test.build('actions.gyp', 'action_with_dependencies_123', chdir='relocate/src', |
|||
arguments=arguments) |
|||
test.must_exist('relocate/src/deps_all_done_first_123.txt') |
|||
|
|||
# Try again with a target that has deps in reverse. Output files from |
|||
# previous tests deleted. Confirm this execution did NOT run the ALL |
|||
# target which would mess up our dep tests. |
|||
clean_dep_files() |
|||
test.build('actions.gyp', 'action_with_dependencies_321', chdir='relocate/src', |
|||
arguments=arguments) |
|||
test.must_exist('relocate/src/deps_all_done_first_321.txt') |
|||
test.must_not_exist('relocate/src/deps_all_done_first_123.txt') |
|||
|
|||
|
|||
test.pass_test() |
@ -1,68 +0,0 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2009 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 simple actions when using the default build target. |
|||
""" |
|||
|
|||
import TestGyp |
|||
|
|||
test = TestGyp.TestGyp(workdir='workarea_default') |
|||
|
|||
test.run_gyp('actions.gyp', chdir='src') |
|||
|
|||
test.relocate('src', 'relocate/src') |
|||
|
|||
# Some gyp files use an action that mentions an output but never |
|||
# writes it as a means to making the action run on every build. That |
|||
# doesn't mesh well with ninja's semantics. TODO(evan): figure out |
|||
# how to work always-run actions in to ninja. |
|||
if test.format == 'ninja': |
|||
test.build('actions.gyp', test.ALL, chdir='relocate/src') |
|||
else: |
|||
# Test that an "always run" action increases a counter on multiple |
|||
# invocations, and that a dependent action updates in step. |
|||
test.build('actions.gyp', chdir='relocate/src') |
|||
test.must_match('relocate/src/subdir1/actions-out/action-counter.txt', '1') |
|||
test.must_match('relocate/src/subdir1/actions-out/action-counter_2.txt', '1') |
|||
test.build('actions.gyp', chdir='relocate/src') |
|||
test.must_match('relocate/src/subdir1/actions-out/action-counter.txt', '2') |
|||
test.must_match('relocate/src/subdir1/actions-out/action-counter_2.txt', '2') |
|||
|
|||
# The "always run" action only counts to 2, but the dependent target |
|||
# will count forever if it's allowed to run. This verifies that the |
|||
# dependent target only runs when the "always run" action generates |
|||
# new output, not just because the "always run" ran. |
|||
test.build('actions.gyp', test.ALL, chdir='relocate/src') |
|||
test.must_match('relocate/src/subdir1/actions-out/action-counter.txt', '2') |
|||
test.must_match('relocate/src/subdir1/actions-out/action-counter_2.txt', '2') |
|||
|
|||
expect = """\ |
|||
Hello from program.c |
|||
Hello from make-prog1.py |
|||
Hello from make-prog2.py |
|||
""" |
|||
|
|||
if test.format == 'xcode': |
|||
chdir = 'relocate/src/subdir1' |
|||
else: |
|||
chdir = 'relocate/src' |
|||
test.run_built_executable('program', chdir=chdir, stdout=expect) |
|||
|
|||
|
|||
test.must_match('relocate/src/subdir2/file.out', "Hello from make-file.py\n") |
|||
|
|||
|
|||
expect = "Hello from generate_main.py\n" |
|||
|
|||
if test.format == 'xcode': |
|||
chdir = 'relocate/src/subdir3' |
|||
else: |
|||
chdir = 'relocate/src' |
|||
test.run_built_executable('null_input', chdir=chdir, stdout=expect) |
|||
|
|||
|
|||
test.pass_test() |
@ -1,24 +0,0 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2009 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 behavior for different action configuration errors: |
|||
exit status of 1, and the expected error message must be in stderr. |
|||
""" |
|||
|
|||
import TestGyp |
|||
|
|||
test = TestGyp.TestGyp(workdir='workarea_errors') |
|||
|
|||
|
|||
test.run_gyp('action_missing_name.gyp', chdir='src', status=1, stderr=None) |
|||
expect = [ |
|||
"Anonymous action in target broken_actions2. An action must have an 'action_name' field.", |
|||
] |
|||
test.must_contain_all_lines(test.stderr(), expect) |
|||
|
|||
|
|||
test.pass_test() |
@ -1,24 +0,0 @@ |
|||
# Copyright (c) 2009 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': 'broken_actions2', |
|||
'type': 'none', |
|||
'actions': [ |
|||
{ |
|||
'inputs': [ |
|||
'no_name.input', |
|||
], |
|||
'action': [ |
|||
'python', |
|||
'-c', |
|||
'print \'missing name\'', |
|||
], |
|||
}, |
|||
], |
|||
}, |
|||
], |
|||
} |
@ -1,114 +0,0 @@ |
|||
# Copyright (c) 2009 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': 'pull_in_all_actions', |
|||
'type': 'none', |
|||
'dependencies': [ |
|||
'subdir1/executable.gyp:*', |
|||
'subdir2/none.gyp:*', |
|||
'subdir3/null_input.gyp:*', |
|||
], |
|||
}, |
|||
{ |
|||
'target_name': 'depend_on_always_run_action', |
|||
'type': 'none', |
|||
'dependencies': [ 'subdir1/executable.gyp:counter' ], |
|||
'actions': [ |
|||
{ |
|||
'action_name': 'use_always_run_output', |
|||
'inputs': [ |
|||
'subdir1/actions-out/action-counter.txt', |
|||
'subdir1/counter.py', |
|||
], |
|||
'outputs': [ |
|||
'subdir1/actions-out/action-counter_2.txt', |
|||
], |
|||
'action': [ |
|||
'python', 'subdir1/counter.py', '<(_outputs)', |
|||
], |
|||
# Allows the test to run without hermetic cygwin on windows. |
|||
'msvs_cygwin_shell': 0, |
|||
}, |
|||
], |
|||
}, |
|||
|
|||
# Three deps which don't finish immediately. |
|||
# Each one has a small delay then creates a file. |
|||
# Delays are 1.0, 1.1, and 2.0 seconds. |
|||
{ |
|||
'target_name': 'dep_1', |
|||
'type': 'none', |
|||
'actions': [{ |
|||
'inputs': [ 'actions.gyp' ], |
|||
'outputs': [ 'dep_1.txt' ], |
|||
'action_name': 'dep_1', |
|||
'action': [ 'python', '-c', |
|||
'import time; time.sleep(1); open(\'dep_1.txt\', \'w\')' ], |
|||
# Allows the test to run without hermetic cygwin on windows. |
|||
'msvs_cygwin_shell': 0, |
|||
}], |
|||
}, |
|||
{ |
|||
'target_name': 'dep_2', |
|||
'type': 'none', |
|||
'actions': [{ |
|||
'inputs': [ 'actions.gyp' ], |
|||
'outputs': [ 'dep_2.txt' ], |
|||
'action_name': 'dep_2', |
|||
'action': [ 'python', '-c', |
|||
'import time; time.sleep(1.1); open(\'dep_2.txt\', \'w\')' ], |
|||
# Allows the test to run without hermetic cygwin on windows. |
|||
'msvs_cygwin_shell': 0, |
|||
}], |
|||
}, |
|||
{ |
|||
'target_name': 'dep_3', |
|||
'type': 'none', |
|||
'actions': [{ |
|||
'inputs': [ 'actions.gyp' ], |
|||
'outputs': [ 'dep_3.txt' ], |
|||
'action_name': 'dep_3', |
|||
'action': [ 'python', '-c', |
|||
'import time; time.sleep(2.0); open(\'dep_3.txt\', \'w\')' ], |
|||
# Allows the test to run without hermetic cygwin on windows. |
|||
'msvs_cygwin_shell': 0, |
|||
}], |
|||
}, |
|||
|
|||
# An action which assumes the deps have completed. |
|||
# Does NOT list the output files of it's deps as inputs. |
|||
# On success create the file deps_all_done_first.txt. |
|||
{ |
|||
'target_name': 'action_with_dependencies_123', |
|||
'type': 'none', |
|||
'dependencies': [ 'dep_1', 'dep_2', 'dep_3' ], |
|||
'actions': [{ |
|||
'inputs': [ 'actions.gyp' ], |
|||
'outputs': [ 'deps_all_done_first_123.txt' ], |
|||
'action_name': 'action_with_dependencies_123', |
|||
'action': [ 'python', 'confirm-dep-files.py', '<(_outputs)' ], |
|||
# Allows the test to run without hermetic cygwin on windows. |
|||
'msvs_cygwin_shell': 0, |
|||
}], |
|||
}, |
|||
# Same as above but with deps in reverse. |
|||
{ |
|||
'target_name': 'action_with_dependencies_321', |
|||
'type': 'none', |
|||
'dependencies': [ 'dep_3', 'dep_2', 'dep_1' ], |
|||
'actions': [{ |
|||
'inputs': [ 'actions.gyp' ], |
|||
'outputs': [ 'deps_all_done_first_321.txt' ], |
|||
'action_name': 'action_with_dependencies_321', |
|||
'action': [ 'python', 'confirm-dep-files.py', '<(_outputs)' ], |
|||
# Allows the test to run without hermetic cygwin on windows. |
|||
'msvs_cygwin_shell': 0, |
|||
}], |
|||
}, |
|||
|
|||
], |
|||
} |
@ -1,21 +0,0 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# 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. |
|||
|
|||
"""Confirms presence of files generated by our targets we depend on. |
|||
If they exist, create a new file. |
|||
|
|||
Note target's input files are explicitly NOT defined in the gyp file |
|||
so they can't easily be passed to this script as args. |
|||
""" |
|||
|
|||
import os |
|||
import sys |
|||
|
|||
outfile = sys.argv[1] # Example value we expect: deps_all_done_first_123.txt |
|||
if (os.path.exists("dep_1.txt") and |
|||
os.path.exists("dep_2.txt") and |
|||
os.path.exists("dep_3.txt")): |
|||
open(outfile, "w") |
@ -1,46 +0,0 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2010 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. |
|||
|
|||
import sys |
|||
import time |
|||
|
|||
output = sys.argv[1] |
|||
persistoutput = "%s.persist" % sys.argv[1] |
|||
|
|||
count = 0 |
|||
try: |
|||
count = open(persistoutput, 'r').read() |
|||
except: |
|||
pass |
|||
count = int(count) + 1 |
|||
|
|||
if len(sys.argv) > 2: |
|||
max_count = int(sys.argv[2]) |
|||
if count > max_count: |
|||
count = max_count |
|||
|
|||
oldcount = 0 |
|||
try: |
|||
oldcount = open(output, 'r').read() |
|||
except: |
|||
pass |
|||
|
|||
# Save the count in a file that is undeclared, and thus hidden, to gyp. We need |
|||
# to do this because, prior to running commands, scons deletes any declared |
|||
# outputs, so we would lose our count if we just wrote to the given output file. |
|||
# (The other option is to use Precious() in the scons generator, but that seems |
|||
# too heavy-handed just to support this somewhat unrealistic test case, and |
|||
# might lead to unintended side-effects). |
|||
open(persistoutput, 'w').write('%d' % (count)) |
|||
|
|||
# Only write the given output file if the count has changed. |
|||
if int(oldcount) != count: |
|||
open(output, 'w').write('%d' % (count)) |
|||
# Sleep so the next run changes the file time sufficiently to make the build |
|||
# detect the file as changed. |
|||
time.sleep(1) |
|||
|
|||
sys.exit(0) |
@ -1,74 +0,0 @@ |
|||
# Copyright (c) 2009 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': 'program', |
|||
'type': 'executable', |
|||
'msvs_cygwin_shell': 0, |
|||
'sources': [ |
|||
'program.c', |
|||
], |
|||
'actions': [ |
|||
{ |
|||
'action_name': 'make-prog1', |
|||
'inputs': [ |
|||
'make-prog1.py', |
|||
], |
|||
'outputs': [ |
|||
'<(INTERMEDIATE_DIR)/prog1.c', |
|||
], |
|||
'action': [ |
|||
'python', '<(_inputs)', '<@(_outputs)', |
|||
], |
|||
'process_outputs_as_sources': 1, |
|||
}, |
|||
{ |
|||
'action_name': 'make-prog2', |
|||
'inputs': [ |
|||
'make-prog2.py', |
|||
], |
|||
'outputs': [ |
|||
'actions-out/prog2.c', |
|||
], |
|||
'action': [ |
|||
'python', '<(_inputs)', '<@(_outputs)', |
|||
], |
|||
'process_outputs_as_sources': 1, |
|||
# Allows the test to run without hermetic cygwin on windows. |
|||
'msvs_cygwin_shell': 0, |
|||
}, |
|||
], |
|||
}, |
|||
{ |
|||
'target_name': 'counter', |
|||
'type': 'none', |
|||
'actions': [ |
|||
{ |
|||
# This action should always run, regardless of whether or not it's |
|||
# inputs or the command-line change. We do this by creating a dummy |
|||
# first output, which is always missing, thus causing the build to |
|||
# always try to recreate it. Actual output files should be listed |
|||
# after the dummy one, and dependent targets should list the real |
|||
# output(s) in their inputs |
|||
# (see '../actions.gyp:depend_on_always_run_action'). |
|||
'action_name': 'action_counter', |
|||
'inputs': [ |
|||
'counter.py', |
|||
], |
|||
'outputs': [ |
|||
'actions-out/action-counter.txt.always', |
|||
'actions-out/action-counter.txt', |
|||
], |
|||
'action': [ |
|||
'python', '<(_inputs)', 'actions-out/action-counter.txt', '2', |
|||
], |
|||
# Allows the test to run without hermetic cygwin on windows. |
|||
'msvs_cygwin_shell': 0, |
|||
}, |
|||
], |
|||
}, |
|||
], |
|||
} |
@ -1,20 +0,0 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2009 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. |
|||
|
|||
import sys |
|||
|
|||
contents = r""" |
|||
#include <stdio.h> |
|||
|
|||
void prog1(void) |
|||
{ |
|||
printf("Hello from make-prog1.py\n"); |
|||
} |
|||
""" |
|||
|
|||
open(sys.argv[1], 'w').write(contents) |
|||
|
|||
sys.exit(0) |
@ -1,20 +0,0 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2009 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. |
|||
|
|||
import sys |
|||
|
|||
contents = r""" |
|||
#include <stdio.h> |
|||
|
|||
void prog2(void) |
|||
{ |
|||
printf("Hello from make-prog2.py\n"); |
|||
} |
|||
""" |
|||
|
|||
open(sys.argv[1], 'w').write(contents) |
|||
|
|||
sys.exit(0) |
@ -1,12 +0,0 @@ |
|||
#include <stdio.h> |
|||
|
|||
extern void prog1(void); |
|||
extern void prog2(void); |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
printf("Hello from program.c\n"); |
|||
prog1(); |
|||
prog2(); |
|||
return 0; |
|||
} |
@ -1,11 +0,0 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2009 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. |
|||
|
|||
import sys |
|||
|
|||
contents = "Hello from make-file.py\n" |
|||
|
|||
open(sys.argv[1], 'wb').write(contents) |
@ -1,33 +0,0 @@ |
|||
# Copyright (c) 2009 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': 'file', |
|||
'type': 'none', |
|||
'msvs_cygwin_shell': 0, |
|||
'actions': [ |
|||
{ |
|||
'action_name': 'make-file', |
|||
'inputs': [ |
|||
'make-file.py', |
|||
], |
|||
'outputs': [ |
|||
'file.out', |
|||
# TODO: enhance testing infrastructure to test this |
|||
# without having to hard-code the intermediate dir paths. |
|||
#'<(INTERMEDIATE_DIR)/file.out', |
|||
], |
|||
'action': [ |
|||
'python', '<(_inputs)', '<@(_outputs)', |
|||
], |
|||
'process_outputs_as_sources': 1, |
|||
# Allows the test to run without hermetic cygwin on windows. |
|||
'msvs_cygwin_shell': 0, |
|||
} |
|||
], |
|||
}, |
|||
], |
|||
} |
@ -1,21 +0,0 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2009 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. |
|||
|
|||
import sys |
|||
|
|||
contents = """ |
|||
#include <stdio.h> |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
printf("Hello from generate_main.py\\n"); |
|||
return 0; |
|||
} |
|||
""" |
|||
|
|||
open(sys.argv[1], 'w').write(contents) |
|||
|
|||
sys.exit(0) |
@ -1,29 +0,0 @@ |
|||
# Copyright (c) 2009 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': 'null_input', |
|||
'type': 'executable', |
|||
'msvs_cygwin_shell': 0, |
|||
'actions': [ |
|||
{ |
|||
'action_name': 'generate_main', |
|||
'process_outputs_as_sources': 1, |
|||
'inputs': [], |
|||
'outputs': [ |
|||
'<(INTERMEDIATE_DIR)/main.c', |
|||
], |
|||
'action': [ |
|||
# TODO: we can't just use <(_outputs) here?! |
|||
'python', 'generate_main.py', '<(INTERMEDIATE_DIR)/main.c', |
|||
], |
|||
# Allows the test to run without hermetic cygwin on windows. |
|||
'msvs_cygwin_shell': 0, |
|||
}, |
|||
], |
|||
}, |
|||
], |
|||
} |
@ -1,55 +0,0 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2009 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 simple actions when using an explicit build target of 'all'. |
|||
""" |
|||
|
|||
import TestGyp |
|||
|
|||
test = TestGyp.TestGyp() |
|||
|
|||
test.run_gyp('all.gyp', chdir='src') |
|||
test.relocate('src', 'relocate/src') |
|||
|
|||
# Build all. |
|||
test.build('all.gyp', chdir='relocate/src') |
|||
|
|||
if test.format=='xcode': |
|||
chdir = 'relocate/src/dir1' |
|||
else: |
|||
chdir = 'relocate/src' |
|||
|
|||
# Output is as expected. |
|||
file_content = 'Hello from emit.py\n' |
|||
test.built_file_must_match('out2.txt', file_content, chdir=chdir) |
|||
|
|||
test.built_file_must_not_exist('out.txt', chdir='relocate/src') |
|||
test.built_file_must_not_exist('foolib1', |
|||
type=test.SHARED_LIB, |
|||
chdir=chdir) |
|||
|
|||
# TODO(mmoss) Make consistent with scons, with 'dir1' before 'out/Default'? |
|||
if test.format in ('make', 'ninja'): |
|||
chdir='relocate/src' |
|||
else: |
|||
chdir='relocate/src/dir1' |
|||
|
|||
# Build the action explicitly. |
|||
test.build('actions.gyp', 'action1_target', chdir=chdir) |
|||
|
|||
# Check that things got run. |
|||
file_content = 'Hello from emit.py\n' |
|||
test.built_file_must_exist('out.txt', chdir=chdir) |
|||
|
|||
# Build the shared library explicitly. |
|||
test.build('actions.gyp', 'foolib1', chdir=chdir) |
|||
|
|||
test.built_file_must_exist('foolib1', |
|||
type=test.SHARED_LIB, |
|||
chdir=chdir) |
|||
|
|||
test.pass_test() |
@ -1,13 +0,0 @@ |
|||
# Copyright (c) 2009 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': 'all_targets', |
|||
'type': 'none', |
|||
'dependencies': ['dir1/actions.gyp:*'], |
|||
}, |
|||
], |
|||
} |
@ -1,56 +0,0 @@ |
|||
# Copyright (c) 2009 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': 'action1_target', |
|||
'type': 'none', |
|||
'suppress_wildcard': 1, |
|||
'actions': [ |
|||
{ |
|||
'action_name': 'action1', |
|||
'inputs': [ |
|||
'emit.py', |
|||
], |
|||
'outputs': [ |
|||
'<(PRODUCT_DIR)/out.txt', |
|||
], |
|||
'action': ['python', 'emit.py', '<(PRODUCT_DIR)/out.txt'], |
|||
'msvs_cygwin_shell': 0, |
|||
}, |
|||
], |
|||
}, |
|||
{ |
|||
'target_name': 'action2_target', |
|||
'type': 'none', |
|||
'actions': [ |
|||
{ |
|||
'action_name': 'action2', |
|||
'inputs': [ |
|||
'emit.py', |
|||
], |
|||
'outputs': [ |
|||
'<(PRODUCT_DIR)/out2.txt', |
|||
], |
|||
'action': ['python', 'emit.py', '<(PRODUCT_DIR)/out2.txt'], |
|||
'msvs_cygwin_shell': 0, |
|||
}, |
|||
], |
|||
}, |
|||
{ |
|||
'target_name': 'foolib1', |
|||
'type': 'shared_library', |
|||
'suppress_wildcard': 1, |
|||
'sources': ['lib1.c'], |
|||
}, |
|||
], |
|||
'conditions': [ |
|||
['OS=="linux"', { |
|||
'target_defaults': { |
|||
'cflags': ['-fPIC'], |
|||
}, |
|||
}], |
|||
], |
|||
} |
@ -1,11 +0,0 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2009 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. |
|||
|
|||
import sys |
|||
|
|||
f = open(sys.argv[1], 'wb') |
|||
f.write('Hello from emit.py\n') |
|||
f.close() |
@ -1,6 +0,0 @@ |
|||
#ifdef _WIN32 |
|||
__declspec(dllexport) |
|||
#endif |
|||
int func1(void) { |
|||
return 42; |
|||
} |
@ -1,31 +0,0 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2009 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 .hpp files are ignored when included in the source list on all |
|||
platforms. |
|||
""" |
|||
|
|||
import sys |
|||
import TestGyp |
|||
|
|||
# TODO(bradnelson): get this working for windows. |
|||
test = TestGyp.TestGyp(formats=['make', 'ninja', 'scons', 'xcode']) |
|||
|
|||
test.run_gyp('assembly.gyp', chdir='src') |
|||
|
|||
test.relocate('src', 'relocate/src') |
|||
|
|||
test.build('assembly.gyp', test.ALL, chdir='relocate/src') |
|||
|
|||
expect = """\ |
|||
Hello from program.c |
|||
Got 42. |
|||
""" |
|||
test.run_built_executable('program', chdir='relocate/src', stdout=expect) |
|||
|
|||
|
|||
test.pass_test() |
@ -1,4 +0,0 @@ |
|||
@echo off |
|||
:: Mock windows assembler. |
|||
cl /c %1 /Fo"%2" |
|||
|
@ -1,59 +0,0 @@ |
|||
# Copyright (c) 2009 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': { |
|||
'conditions': [ |
|||
['OS=="win"', { |
|||
'defines': ['PLATFORM_WIN'], |
|||
}], |
|||
['OS=="mac"', { |
|||
'defines': ['PLATFORM_MAC'], |
|||
}], |
|||
['OS=="linux"', { |
|||
'defines': ['PLATFORM_LINUX'], |
|||
}], |
|||
], |
|||
}, |
|||
'targets': [ |
|||
{ |
|||
'target_name': 'program', |
|||
'type': 'executable', |
|||
'dependencies': ['lib1'], |
|||
'sources': [ |
|||
'program.c', |
|||
], |
|||
}, |
|||
{ |
|||
'target_name': 'lib1', |
|||
'type': 'static_library', |
|||
'sources': [ |
|||
'lib1.S', |
|||
], |
|||
}, |
|||
], |
|||
'conditions': [ |
|||
['OS=="win"', { |
|||
'target_defaults': { |
|||
'rules': [ |
|||
{ |
|||
'rule_name': 'assembler', |
|||
'msvs_cygwin_shell': 0, |
|||
'extension': 'S', |
|||
'inputs': [ |
|||
'as.bat', |
|||
], |
|||
'outputs': [ |
|||
'<(INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).obj', |
|||
], |
|||
'action': |
|||
['as.bat', 'lib1.c', '<(_outputs)'], |
|||
'message': 'Building assembly file <(RULE_INPUT_PATH)', |
|||
'process_outputs_as_sources': 1, |
|||
}, |
|||
], |
|||
}, |
|||
},], |
|||
], |
|||
} |
@ -1,10 +0,0 @@ |
|||
#if PLATFORM_WINDOWS || PLATFORM_MAC |
|||
# define IDENTIFIER(n) _##n |
|||
#else /* Linux */ |
|||
# define IDENTIFIER(n) n |
|||
#endif |
|||
|
|||
.globl IDENTIFIER(lib1_function) |
|||
IDENTIFIER(lib1_function): |
|||
movl $42, %eax |
|||
ret |
@ -1,3 +0,0 @@ |
|||
int lib1_function(void) { |
|||
return 42; |
|||
} |
@ -1,12 +0,0 @@ |
|||
#include <stdio.h> |
|||
|
|||
extern int lib1_function(void); |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
fprintf(stdout, "Hello from program.c\n"); |
|||
fflush(stdout); |
|||
fprintf(stdout, "Got %d.\n", lib1_function()); |
|||
fflush(stdout); |
|||
return 0; |
|||
} |
@ -1,77 +0,0 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2009 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. |
|||
|
|||
""" |
|||
Verify the settings that cause a set of programs to be created in |
|||
a specific build directory, and that no intermediate built files |
|||
get created outside of that build directory hierarchy even when |
|||
referred to with deeply-nested ../../.. paths. |
|||
""" |
|||
|
|||
import TestGyp |
|||
|
|||
# TODO(mmoss): Make only supports (theoretically) a single, global build |
|||
# directory (through GYP_GENERATOR_FLAGS 'output_dir'), rather than |
|||
# gyp-file-specific settings (e.g. the stuff in builddir.gypi) that the other |
|||
# generators support, so this doesn't work yet for make. |
|||
# TODO(mmoss) Make also has the issue that the top-level Makefile is written to |
|||
# the "--depth" location, which is one level above 'src', but then this test |
|||
# moves 'src' somewhere else, leaving the Makefile behind, so make can't find |
|||
# its sources. I'm not sure if make is wrong for writing outside the current |
|||
# directory, or if the test is wrong for assuming everything generated is under |
|||
# the current directory. |
|||
test = TestGyp.TestGyp(formats=['!make', '!ninja']) |
|||
|
|||
test.run_gyp('prog1.gyp', '--depth=..', chdir='src') |
|||
|
|||
test.relocate('src', 'relocate/src') |
|||
|
|||
test.subdir('relocate/builddir') |
|||
|
|||
# Make sure that all the built ../../etc. files only get put under builddir, |
|||
# by making all of relocate read-only and then making only builddir writable. |
|||
test.writable('relocate', False) |
|||
test.writable('relocate/builddir', True) |
|||
|
|||
# Suppress the test infrastructure's setting SYMROOT on the command line. |
|||
test.build('prog1.gyp', test.ALL, SYMROOT=None, chdir='relocate/src') |
|||
|
|||
expect1 = """\ |
|||
Hello from prog1.c |
|||
Hello from func1.c |
|||
""" |
|||
|
|||
expect2 = """\ |
|||
Hello from subdir2/prog2.c |
|||
Hello from func2.c |
|||
""" |
|||
|
|||
expect3 = """\ |
|||
Hello from subdir2/subdir3/prog3.c |
|||
Hello from func3.c |
|||
""" |
|||
|
|||
expect4 = """\ |
|||
Hello from subdir2/subdir3/subdir4/prog4.c |
|||
Hello from func4.c |
|||
""" |
|||
|
|||
expect5 = """\ |
|||
Hello from subdir2/subdir3/subdir4/subdir5/prog5.c |
|||
Hello from func5.c |
|||
""" |
|||
|
|||
def run_builddir(prog, expect): |
|||
dir = 'relocate/builddir/Default/' |
|||
test.run(program=test.workpath(dir + prog), stdout=expect) |
|||
|
|||
run_builddir('prog1', expect1) |
|||
run_builddir('prog2', expect2) |
|||
run_builddir('prog3', expect3) |
|||
run_builddir('prog4', expect4) |
|||
run_builddir('prog5', expect5) |
|||
|
|||
test.pass_test() |
@ -1,77 +0,0 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2009 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. |
|||
|
|||
""" |
|||
Verify the settings that cause a set of programs to be created in |
|||
a specific build directory, and that no intermediate built files |
|||
get created outside of that build directory hierarchy even when |
|||
referred to with deeply-nested ../../.. paths. |
|||
""" |
|||
|
|||
import TestGyp |
|||
|
|||
# TODO(mmoss): Make only supports (theoretically) a single, global build |
|||
# directory (through GYP_GENERATOR_FLAGS 'output_dir'), rather than |
|||
# gyp-file-specific settings (e.g. the stuff in builddir.gypi) that the other |
|||
# generators support, so this doesn't work yet for make. |
|||
# TODO(mmoss) Make also has the issue that the top-level Makefile is written to |
|||
# the "--depth" location, which is one level above 'src', but then this test |
|||
# moves 'src' somewhere else, leaving the Makefile behind, so make can't find |
|||
# its sources. I'm not sure if make is wrong for writing outside the current |
|||
# directory, or if the test is wrong for assuming everything generated is under |
|||
# the current directory. |
|||
test = TestGyp.TestGyp(formats=['!make', '!ninja']) |
|||
|
|||
test.run_gyp('prog1.gyp', '--depth=..', chdir='src') |
|||
|
|||
test.relocate('src', 'relocate/src') |
|||
|
|||
test.subdir('relocate/builddir') |
|||
|
|||
# Make sure that all the built ../../etc. files only get put under builddir, |
|||
# by making all of relocate read-only and then making only builddir writable. |
|||
test.writable('relocate', False) |
|||
test.writable('relocate/builddir', True) |
|||
|
|||
# Suppress the test infrastructure's setting SYMROOT on the command line. |
|||
test.build('prog1.gyp', SYMROOT=None, chdir='relocate/src') |
|||
|
|||
expect1 = """\ |
|||
Hello from prog1.c |
|||
Hello from func1.c |
|||
""" |
|||
|
|||
expect2 = """\ |
|||
Hello from subdir2/prog2.c |
|||
Hello from func2.c |
|||
""" |
|||
|
|||
expect3 = """\ |
|||
Hello from subdir2/subdir3/prog3.c |
|||
Hello from func3.c |
|||
""" |
|||
|
|||
expect4 = """\ |
|||
Hello from subdir2/subdir3/subdir4/prog4.c |
|||
Hello from func4.c |
|||
""" |
|||
|
|||
expect5 = """\ |
|||
Hello from subdir2/subdir3/subdir4/subdir5/prog5.c |
|||
Hello from func5.c |
|||
""" |
|||
|
|||
def run_builddir(prog, expect): |
|||
dir = 'relocate/builddir/Default/' |
|||
test.run(program=test.workpath(dir + prog), stdout=expect) |
|||
|
|||
run_builddir('prog1', expect1) |
|||
run_builddir('prog2', expect2) |
|||
run_builddir('prog3', expect3) |
|||
run_builddir('prog4', expect4) |
|||
run_builddir('prog5', expect5) |
|||
|
|||
test.pass_test() |
@ -1,21 +0,0 @@ |
|||
# Copyright (c) 2009 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': { |
|||
'Default': { |
|||
'msvs_configuration_attributes': { |
|||
'OutputDirectory': '<(DEPTH)\\builddir\Default', |
|||
}, |
|||
}, |
|||
}, |
|||
}, |
|||
'scons_settings': { |
|||
'sconsbuild_dir': '<(DEPTH)/builddir', |
|||
}, |
|||
'xcode_settings': { |
|||
'SYMROOT': '<(DEPTH)/builddir', |
|||
}, |
|||
} |
@ -1,6 +0,0 @@ |
|||
#include <stdio.h> |
|||
|
|||
void func1(void) |
|||
{ |
|||
printf("Hello from func1.c\n"); |
|||
} |
@ -1,6 +0,0 @@ |
|||
#include <stdio.h> |
|||
|
|||
void func2(void) |
|||
{ |
|||
printf("Hello from func2.c\n"); |
|||
} |
@ -1,6 +0,0 @@ |
|||
#include <stdio.h> |
|||
|
|||
void func3(void) |
|||
{ |
|||
printf("Hello from func3.c\n"); |
|||
} |
@ -1,6 +0,0 @@ |
|||
#include <stdio.h> |
|||
|
|||
void func4(void) |
|||
{ |
|||
printf("Hello from func4.c\n"); |
|||
} |
@ -1,6 +0,0 @@ |
|||
#include <stdio.h> |
|||
|
|||
void func5(void) |
|||
{ |
|||
printf("Hello from func5.c\n"); |
|||
} |
@ -1,10 +0,0 @@ |
|||
#include <stdio.h> |
|||
|
|||
extern void func1(void); |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
printf("Hello from prog1.c\n"); |
|||
func1(); |
|||
return 0; |
|||
} |
@ -1,30 +0,0 @@ |
|||
# Copyright (c) 2009 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. |
|||
|
|||
{ |
|||
'includes': [ |
|||
'builddir.gypi', |
|||
], |
|||
'targets': [ |
|||
{ |
|||
'target_name': 'pull_in_all', |
|||
'type': 'none', |
|||
'dependencies': [ |
|||
'prog1', |
|||
'subdir2/prog2.gyp:prog2', |
|||
'subdir2/subdir3/prog3.gyp:prog3', |
|||
'subdir2/subdir3/subdir4/prog4.gyp:prog4', |
|||
'subdir2/subdir3/subdir4/subdir5/prog5.gyp:prog5', |
|||
], |
|||
}, |
|||
{ |
|||
'target_name': 'prog1', |
|||
'type': 'executable', |
|||
'sources': [ |
|||
'prog1.c', |
|||
'func1.c', |
|||
], |
|||
}, |
|||
], |
|||
} |
@ -1,10 +0,0 @@ |
|||
#include <stdio.h> |
|||
|
|||
extern void func2(void); |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
printf("Hello from subdir2/prog2.c\n"); |
|||
func2(); |
|||
return 0; |
|||
} |
@ -1,19 +0,0 @@ |
|||
# Copyright (c) 2009 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. |
|||
|
|||
{ |
|||
'includes': [ |
|||
'../builddir.gypi', |
|||
], |
|||
'targets': [ |
|||
{ |
|||
'target_name': 'prog2', |
|||
'type': 'executable', |
|||
'sources': [ |
|||
'prog2.c', |
|||
'../func2.c', |
|||
], |
|||
}, |
|||
], |
|||
} |
@ -1,10 +0,0 @@ |
|||
#include <stdio.h> |
|||
|
|||
extern void func3(void); |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
printf("Hello from subdir2/subdir3/prog3.c\n"); |
|||
func3(); |
|||
return 0; |
|||
} |
@ -1,19 +0,0 @@ |
|||
# Copyright (c) 2009 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. |
|||
|
|||
{ |
|||
'includes': [ |
|||
'../../builddir.gypi', |
|||
], |
|||
'targets': [ |
|||
{ |
|||
'target_name': 'prog3', |
|||
'type': 'executable', |
|||
'sources': [ |
|||
'prog3.c', |
|||
'../../func3.c', |
|||
], |
|||
}, |
|||
], |
|||
} |
@ -1,10 +0,0 @@ |
|||
#include <stdio.h> |
|||
|
|||
extern void func4(void); |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
printf("Hello from subdir2/subdir3/subdir4/prog4.c\n"); |
|||
func4(); |
|||
return 0; |
|||
} |
@ -1,19 +0,0 @@ |
|||
# Copyright (c) 2009 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. |
|||
|
|||
{ |
|||
'includes': [ |
|||
'../../../builddir.gypi', |
|||
], |
|||
'targets': [ |
|||
{ |
|||
'target_name': 'prog4', |
|||
'type': 'executable', |
|||
'sources': [ |
|||
'prog4.c', |
|||
'../../../func4.c', |
|||
], |
|||
}, |
|||
], |
|||
} |
@ -1,10 +0,0 @@ |
|||
#include <stdio.h> |
|||
|
|||
extern void func5(void); |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
printf("Hello from subdir2/subdir3/subdir4/subdir5/prog5.c\n"); |
|||
func5(); |
|||
return 0; |
|||
} |
@ -1,19 +0,0 @@ |
|||
# Copyright (c) 2009 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. |
|||
|
|||
{ |
|||
'includes': [ |
|||
'../../../../builddir.gypi', |
|||
], |
|||
'targets': [ |
|||
{ |
|||
'target_name': 'prog5', |
|||
'type': 'executable', |
|||
'sources': [ |
|||
'prog5.c', |
|||
'../../../../func5.c', |
|||
], |
|||
}, |
|||
], |
|||
} |
@ -1,15 +0,0 @@ |
|||
/* Copyright (c) 2010 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> |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
#ifdef __OPTIMIZE__ |
|||
printf("Using an optimization flag\n"); |
|||
#else |
|||
printf("Using no optimization flag\n"); |
|||
#endif |
|||
return 0; |
|||
} |
@ -1,16 +0,0 @@ |
|||
# Copyright (c) 2010 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': 'cflags', |
|||
'type': 'executable', |
|||
'opt': '-Os', |
|||
'sources': [ |
|||
'cflags.c', |
|||
], |
|||
}, |
|||
], |
|||
} |
@ -1,65 +0,0 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2010 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 build of an executable with C++ define specified by a gyp define, and |
|||
the use of the environment during regeneration when the gyp file changes. |
|||
""" |
|||
|
|||
import os |
|||
import TestGyp |
|||
|
|||
env_stack = [] |
|||
|
|||
|
|||
def PushEnv(): |
|||
env_copy = os.environ.copy() |
|||
env_stack.append(env_copy) |
|||
|
|||
def PopEnv(): |
|||
os.eniron=env_stack.pop() |
|||
|
|||
# Regenerating build files when a gyp file changes is currently only supported |
|||
# by the make generator. |
|||
test = TestGyp.TestGyp(formats=['make']) |
|||
|
|||
try: |
|||
PushEnv() |
|||
os.environ['CFLAGS'] = '-O0' |
|||
test.run_gyp('cflags.gyp') |
|||
finally: |
|||
# We clear the environ after calling gyp. When the auto-regeneration happens, |
|||
# the same define should be reused anyway. Reset to empty string first in |
|||
# case the platform doesn't support unsetenv. |
|||
PopEnv() |
|||
|
|||
test.build('cflags.gyp') |
|||
|
|||
expect = """\ |
|||
Using no optimization flag |
|||
""" |
|||
test.run_built_executable('cflags', stdout=expect) |
|||
|
|||
test.sleep() |
|||
|
|||
try: |
|||
PushEnv() |
|||
os.environ['CFLAGS'] = '-O2' |
|||
test.run_gyp('cflags.gyp') |
|||
finally: |
|||
# We clear the environ after calling gyp. When the auto-regeneration happens, |
|||
# the same define should be reused anyway. Reset to empty string first in |
|||
# case the platform doesn't support unsetenv. |
|||
PopEnv() |
|||
|
|||
test.build('cflags.gyp') |
|||
|
|||
expect = """\ |
|||
Using an optimization flag |
|||
""" |
|||
test.run_built_executable('cflags', stdout=expect) |
|||
|
|||
test.pass_test() |
@ -1,29 +0,0 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2009 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 .hpp files are ignored when included in the source list on all |
|||
platforms. |
|||
""" |
|||
|
|||
import TestGyp |
|||
|
|||
test = TestGyp.TestGyp() |
|||
|
|||
test.run_gyp('headers.gyp', chdir='src') |
|||
|
|||
test.relocate('src', 'relocate/src') |
|||
|
|||
test.build('headers.gyp', test.ALL, chdir='relocate/src') |
|||
|
|||
expect = """\ |
|||
Hello from program.c |
|||
Hello from lib1.c |
|||
""" |
|||
test.run_built_executable('program', chdir='relocate/src', stdout=expect) |
|||
|
|||
|
|||
test.pass_test() |
@ -1,26 +0,0 @@ |
|||
# Copyright (c) 2009 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': 'program', |
|||
'type': 'executable', |
|||
'dependencies': [ |
|||
'lib1' |
|||
], |
|||
'sources': [ |
|||
'program.cpp', |
|||
], |
|||
}, |
|||
{ |
|||
'target_name': 'lib1', |
|||
'type': 'static_library', |
|||
'sources': [ |
|||
'lib1.hpp', |
|||
'lib1.cpp', |
|||
], |
|||
}, |
|||
], |
|||
} |
@ -1,7 +0,0 @@ |
|||
#include <stdio.h> |
|||
#include "lib1.hpp" |
|||
|
|||
void lib1_function(void) { |
|||
fprintf(stdout, "Hello from lib1.c\n"); |
|||
fflush(stdout); |
|||
} |
@ -1,6 +0,0 @@ |
|||
#ifndef _lib1_hpp |
|||
#define _lib1_hpp |
|||
|
|||
extern void lib1_function(void); |
|||
|
|||
#endif |
@ -1,9 +0,0 @@ |
|||
#include <stdio.h> |
|||
#include "lib1.hpp" |
|||
|
|||
int main(int argc, char *argv[]) { |
|||
fprintf(stdout, "Hello from program.c\n"); |
|||
fflush(stdout); |
|||
lib1_function(); |
|||
return 0; |
|||
} |
@ -1,15 +0,0 @@ |
|||
#include <stdio.h> |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
#ifdef FOO |
|||
printf("Foo configuration\n"); |
|||
#endif |
|||
#ifdef DEBUG |
|||
printf("Debug configuration\n"); |
|||
#endif |
|||
#ifdef RELEASE |
|||
printf("Release configuration\n"); |
|||
#endif |
|||
return 0; |
|||
} |
@ -1,32 +0,0 @@ |
|||
# Copyright (c) 2009 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': 'configurations', |
|||
'type': 'executable', |
|||
'sources': [ |
|||
'configurations.c', |
|||
], |
|||
'configurations': { |
|||
'Debug': { |
|||
'defines': [ |
|||
'DEBUG', |
|||
], |
|||
}, |
|||
'Release': { |
|||
'defines': [ |
|||
'RELEASE', |
|||
], |
|||
}, |
|||
'Foo': { |
|||
'defines': [ |
|||
'FOO', |
|||
], |
|||
}, |
|||
} |
|||
}, |
|||
], |
|||
} |
@ -1,29 +0,0 @@ |
|||
#!/usr/bin/env python |
|||
|
|||
# Copyright (c) 2009 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 build of an executable in three different configurations. |
|||
""" |
|||
|
|||
import TestGyp |
|||
|
|||
test = TestGyp.TestGyp() |
|||
|
|||
test.run_gyp('configurations.gyp') |
|||
|
|||
test.set_configuration('Release') |
|||
test.build('configurations.gyp') |
|||
test.run_built_executable('configurations', stdout="Release configuration\n") |
|||
|
|||
test.set_configuration('Debug') |
|||
test.build('configurations.gyp') |
|||
test.run_built_executable('configurations', stdout="Debug configuration\n") |
|||
|
|||
test.set_configuration('Foo') |
|||
test.build('configurations.gyp') |
|||
test.run_built_executable('configurations', stdout="Foo configuration\n") |
|||
|
|||
test.pass_test() |
@ -1,21 +0,0 @@ |
|||
#include <stdio.h> |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
#ifdef BASE |
|||
printf("Base configuration\n"); |
|||
#endif |
|||
#ifdef COMMON |
|||
printf("Common configuration\n"); |
|||
#endif |
|||
#ifdef COMMON2 |
|||
printf("Common2 configuration\n"); |
|||
#endif |
|||
#ifdef DEBUG |
|||
printf("Debug configuration\n"); |
|||
#endif |
|||
#ifdef RELEASE |
|||
printf("Release configuration\n"); |
|||
#endif |
|||
return 0; |
|||
} |
@ -1,40 +0,0 @@ |
|||
# Copyright (c) 2009 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': { |
|||
'Base': { |
|||
'abstract': 1, |
|||
'defines': ['BASE'], |
|||
}, |
|||
'Common': { |
|||
'abstract': 1, |
|||
'inherit_from': ['Base'], |
|||
'defines': ['COMMON'], |
|||
}, |
|||
'Common2': { |
|||
'abstract': 1, |
|||
'defines': ['COMMON2'], |
|||
}, |
|||
'Debug': { |
|||
'inherit_from': ['Common', 'Common2'], |
|||
'defines': ['DEBUG'], |
|||
}, |
|||
'Release': { |
|||
'inherit_from': ['Common', 'Common2'], |
|||
'defines': ['RELEASE'], |
|||
}, |
|||
}, |
|||
}, |
|||
'targets': [ |
|||
{ |
|||
'target_name': 'configurations', |
|||
'type': 'executable', |
|||
'sources': [ |
|||
'configurations.c', |
|||
], |
|||
}, |
|||
], |
|||
} |
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue