diff options
author | bradnelson@chromium.org <bradnelson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-12-04 19:35:47 +0000 |
---|---|---|
committer | bradnelson@chromium.org <bradnelson@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-12-04 19:35:47 +0000 |
commit | 5a17959168f700202c3ee498e88cca7bcfa43a97 (patch) | |
tree | f0c8d497ded5551516310cebec76c3395880c19c /site_scons | |
parent | aedd85af7d7d0c90ed343ece4c66660db00841ec (diff) | |
download | chromium_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.py | 123 | ||||
-rw-r--r-- | site_scons/site_tools/component_bits.py | 4 | ||||
-rw-r--r-- | site_scons/site_tools/component_setup.py | 46 | ||||
-rwxr-xr-x | site_scons/site_tools/component_targets.py | 9 | ||||
-rwxr-xr-x | site_scons/site_tools/component_targets_msvs.py | 2 | ||||
-rw-r--r-- | site_scons/site_tools/concat_source.py | 17 | ||||
-rw-r--r-- | site_scons/site_tools/defer.py | 71 | ||||
-rw-r--r-- | site_scons/site_tools/replace_strings.py | 5 | ||||
-rw-r--r-- | site_scons/site_tools/replicate.py | 6 | ||||
-rw-r--r-- | site_scons/site_tools/target_platform_linux.py | 9 | ||||
-rw-r--r-- | site_scons/site_tools/target_platform_mac.py | 9 | ||||
-rw-r--r-- | site_scons/site_tools/target_platform_windows.py | 114 | ||||
-rw-r--r-- | site_scons/site_tools/windows_hard_link.py | 2 |
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 |