Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Starting with additional includes, defines, and some basic cflags and…

… ldflags.

Review URL: https://chromiumcodereview.appspot.com/9443044

git-svn-id: http://gyp.googlecode.com/svn/trunk@1243 78cadc50-ecff-11dd-a971-7dbc132099af
  • Loading branch information...
commit e9f84600b50e10b673135656e5f7351066fca90f 1 parent e3a8d23
scottmg@chromium.org authored
View
4 DEPS
@@ -4,6 +4,7 @@
vars = {
"chrome_trunk": "http://src.chromium.org/svn/trunk",
+ "googlecode_url": "http://%s.googlecode.com/svn",
}
deps = {
@@ -18,5 +19,8 @@ deps_os = {
"third_party/python_26":
Var("chrome_trunk") + "/tools/third_party/python_26@89111",
+
+ "src/third_party/pefile":
+ (Var("googlecode_url") % "pefile") + "/trunk@63",
},
}
View
66 pylib/gyp/generator/ninja.py
@@ -6,6 +6,7 @@
import gyp
import gyp.common
import gyp.msvs_emulation
+import gyp.MSVSVersion
import gyp.system_test
import gyp.xcode_emulation
import os.path
@@ -213,11 +214,6 @@ def ExpandSpecial(self, path, product_dir=None):
# so insert product_dir in front if it is provided.
path = path.replace(INTERMEDIATE_DIR,
os.path.join(product_dir or '', int_dir))
-
- if self.flavor == 'win':
- # Don't use os.path.normpath here. Callers pass in './foo' and expect
- # the result to be runnable, but normpath removes the prefix.
- return path.replace('/', '\\')
return path
def ExpandRuleVariables(self, path, root, dirname, source, ext, name):
@@ -237,7 +233,10 @@ def GypPathToNinja(self, path, env=None):
if env:
path = gyp.xcode_emulation.ExpandEnvVars(path, env)
if path.startswith('$!'):
- return self.ExpandSpecial(path)
+ expanded = self.ExpandSpecial(path)
+ if self.flavor == 'win':
+ expanded = os.path.normpath(expanded)
+ return expanded
assert '$' not in path, path
return os.path.normpath(os.path.join(self.build_to_base, path))
@@ -303,10 +302,11 @@ def WriteSpec(self, spec, config_name):
self.target = Target(spec['type'])
self.is_mac_bundle = gyp.xcode_emulation.IsMacBundle(self.flavor, spec)
+ self.xcode_settings = self.msvs_settings = None
if self.flavor == 'mac':
self.xcode_settings = gyp.xcode_emulation.XcodeSettings(spec)
- else:
- self.xcode_settings = None
+ if self.flavor == 'win':
+ self.msvs_settings = gyp.msvs_emulation.MsvsSettings(spec)
# Compute predepends for all rules.
# actions_depends is the dependencies this target depends on before running
@@ -583,6 +583,8 @@ def WriteSources(self, config_name, config, sources, predepends,
self.ninja.variable('cxx', '$cxx_target')
self.ninja.variable('ld', '$ld_target')
+ extra_defines = []
+ extra_includes = []
if self.flavor == 'mac':
cflags = self.xcode_settings.GetCflags(config_name)
cflags_c = self.xcode_settings.GetCflagsC(config_name)
@@ -591,17 +593,25 @@ def WriteSources(self, config_name, config, sources, predepends,
self.xcode_settings.GetCflagsObjC(config_name)
cflags_objcc = ['$cflags_cc'] + \
self.xcode_settings.GetCflagsObjCC(config_name)
+ elif self.flavor == 'win':
+ cflags = self.msvs_settings.GetCflags(config_name)
+ cflags_c = self.msvs_settings.GetCflagsC(config_name)
+ cflags_cc = self.msvs_settings.GetCflagsCC(config_name)
+ extra_defines = self.msvs_settings.GetComputedDefines(config_name)
+ extra_includes = self.msvs_settings.GetSystemIncludes(config_name)
else:
cflags = config.get('cflags', [])
cflags_c = config.get('cflags_c', [])
cflags_cc = config.get('cflags_cc', [])
+ defines = config.get('defines', []) + extra_defines
self.WriteVariableList('defines',
[QuoteShellArgument(ninja_syntax.escape('-D' + d), self.flavor)
- for d in config.get('defines', [])])
+ for d in defines])
+ include_dirs = config.get('include_dirs', []) + extra_includes
self.WriteVariableList('includes',
- ['-I' + self.GypPathToNinja(i)
- for i in config.get('include_dirs', [])])
+ [QuoteShellArgument('-I' + self.GypPathToNinja(i), self.flavor)
+ for i in include_dirs])
pch_commands = precompiled_header.GetGchBuildCommands()
if self.flavor == 'mac':
@@ -711,6 +721,10 @@ def WriteLink(self, spec, config_name, config, link_deps):
ldflags = self.xcode_settings.GetLdflags(config_name,
self.ExpandSpecial(generator_default_variables['PRODUCT_DIR']),
self.GypPathToNinja)
+ elif self.flavor == 'win':
+ ldflags = self.msvs_settings.GetLdflags(config_name,
+ self.ExpandSpecial(generator_default_variables['PRODUCT_DIR']),
+ self.GypPathToNinja)
else:
ldflags = config.get('ldflags', [])
self.WriteVariableList('ldflags',
@@ -1011,6 +1025,24 @@ def CalculateVariables(default_variables, params):
default_variables['STATIC_LIB_SUFFIX'] = '.lib'
default_variables['SHARED_LIB_PREFIX'] = ''
default_variables['SHARED_LIB_SUFFIX'] = '.dll'
+ generator_flags = params.get('generator_flags', {})
+ msvs_version = gyp.MSVSVersion.SelectVisualStudioVersion(
+ generator_flags.get('msvs_version', 'auto'))
+ # Stash msvs_version for later (so we don't have to probe the system twice).
+ params['msvs_version'] = msvs_version
+
+ # Set a variable so conditions can be based on msvs_version.
+ default_variables['MSVS_VERSION'] = msvs_version.ShortName()
+
+ # To determine processor word size on Windows, in addition to checking
+ # PROCESSOR_ARCHITECTURE (which reflects the word size of the current
+ # process), it is also necessary to check PROCESSOR_ARCHITEW6432 (which
+ # contains the actual word size of the system when running thru WOW64).
+ if ('64' in os.environ.get('PROCESSOR_ARCHITECTURE', '') or
+ '64' in os.environ.get('PROCESSOR_ARCHITEW6432', '')):
+ default_variables['MSVS_OS_BITS'] = 64
+ else:
+ default_variables['MSVS_OS_BITS'] = 32
else:
operating_system = flavor
if flavor == 'android':
@@ -1106,7 +1138,7 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params,
command=('cmd /c $cc /nologo /showIncludes '
'$defines $includes $cflags $cflags_c '
'$cflags_pch_c /c $in /Fo$out '
- '| ninja-deplist-helper -f cl -o $out.dl'),
+ '| ninja-deplist-helper -q -f cl -o $out.dl'),
deplist='$out.dl')
master_ninja.rule(
'cxx',
@@ -1114,7 +1146,7 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params,
command=('cmd /c $cxx /nologo /showIncludes '
'$defines $includes $cflags $cflags_cc '
'$cflags_pch_cc /c $in /Fo$out '
- '| ninja-deplist-helper -f cl -o $out.dl'),
+ '| ninja-deplist-helper -q -f cl -o $out.dl'),
deplist='$out.dl')
if flavor != 'mac' and flavor != 'win':
@@ -1145,15 +1177,17 @@ def GenerateOutputForConfig(target_list, target_dicts, data, params,
master_ninja.rule(
'solink',
description='LINK(DLL) $dll',
- command=('$ld /nologo /IMPLIB:$implib /DLL $ldflags /OUT:$dll $in $libs'))
+ command=('$ld /nologo /IMPLIB:$implib /DLL $ldflags /OUT:$dll '
+ '/PDB:$dll.pdb $in $libs'))
master_ninja.rule(
'solink_module',
description='LINK(DLL) $dll',
- command=('$ld /nologo /IMPLIB:$implib /DLL $ldflags /OUT:$dll $in $libs'))
+ command=('$ld /nologo /IMPLIB:$implib /DLL $ldflags /OUT:$dll '
+ '/PDB:$dll.pdb $in $libs'))
master_ninja.rule(
'link',
description='LINK $out',
- command=('$ld /nologo $ldflags /OUT:$out $in $libs'))
+ command=('$ld /nologo $ldflags /OUT:$out /PDB:$out.pdb $in $libs'))
else:
master_ninja.rule(
'objc',
View
195 pylib/gyp/msvs_emulation.py
@@ -8,6 +8,7 @@
"""
import re
+import sys
windows_quoter_regex = re.compile(r'(\\*)"')
@@ -41,6 +42,200 @@ def QuoteCmdExeArgument(arg):
# applies and whitespace isn't a word break.
return '"' + tmp + '"'
+
def EncodeCmdExeList(args):
"""Process a list of arguments using QuoteCmdExeArgument."""
return ' '.join(QuoteCmdExeArgument(arg) for arg in args)
+
+
+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 isinstance(element, list) or isinstance(element, tuple):
+ element = filter(None, [map.get(elem) for elem in element])
+ else:
+ element = map.get(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
+
+
+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):
+ self.spec = spec
+ self.configname = None
+
+ supported_fields = [
+ 'msvs_configuration_attributes',
+ 'msvs_settings',
+ 'msvs_system_include_dirs',
+ 'msvs_disabled_warnings',
+ ]
+ configs = spec['configurations']
+ for field in supported_fields:
+ setattr(self, field, {})
+ for configname, config in configs.iteritems():
+ getattr(self, field)[configname] = config.get(field, {})
+
+ def _ConvertVSMacros(self, s):
+ """Convert from VS macro names to something equivalent."""
+ if '$' in s:
+ replacements = {
+ # TODO(scottmg): obviously
+ '$(VSInstallDir)':
+ r'C:\Program Files (x86)\Microsoft Visual Studio 9.0\\',
+ }
+ for old, new in replacements.iteritems():
+ s = s.replace(old, new)
+ return s
+
+ 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=''):
+ return self.parent._GetAndMunge(self.field, self.base_path + [name],
+ default=None, prefix=prefix, append=self.append, map=map)
+
+ def Setting(self, path, default=None, prefix='', append=None, map=None):
+ """_GetAndMunge for msvs_settings."""
+ return self._GetAndMunge(
+ self.msvs_settings[self.configname], path, default, prefix, append, map)
+
+ def ConfigAttrib(self, path, default=None, prefix='', append=None, map=None):
+ """_GetAndMunge for msvs_configuration_attributes."""
+ return self._GetAndMunge(
+ self.msvs_configuration_attributes[self.configname],
+ path, default, prefix, append, map)
+
+ def GetSystemIncludes(self, config):
+ """Returns the extra set of include paths that are used for the Windows
+ SDK and similar."""
+ return [self._ConvertVSMacros(p)
+ for p in self.msvs_system_include_dirs[config]]
+
+ def GetComputedDefines(self, config):
+ """Returns the set of defines that are injected to the defines list based
+ on other VS settings."""
+ self.configname = config
+ defines = []
+ if self.ConfigAttrib(['CharacterSet']) == '1':
+ defines.extend(('_UNICODE', 'UNICODE'))
+ if self.ConfigAttrib(['CharacterSet']) == '2':
+ defines.append('_MBCS')
+ defines.extend(self.Setting(('VCCLCompilerTool', 'PreprocessorDefinitions'),
+ default=[]))
+ self.configname = None
+ return defines
+
+ def GetCflags(self, config):
+ """Returns the flags that need to be added to .c and .cc compilations."""
+ 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', '2': 's'}, prefix='/O')
+ cl('InlineFunctionExpansion', prefix='/Ob')
+ cl('OmitFramePointers', map={'false': '-', 'true': ''}, prefix='/Oy')
+ cl('FavorSizeOrSpeed', map={'1': 's', '2': 't'}, 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='')
+ return cflags
+
+ def GetCflagsC(self, config):
+ """Returns the flags that need to be added to .c compilations."""
+ return []
+
+ def GetCflagsCC(self, config):
+ """Returns the flags that need to be added to .cc compilations."""
+ return ['/TP']
+
+ def GetLdflags(self, config, product_dir, gyp_to_build_path):
+ """Returns the flags that need to be added to link and lib commands."""
+ ldflags = []
+ ld = self._GetWrapper(self, self.msvs_settings[config],
+ 'VCLinkerTool', append=ldflags)
+ ld('GenerateDebugInformation', map={'true': '/DEBUG'})
+ ld('TargetMachine', map={'1': 'X86', '17': 'X64'}, prefix='/MACHINE:')
+ ld('AdditionalLibraryDirectories', prefix='/LIBPATH:')
+ ld('DelayLoadDLLs', prefix='/DELAYLOAD:')
+ 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'})
+ # 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', 'odbccp32.lib',
+ 'DelayImp.lib'))
+ return ldflags
View
11 test/win/compiler-flags/character-set-mbcs.cc
@@ -0,0 +1,11 @@
+// Copyright (c) 2012 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef _MBCS
+#error
+#endif
+
+int main() {
+ return 0;
+}
View
15 test/win/compiler-flags/character-set-unicode.cc
@@ -0,0 +1,15 @@
+// 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.
+
+#ifndef _UNICODE
+#error
+#endif
+
+#ifndef UNICODE
+#error
+#endif
+
+int main() {
+ return 0;
+}
View
41 test/win/compiler-flags/character-set.gyp
@@ -0,0 +1,41 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test_cs_notset',
+ 'product_name': 'test_cs_notset',
+ 'type': 'executable',
+ 'msvs_configuration_attributes': {
+ 'CharacterSet': '0'
+ },
+ 'sources': [
+ 'hello.cc'
+ ]
+ },
+ {
+ 'target_name': 'test_cs_unicode',
+ 'product_name': 'test_cs_unicode',
+ 'type': 'executable',
+ 'msvs_configuration_attributes': {
+ 'CharacterSet': '1'
+ },
+ 'sources': [
+ 'character-set-unicode.cc'
+ ]
+ },
+ {
+ 'target_name': 'test_cs_mbcs',
+ 'product_name': 'test_cs_mbcs',
+ 'type': 'executable',
+ 'msvs_configuration_attributes': {
+ 'CharacterSet': '2'
+ },
+ 'sources': [
+ 'character-set-mbcs.cc'
+ ]
+ },
+ ]
+}
View
7 test/win/compiler-flags/hello.cc
@@ -0,0 +1,7 @@
+// Copyright (c) 2012 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+int main() {
+ return 0;
+}
View
23 test/win/gyptest-cl_character_set.py
@@ -0,0 +1,23 @@
+#!/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.
+
+"""
+Make sure character set setting is extracted properly.
+"""
+
+import TestGyp
+
+import subprocess
+import sys
+
+if sys.platform == 'win32':
+ test = TestGyp.TestGyp(formats=['ninja', 'msvs'])
+
+ CHDIR = 'compiler-flags'
+ test.run_gyp('character-set.gyp', chdir=CHDIR)
+ test.build('character-set.gyp', test.ALL, chdir=CHDIR)
+
+ test.pass_test()
Please sign in to comment.
Something went wrong with that request. Please try again.