summaryrefslogtreecommitdiffstats
path: root/site_scons
diff options
context:
space:
mode:
authorbradnelson@chromium.org <bradnelson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-12-04 19:35:47 +0000
committerbradnelson@chromium.org <bradnelson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-12-04 19:35:47 +0000
commit5a17959168f700202c3ee498e88cca7bcfa43a97 (patch)
treef0c8d497ded5551516310cebec76c3395880c19c /site_scons
parentaedd85af7d7d0c90ed343ece4c66660db00841ec (diff)
downloadchromium_src-5a17959168f700202c3ee498e88cca7bcfa43a97.zip
chromium_src-5a17959168f700202c3ee498e88cca7bcfa43a97.tar.gz
chromium_src-5a17959168f700202c3ee498e88cca7bcfa43a97.tar.bz2
Pulling in hammer changes.
Review URL: http://codereview.chromium.org/13134 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@6370 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'site_scons')
-rw-r--r--site_scons/site_tools/code_coverage.py123
-rw-r--r--site_scons/site_tools/component_bits.py4
-rw-r--r--site_scons/site_tools/component_setup.py46
-rwxr-xr-xsite_scons/site_tools/component_targets.py9
-rwxr-xr-xsite_scons/site_tools/component_targets_msvs.py2
-rw-r--r--site_scons/site_tools/concat_source.py17
-rw-r--r--site_scons/site_tools/defer.py71
-rw-r--r--site_scons/site_tools/replace_strings.py5
-rw-r--r--site_scons/site_tools/replicate.py6
-rw-r--r--site_scons/site_tools/target_platform_linux.py9
-rw-r--r--site_scons/site_tools/target_platform_mac.py9
-rw-r--r--site_scons/site_tools/target_platform_windows.py114
-rw-r--r--site_scons/site_tools/windows_hard_link.py2
13 files changed, 350 insertions, 67 deletions
diff --git a/site_scons/site_tools/code_coverage.py b/site_scons/site_tools/code_coverage.py
new file mode 100644
index 0000000..6155cdf
--- /dev/null
+++ b/site_scons/site_tools/code_coverage.py
@@ -0,0 +1,123 @@
+#!/usr/bin/python2.4
+# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""SCons tool for generating code coverage.
+
+This module enhances a debug environment to add code coverage.
+It is used as follows:
+ coverage_env = dbg_env.Clone(tools = ['code_coverage'])
+"""
+
+
+def AddCoverageSetup(env):
+ """Add coverage related build steps and dependency links.
+
+ Args:
+ env: a leaf environment ready to have coverage steps added.
+ """
+ # Add a step to start coverage (for instance windows needs this).
+ # This step should get run before and tests are run.
+ if env.get('COVERAGE_START_CMD', None):
+ start = env.Command('$COVERAGE_START_FILE', [], '$COVERAGE_START_CMD')
+ env.AlwaysBuild(start)
+ else:
+ start = []
+
+ # Add a step to end coverage (used on basically all platforms).
+ # This step should get after all the tests have run.
+ if env.get('COVERAGE_STOP_CMD', None):
+ stop = env.Command('$COVERAGE_OUTPUT_FILE', [], '$COVERAGE_STOP_CMD')
+ env.AlwaysBuild(stop)
+ else:
+ stop = []
+
+ # start must happen before tests run, stop must happen after.
+ for group in env.SubstList2('$COVERAGE_TARGETS'):
+ group_alias = env.Alias(group)
+ # Force each alias to happen after start but before stop.
+ env.Requires(group_alias, start)
+ env.Requires(stop, group_alias)
+ # Force each source of the aliases to happen after start but before stop.
+ # This is needed to work around non-standard aliases in some projects.
+ for test in group_alias:
+ for s in test.sources:
+ env.Requires(s, start)
+ env.Requires(stop, s)
+
+ # Add an alias for coverage.
+ env.Alias('coverage', [start, stop])
+
+
+def generate(env):
+ # NOTE: SCons requires the use of this name, which fails gpylint.
+ """SCons entry point for this tool."""
+
+ env['COVERAGE_ENABLED'] = True
+
+ env.SetDefault(
+ # Setup up coverage related tool paths.
+ # These can be overridden elsewhere, if needed, to relocate the tools.
+ COVERAGE_MCOV='mcov',
+ COVERAGE_GENHTML='genhtml',
+ COVERAGE_ANALYZER='coverage_analyzer.exe',
+ COVERAGE_VSPERFCMD='VSPerfCmd.exe',
+ COVERAGE_VSINSTR='vsinstr.exe',
+
+ # Setup coverage related locations.
+ COVERAGE_DIR='$TARGET_ROOT/coverage',
+ COVERAGE_HTML_DIR='$COVERAGE_DIR/html',
+ COVERAGE_START_FILE='$COVERAGE_DIR/start.junk',
+ COVERAGE_OUTPUT_FILE='$COVERAGE_DIR/coverage.lcov',
+
+ # The list of aliases containing test execution targets.
+ COVERAGE_TARGETS=['run_all_tests'],
+ )
+
+ # Add in coverage flags. These come from target_platform_xxx.
+ env.Append(
+ CCFLAGS='$COVERAGE_CCFLAGS',
+ LIBS='$COVERAGE_LIBS',
+ LINKFLAGS='$COVERAGE_LINKFLAGS',
+ )
+
+ # Add on LINKCOM steps.
+ # TODO(bradnelson): Ideally this would just get appended, but that seems to
+ # cause it to blow up in the gather_inputs builder with a complaint about
+ # "Can't creation Action from None". Once that builder is gone, then this
+ # can change to be more general.
+ if env.get('COVERAGE_LINKCOM_EXTRAS'):
+ env['LINKCOM'] = env.Action([env['LINKCOM'],
+ env['COVERAGE_LINKCOM_EXTRAS']])
+
+ # Add any extra paths.
+ env.AppendENVPath('PATH', env.SubstList2('$COVERAGE_EXTRA_PATHS'))
+
+ # Add coverage start/stop and processing in deferred steps.
+ env.Defer(AddCoverageSetup)
diff --git a/site_scons/site_tools/component_bits.py b/site_scons/site_tools/component_bits.py
index 5c89a96..53e6d88 100644
--- a/site_scons/site_tools/component_bits.py
+++ b/site_scons/site_tools/component_bits.py
@@ -191,11 +191,11 @@ def SetBits(env, *args):
def ClearBits(env, *args):
- """Sets the bits in the environment.
+ """Clears the bits in the environment.
Args:
env: Environment to check.
- args: List of bit names to set.
+ args: List of bit names to clear (remove).
"""
_CheckDeclared(args)
env['_BITS'] = env['_BITS'].difference(args)
diff --git a/site_scons/site_tools/component_setup.py b/site_scons/site_tools/component_setup.py
index a9ec5c0..7155655 100644
--- a/site_scons/site_tools/component_setup.py
+++ b/site_scons/site_tools/component_setup.py
@@ -70,9 +70,11 @@ def PreEvaluateVariables(env):
Args:
env: Environment for the current build mode.
"""
- # Convert directory variables to strings
+ # Convert directory variables to strings. Must use .abspath not str(), since
+ # otherwise $OBJ_ROOT is converted to a relative path, which evaluates
+ # improperly in SConscripts not in $MAIN_DIR.
for var in env.SubstList2('$PRE_EVALUATE_DIRS'):
- env[var] = str(env.Dir('$' + var))
+ env[var] = env.Dir('$' + var).abspath
#------------------------------------------------------------------------------
@@ -195,6 +197,46 @@ def generate(env):
# default to do so after including the component_setup tool.
env.Default('$DESTINATION_ROOT')
+ # Use brief command line strings if necessary
+ SCons.Script.Help("""\
+ --verbose Print verbose output while building, including
+ the full command lines for all commands.
+ --brief Print brief output while building (the default).
+ This and --verbose are opposites. Use --silent
+ to turn off all output.
+""")
+ SCons.Script.AddOption(
+ '--brief',
+ dest='brief_comstr',
+ default=True,
+ action='store_true',
+ help='brief command line output')
+ SCons.Script.AddOption(
+ '--verbose',
+ dest='brief_comstr',
+ default=True,
+ action='store_false',
+ help='verbose command line output')
+ if env.GetOption('brief_comstr'):
+ env.SetDefault(
+ ARCOMSTR='________Creating library $TARGET',
+ ASCOMSTR='________Assembling $TARGET',
+ CCCOMSTR='________Compiling $TARGET',
+ CONCAT_SOURCE_COMSTR='________ConcatSource $TARGET',
+ CXXCOMSTR='________Compiling $TARGET',
+ LDMODULECOMSTR='________Building loadable module $TARGET',
+ LINKCOMSTR='________Linking $TARGET',
+ MANIFEST_COMSTR='________Updating manifest for $TARGET',
+ MIDLCOMSTR='________Compiling IDL $TARGET',
+ PCHCOMSTR='________Precompiling $TARGET',
+ RANLIBCOMSTR='________Indexing $TARGET',
+ RCCOMSTR='________Compiling resource $TARGET',
+ SHCCCOMSTR='________Compiling $TARGET',
+ SHCXXCOMSTR='________Compiling $TARGET',
+ SHLINKCOMSTR='________Linking $TARGET',
+ SHMANIFEST_COMSTR='________Updating manifest for $TARGET',
+ )
+
# Add other default tools from our toolkit
# TODO(rspangler): Currently this needs to be before SOURCE_ROOT in case a
# tool needs to redefine it. Need a better way to handle order-dependency
diff --git a/site_scons/site_tools/component_targets.py b/site_scons/site_tools/component_targets.py
index 493e0e2..53a0b26 100755
--- a/site_scons/site_tools/component_targets.py
+++ b/site_scons/site_tools/component_targets.py
@@ -113,7 +113,8 @@ def AddTargetGroup(name, description):
Args:
name: Name of target group. This should be the name of an alias which
points to other aliases for the specific targets.
- description: Description of the target group.
+ description: Description of the target group. Should read properly when
+ appended to 'The following ' - for example, 'programs can be built'.
"""
# Warn if the target group already exists with a different description
@@ -147,6 +148,8 @@ def GetTargetModes():
This dict is not fully populated until after BuildEnvironments() has been
called.
"""
+ # TODO(rspangler): Better to rename this to # GetTargetBuildEnvironments()?
+ # That's a more description name.
return __target_modes
@@ -197,7 +200,9 @@ def SetTargetProperty(self, target_name, all_modes=False, **kwargs):
def AddTargetHelp():
- """Adds help for the targets, groups, and modes."""
+ """Adds SCons help for the targets, groups, and modes.
+
+ This is called automatically by BuildEnvironments()."""
help_text = ''
for group in GetTargetGroups().values():
diff --git a/site_scons/site_tools/component_targets_msvs.py b/site_scons/site_tools/component_targets_msvs.py
index b50f1a5..6afc7fe 100755
--- a/site_scons/site_tools/component_targets_msvs.py
+++ b/site_scons/site_tools/component_targets_msvs.py
@@ -821,7 +821,7 @@ def ComponentVSSolution(self, solution_name, target_names, projects=None,
Args:
self: Environment context.
- solution_name: Name of the target.
+ solution_name: Name of the solution.
target_names: Names of targets or target groups to include in the solution.
This will automatically build projects for them.
projects: List of aditional projects not generated by this solution to
diff --git a/site_scons/site_tools/concat_source.py b/site_scons/site_tools/concat_source.py
index 0598f97..8d0fd89 100644
--- a/site_scons/site_tools/concat_source.py
+++ b/site_scons/site_tools/concat_source.py
@@ -110,17 +110,20 @@ def generate(env):
"""SCons entry point for this tool."""
# Add the builder
- action = SCons.Script.Action(ConcatSourceBuilder,
+ action = SCons.Script.Action(ConcatSourceBuilder, '$CONCAT_SOURCE_COMSTR',
varlist = ['CONCAT_SOURCE_SUFFIXES'])
builder = SCons.Script.Builder(action = action, suffix = '$CXXFILESUFFIX')
env.Append(BUILDERS={'ConcatSourceBuilder': builder})
- # Suffixes of sources we can concatenate. Files not in this list will be
- # passed through untouched. (Note that on Mac, Objective C/C++ files
- # cannot be concatenated with regular C/C++ files.)
- # TODO(rspangler): Probably shouldn't mix C, C++ either...
- env['CONCAT_SOURCE_SUFFIXES'] = ['.c', '.C', '.cxx', '.cpp', '.c++', '.cc',
- '.h', '.H', '.hxx', '.hpp', '.hh']
+ env.SetDefault(
+ CONCAT_SOURCE_COMSTR = 'Creating ConcatSource $TARGET from $SOURCES',
+ # Suffixes of sources we can concatenate. Files not in this list will be
+ # passed through untouched. (Note that on Mac, Objective C/C++ files
+ # cannot be concatenated with regular C/C++ files.)
+ # TODO(rspangler): Probably shouldn't mix C, C++ either...
+ CONCAT_SOURCE_SUFFIXES = ['.c', '.C', '.cxx', '.cpp', '.c++', '.cc',
+ '.h', '.H', '.hxx', '.hpp', '.hh'],
+ )
# Add a psuedo-builder method which can look at the environment to determine
# whether to call the ConcatSource builder or not
diff --git a/site_scons/site_tools/defer.py b/site_scons/site_tools/defer.py
index 8b6de89..3da09ea 100644
--- a/site_scons/site_tools/defer.py
+++ b/site_scons/site_tools/defer.py
@@ -37,6 +37,11 @@ import types
import SCons.Errors
+# Current group name being executed by ExecuteDefer(). Set to None outside
+# of ExecuteDefer().
+_execute_defer_context = None
+
+
class DeferGroup:
"""Named list of functions to be deferred."""
# If we derive DeferGroup from object, instances of it return type
@@ -127,6 +132,11 @@ def ExecuteDefer(self):
Args:
self: Current environment context.
"""
+ # Check for re-entrancy
+ global _execute_defer_context
+ if _execute_defer_context:
+ raise SCons.Errors.UserError('Re-entrant call to ExecuteDefer().')
+
# Save directory, so SConscript functions can occur in the right subdirs
oldcwd = os.getcwd()
@@ -141,24 +151,39 @@ def ExecuteDefer(self):
defer_groups = GetDeferGroups(self)
# Loop through deferred functions
- while defer_groups:
- did_work = False
- for name, group in defer_groups.items():
- if group.after.intersection(defer_groups.keys()):
- continue # Still have dependencies
- if group.func_env_cwd:
- # Run all the functions in our named group
- for func, env, cwd in group.func_env_cwd:
- os.chdir(cwd)
- func(env)
- did_work = True
- del defer_groups[name]
- break
- if not did_work:
- errmsg = 'Error in ExecuteDefer: dependency cycle detected.\n'
+ try:
+ while defer_groups:
+ did_work = False
for name, group in defer_groups.items():
- errmsg += ' %s after: %s\n' % (name, group.after)
- raise SCons.Errors.UserError(errmsg)
+ if group.after.intersection(defer_groups.keys()):
+ continue # Still have dependencies
+
+ # Set defer context
+ _execute_defer_context = name
+
+ # Remove this group from the list of defer groups now, in case one of
+ # the functions it calls adds back a function into that defer group.
+ del defer_groups[name]
+
+ if group.func_env_cwd:
+ # Run all the functions in our named group
+ for func, env, cwd in group.func_env_cwd:
+ os.chdir(cwd)
+ func(env)
+
+ # The defer groups have been altered, so restart the search for
+ # functions that can be executed.
+ did_work = True
+ break
+
+ if not did_work:
+ errmsg = 'Error in ExecuteDefer: dependency cycle detected.\n'
+ for name, group in defer_groups.items():
+ errmsg += ' %s after: %s\n' % (name, group.after)
+ raise SCons.Errors.UserError(errmsg)
+ finally:
+ # No longer in a defer context
+ _execute_defer_context = None
# Restore directory
os.chdir(oldcwd)
@@ -272,6 +297,18 @@ def Defer(self, *args, **kwargs):
# Add dependencies for the function
group.after.update(after)
+ # If we are already inside a call to ExecuteDefer(), any functions which are
+ # deferring until after the current function must also be deferred until
+ # after this new function. In short, this means that if b() defers until
+ # after a() and a() calls Defer() to defer c(), then b() must also defer
+ # until after c().
+ if _execute_defer_context and name != _execute_defer_context:
+ for other_name, other_group in GetDeferGroups(self).items():
+ if other_name == name:
+ continue # Don't defer after ourselves
+ if _execute_defer_context in other_group.after:
+ other_group.after.add(name)
+
def generate(env):
# NOTE: SCons requires the use of this name, which fails gpylint.
diff --git a/site_scons/site_tools/replace_strings.py b/site_scons/site_tools/replace_strings.py
index c31f685..1c92772 100644
--- a/site_scons/site_tools/replace_strings.py
+++ b/site_scons/site_tools/replace_strings.py
@@ -46,7 +46,8 @@ def ReplaceStrings(target, source, env):
From env:
REPLACE_STRINGS: A list of pairs of regex search and replacement strings.
The body of the source file has substitution performed on each
- pair (search_regex, replacement) in order.
+ pair (search_regex, replacement) in order. SCons variables in the
+ replacement strings will be evaluated.
Returns:
The target node, a file with contents from source, with the substitutions
@@ -64,7 +65,7 @@ def ReplaceStrings(target, source, env):
fh.close()
# Do replacements.
for r in env['REPLACE_STRINGS']:
- text = re.sub(r[0], r[1], text)
+ text = re.sub(r[0], env.subst(r[1]), text)
# Write it out.
fh = open(target[0].abspath, 'wb')
fh.write(text)
diff --git a/site_scons/site_tools/replicate.py b/site_scons/site_tools/replicate.py
index b11ce14..e64ec36 100644
--- a/site_scons/site_tools/replicate.py
+++ b/site_scons/site_tools/replicate.py
@@ -50,15 +50,15 @@ def Replicate(env, target, source, **kw):
env: Environment in which to operate.
target: Destination(s) for copy. Must evaluate to a directory via
env.Dir(), or a list of directories. If more than one directory is
- passed, the entire source list will be copied to all target
- directories.
+ passed, the entire source list will be copied to each target
+ directory.
source: Source file(s) to copy. May be a string, Node, or a list of
mixed strings or Nodes. Strings will be passed through env.Glob() to
evaluate wildcards. If a source evaluates to a directory, the entire
directory will be recursively copied.
From env:
- REPLICATE_RENAME: A list of pairs of regex search and replacement strings.
+ REPLICATE_REPLACE: A list of pairs of regex search and replacement strings.
Each full destination path has substitution performed on each pair
(search_regex, replacement) in order.
diff --git a/site_scons/site_tools/target_platform_linux.py b/site_scons/site_tools/target_platform_linux.py
index 776b09c..83b37b0 100644
--- a/site_scons/site_tools/target_platform_linux.py
+++ b/site_scons/site_tools/target_platform_linux.py
@@ -73,6 +73,15 @@ def generate(env):
TARGET_PLATFORM='LINUX',
COMPONENT_PLATFORM_SETUP=ComponentPlatformSetup,
CCFLAG_INCLUDE='-include', # Command line option to include a header
+
+ # Code coverage related.
+ COVERAGE_CCFLAGS=['-ftest-coverage', '-fprofile-arcs'],
+ COVERAGE_LIBS='gcov',
+ COVERAGE_STOP_CMD=[
+ '$COVERAGE_MCOV --directory "$TARGET_ROOT" --output "$TARGET"',
+ ('$COVERAGE_GENHTML --output-directory $COVERAGE_HTML_DIR '
+ '$COVERAGE_OUTPUT_FILE'),
+ ],
)
env.Append(
diff --git a/site_scons/site_tools/target_platform_mac.py b/site_scons/site_tools/target_platform_mac.py
index 4c35334..2d5e419 100644
--- a/site_scons/site_tools/target_platform_mac.py
+++ b/site_scons/site_tools/target_platform_mac.py
@@ -138,6 +138,15 @@ def generate(env):
TARGET_PLATFORM='MAC',
COMPONENT_PLATFORM_SETUP=ComponentPlatformSetup,
CCFLAG_INCLUDE='-include', # Command line option to include a header
+
+ # Code coverage related.
+ COVERAGE_CCFLAGS=['-ftest-coverage', '-fprofile-arcs'],
+ COVERAGE_LIBS='gcov',
+ COVERAGE_STOP_CMD=[
+ '$COVERAGE_MCOV --directory "$TARGET_ROOT" --output "$TARGET"',
+ ('$COVERAGE_GENHTML --output-directory $COVERAGE_HTML_DIR '
+ '$COVERAGE_OUTPUT_FILE'),
+ ],
)
env.Append(
diff --git a/site_scons/site_tools/target_platform_windows.py b/site_scons/site_tools/target_platform_windows.py
index f225435..a0a70e8 100644
--- a/site_scons/site_tools/target_platform_windows.py
+++ b/site_scons/site_tools/target_platform_windows.py
@@ -78,14 +78,14 @@ def WaitForWritable(target, source, env):
return 1
-def RunManifest(target, source, env, resource_num):
+def RunManifest(target, source, env, cmd):
"""Run the Microsoft Visual Studio manifest tool (mt.exe).
Args:
target: List of target nodes.
source: List of source nodes.
env: Environment context.
- resource_num: Resource number to modify in target (1=exe, 2=dll).
+ cmd: Command to run.
Returns:
Zero if success, nonzero if error.
@@ -101,12 +101,7 @@ def RunManifest(target, source, env, resource_num):
with mt.exe returning an errorlevel (return code) of 31. The workaround is
to retry running mt.exe after a short delay.
"""
-
- cmdline = env.subst(
- 'mt.exe -nologo -manifest "$MANIFEST_FILE" -outputresource:"$TARGET";%d'
- % resource_num,
- target=target, source=source)
- print cmdline
+ cmdline = env.subst(cmd, target=target, source=source)
for retry in range(5):
# If this is a retry, print a message and delay first
@@ -129,17 +124,21 @@ def RunManifest(target, source, env, resource_num):
def RunManifestExe(target, source, env):
"""Calls RunManifest for updating an executable (resource_num=1)."""
- return RunManifest(target, source, env, resource_num=1)
+ return RunManifest(target, source, env, cmd='$MANIFEST_COM')
def RunManifestDll(target, source, env):
"""Calls RunManifest for updating a dll (resource_num=2)."""
- return RunManifest(target, source, env, resource_num=2)
+ return RunManifest(target, source, env, cmd='$SHMANIFEST_COM')
def ComponentPlatformSetup(env, builder_name):
"""Hook to allow platform to modify environment inside a component builder.
+ This is called on a clone of the environment passed into the component
+ builder, and is the last modification done to that environment before using
+ it to call the underlying SCons builder (env.Program(), env.Library(), etc.)
+
Args:
env: Environment to modify
builder_name: Name of the builder
@@ -172,6 +171,34 @@ def ComponentPlatformSetup(env, builder_name):
LINKFLAGS=['/SUBSYSTEM:CONSOLE'],
)
+ # Make sure link methods are lists, so we can append to them below
+ env['LINKCOM'] = [env['LINKCOM']]
+ env['SHLINKCOM'] = [env['SHLINKCOM']]
+
+ # Support manifest file generation and consumption
+ if env.get('MANIFEST_FILE'):
+ env.Append(
+ LINKCOM=[SCons.Script.Action(RunManifestExe, '$MANIFEST_COMSTR')],
+ SHLINKCOM=[SCons.Script.Action(RunManifestDll, '$SHMANIFEST_COMSTR')],
+ )
+
+ # If manifest file should be autogenerated, add the -manifest link line and
+ # delete the generated manfest after running mt.exe.
+ if env.get('MANFEST_FILE_GENERATED_BY_LINK'):
+ env.Append(
+ LINKFLAGS=['-manifest'],
+ LINKCOM=[SCons.Script.Delete('$MANFEST_FILE_GENERATED_BY_LINK')],
+ SHLINKCOM=[SCons.Script.Delete('$MANFEST_FILE_GENERATED_BY_LINK')],
+ )
+
+ # Wait for the output file to be writable before releasing control to
+ # SCons. Windows virus scanners temporarily lock modified executable files
+ # for scanning, which causes SCons's env.Install() to fail intermittently.
+ env.Append(
+ LINKCOM=[SCons.Script.Action(WaitForWritable, None)],
+ SHLINKCOM=[SCons.Script.Action(WaitForWritable, None)],
+ )
+
#------------------------------------------------------------------------------
@@ -222,8 +249,48 @@ def generate(env):
# A better rebuild command (actually cleans, then rebuild)
MSVSREBUILDCOM=''.join(['$MSVSSCONSCOM -c "$MSVSBUILDTARGET" && ',
'$MSVSSCONSCOM "$MSVSBUILDTARGET"']),
+ )
- CCFLAG_INCLUDE='/FI', # Command line option to include a header
+ env.SetDefault(
+ # Command line option to include a header
+ CCFLAG_INCLUDE='/FI',
+
+ # Generate PDBs matching target name by default.
+ PDB='${TARGET.base}.pdb',
+
+ # Code coverage related.
+ COVERAGE_LINKFLAGS='/PROFILE', # Requires vc_80 or higher.
+ COVERAGE_LINKCOM_EXTRAS='$COVERAGE_VSINSTR /COVERAGE $TARGET',
+ # NOTE: need to ignore error in return type here, the tool has issues.
+ # Thus a - is added.
+ COVERAGE_START_CMD=[
+ # If a previous build was cancelled or crashed, VSPerfCmd may still
+ # be running, which causes future coverage runs to fail. Make sure
+ # it's shut down before starting coverage up again.
+ '-$COVERAGE_VSPERFCMD -shutdown',
+ '$COVERAGE_VSPERFCMD -start:coverage '
+ '-output:${COVERAGE_OUTPUT_FILE}.pre'],
+ COVERAGE_STOP_CMD=[
+ '-$COVERAGE_VSPERFCMD -shutdown',
+ '$COVERAGE_ANALYZER -sym_path=. ${COVERAGE_OUTPUT_FILE}.pre.coverage',
+ SCons.Script.Copy('$COVERAGE_OUTPUT_FILE',
+ '${COVERAGE_OUTPUT_FILE}.pre.coverage.lcov'),
+ ],
+ COVERAGE_EXTRA_PATHS=['$COVERAGE_ANALYZER_DIR'],
+
+ # Manifest options
+ # When link.exe is run with '-manifest', it always generated a manifest
+ # with this name.
+ MANFEST_FILE_GENERATED_BY_LINK='${TARGET}.manifest',
+ # Manifest file to use as input to mt.exe. Can be overridden to pass in
+ # a pregenerated manifest file.
+ MANIFEST_FILE='$MANFEST_FILE_GENERATED_BY_LINK',
+ MANIFEST_COM=('mt.exe -nologo -manifest "$MANIFEST_FILE" '
+ '-outputresource:"$TARGET";1'),
+ MANIFEST_COMSTR='$MANIFEST_COM',
+ SHMANIFEST_COM=('mt.exe -nologo -manifest "$MANIFEST_FILE" '
+ '-outputresource:"$TARGET";2'),
+ SHMANIFEST_COMSTR='$SHMANIFEST_COM',
)
env.Append(
@@ -233,7 +300,7 @@ def generate(env):
# Turn up the warning level
CCFLAGS=['/W3'],
- # Force x86 platform for now
+ # Force x86 platform, generate manifests
LINKFLAGS=['/MACHINE:X86'],
ARFLAGS=['/MACHINE:X86'],
@@ -251,27 +318,14 @@ def generate(env):
'/MT', # link with LIBCMT.LIB (multi-threaded, static linked crt)
'/GS', # enable security checks
],
+ LINKFLAGS_OPTIMIZED=['/PDBPATH:none'],
# Settings for component_builders
COMPONENT_LIBRARY_LINK_SUFFIXES=['.lib'],
COMPONENT_LIBRARY_DEBUG_SUFFIXES=['.pdb'],
)
- # Add manifests to EXEs and DLLs
- env['MANIFEST_FILE'] = '${TARGET}.manifest' # To allow override.
- wait_action = SCons.Script.Action(WaitForWritable,
- lambda target, source, env: ''),
- env['LINKCOM'] = [
- env['LINKCOM'],
- SCons.Script.Action(RunManifestExe, lambda target, source, env: ''),
- SCons.Script.Delete('${TARGET}.manifest'),
- wait_action,
- ]
- env['SHLINKCOM'] = [
- env['SHLINKCOM'],
- SCons.Script.Action(RunManifestDll, lambda target, source, env: ''),
- SCons.Script.Delete('${TARGET}.manifest'),
- wait_action,
- ]
- env['WINDOWS_INSERT_MANIFESTS'] = True
- env.Append(LINKFLAGS=['-manifest'])
+ # TODO(sgk): mslink.py creates a shlibLinkAction which doesn't specify
+ # '$SHLINKCOMSTR' as its command string. This breaks --brief. For now,
+ # hack into the existing action and override its command string.
+ env['SHLINKCOM'].list[0].cmdstr = '$SHLINKCOMSTR'
diff --git a/site_scons/site_tools/windows_hard_link.py b/site_scons/site_tools/windows_hard_link.py
index 36c768b..9fae120 100644
--- a/site_scons/site_tools/windows_hard_link.py
+++ b/site_scons/site_tools/windows_hard_link.py
@@ -40,7 +40,7 @@ import stat
import sys
import SCons
-if sys.platform in ('win32', 'cygwin'):
+if sys.platform == 'win32':
# Only attempt to load pywin32 on Windows systems
try:
import win32file