| OLD | NEW |
| 1 #!/usr/bin/python2.4 | 1 #!/usr/bin/python2.4 |
| 2 # Copyright 2008, Google Inc. | 2 # Copyright 2008, Google Inc. |
| 3 # All rights reserved. | 3 # All rights reserved. |
| 4 # | 4 # |
| 5 # Redistribution and use in source and binary forms, with or without | 5 # Redistribution and use in source and binary forms, with or without |
| 6 # modification, are permitted provided that the following conditions are | 6 # modification, are permitted provided that the following conditions are |
| 7 # met: | 7 # met: |
| 8 # | 8 # |
| 9 # * Redistributions of source code must retain the above copyright | 9 # * Redistributions of source code must retain the above copyright |
| 10 # notice, this list of conditions and the following disclaimer. | 10 # notice, this list of conditions and the following disclaimer. |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 71 return 0 # Successfully opened file for write, so we're done | 71 return 0 # Successfully opened file for write, so we're done |
| 72 except (IOError, OSError): | 72 except (IOError, OSError): |
| 73 print 'Waiting for access to %s...' % target_path | 73 print 'Waiting for access to %s...' % target_path |
| 74 time.sleep(1) | 74 time.sleep(1) |
| 75 | 75 |
| 76 # If we're still here, fail | 76 # If we're still here, fail |
| 77 print 'Timeout waiting for access to %s.' % target_path | 77 print 'Timeout waiting for access to %s.' % target_path |
| 78 return 1 | 78 return 1 |
| 79 | 79 |
| 80 | 80 |
| 81 def RunManifest(target, source, env, resource_num): | 81 def RunManifest(target, source, env, cmd): |
| 82 """Run the Microsoft Visual Studio manifest tool (mt.exe). | 82 """Run the Microsoft Visual Studio manifest tool (mt.exe). |
| 83 | 83 |
| 84 Args: | 84 Args: |
| 85 target: List of target nodes. | 85 target: List of target nodes. |
| 86 source: List of source nodes. | 86 source: List of source nodes. |
| 87 env: Environment context. | 87 env: Environment context. |
| 88 resource_num: Resource number to modify in target (1=exe, 2=dll). | 88 cmd: Command to run. |
| 89 | 89 |
| 90 Returns: | 90 Returns: |
| 91 Zero if success, nonzero if error. | 91 Zero if success, nonzero if error. |
| 92 | 92 |
| 93 The mt.exe tool seems to experience intermittent failures trying to write to | 93 The mt.exe tool seems to experience intermittent failures trying to write to |
| 94 .exe or .dll files. Antivirus software makes this worse, but the problem | 94 .exe or .dll files. Antivirus software makes this worse, but the problem |
| 95 can still occur even if antivirus software is disabled. The failures look | 95 can still occur even if antivirus software is disabled. The failures look |
| 96 like: | 96 like: |
| 97 | 97 |
| 98 mt.exe : general error c101008d: Failed to write the updated manifest to | 98 mt.exe : general error c101008d: Failed to write the updated manifest to |
| 99 the resource of file "(name of exe)". Access is denied. | 99 the resource of file "(name of exe)". Access is denied. |
| 100 | 100 |
| 101 with mt.exe returning an errorlevel (return code) of 31. The workaround is | 101 with mt.exe returning an errorlevel (return code) of 31. The workaround is |
| 102 to retry running mt.exe after a short delay. | 102 to retry running mt.exe after a short delay. |
| 103 """ | 103 """ |
| 104 | 104 cmdline = env.subst(cmd, target=target, source=source) |
| 105 cmdline = env.subst( | |
| 106 'mt.exe -nologo -manifest "$MANIFEST_FILE" -outputresource:"$TARGET";%d' | |
| 107 % resource_num, | |
| 108 target=target, source=source) | |
| 109 print cmdline | |
| 110 | 105 |
| 111 for retry in range(5): | 106 for retry in range(5): |
| 112 # If this is a retry, print a message and delay first | 107 # If this is a retry, print a message and delay first |
| 113 if retry: | 108 if retry: |
| 114 # mt.exe failed to write to the target file. Print a warning message, | 109 # mt.exe failed to write to the target file. Print a warning message, |
| 115 # delay 3 seconds, and retry. | 110 # delay 3 seconds, and retry. |
| 116 print 'Warning: mt.exe failed to write to %s; retrying.' % target[0] | 111 print 'Warning: mt.exe failed to write to %s; retrying.' % target[0] |
| 117 time.sleep(3) | 112 time.sleep(3) |
| 118 | 113 |
| 119 return_code, output = command_output.RunCommand( | 114 return_code, output = command_output.RunCommand( |
| 120 cmdline, env=env['ENV'], echo_output=False) | 115 cmdline, env=env['ENV'], echo_output=False) |
| 121 if return_code != 31: # Something other than the intermittent error | 116 if return_code != 31: # Something other than the intermittent error |
| 122 break | 117 break |
| 123 | 118 |
| 124 # Pass through output (if any) and return code from manifest | 119 # Pass through output (if any) and return code from manifest |
| 125 if output: | 120 if output: |
| 126 print output | 121 print output |
| 127 return return_code | 122 return return_code |
| 128 | 123 |
| 129 | 124 |
| 130 def RunManifestExe(target, source, env): | 125 def RunManifestExe(target, source, env): |
| 131 """Calls RunManifest for updating an executable (resource_num=1).""" | 126 """Calls RunManifest for updating an executable (resource_num=1).""" |
| 132 return RunManifest(target, source, env, resource_num=1) | 127 return RunManifest(target, source, env, cmd='$MANIFEST_COM') |
| 133 | 128 |
| 134 | 129 |
| 135 def RunManifestDll(target, source, env): | 130 def RunManifestDll(target, source, env): |
| 136 """Calls RunManifest for updating a dll (resource_num=2).""" | 131 """Calls RunManifest for updating a dll (resource_num=2).""" |
| 137 return RunManifest(target, source, env, resource_num=2) | 132 return RunManifest(target, source, env, cmd='$SHMANIFEST_COM') |
| 138 | 133 |
| 139 | 134 |
| 140 def ComponentPlatformSetup(env, builder_name): | 135 def ComponentPlatformSetup(env, builder_name): |
| 141 """Hook to allow platform to modify environment inside a component builder. | 136 """Hook to allow platform to modify environment inside a component builder. |
| 142 | 137 |
| 138 This is called on a clone of the environment passed into the component |
| 139 builder, and is the last modification done to that environment before using |
| 140 it to call the underlying SCons builder (env.Program(), env.Library(), etc.) |
| 141 |
| 143 Args: | 142 Args: |
| 144 env: Environment to modify | 143 env: Environment to modify |
| 145 builder_name: Name of the builder | 144 builder_name: Name of the builder |
| 146 """ | 145 """ |
| 147 if env.get('ENABLE_EXCEPTIONS'): | 146 if env.get('ENABLE_EXCEPTIONS'): |
| 148 env.FilterOut( | 147 env.FilterOut( |
| 149 CPPDEFINES=['_HAS_EXCEPTIONS=0'], | 148 CPPDEFINES=['_HAS_EXCEPTIONS=0'], |
| 150 # There are problems with LTCG when some files are compiled with | 149 # There are problems with LTCG when some files are compiled with |
| 151 # exceptions and some aren't (the v-tables for STL and BOOST classes | 150 # exceptions and some aren't (the v-tables for STL and BOOST classes |
| 152 # don't match). Therefore, turn off LTCG when exceptions are enabled. | 151 # don't match). Therefore, turn off LTCG when exceptions are enabled. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 165 if builder_name == 'ComponentTestProgram': | 164 if builder_name == 'ComponentTestProgram': |
| 166 env.FilterOut( | 165 env.FilterOut( |
| 167 CPPDEFINES=['_WINDOWS'], | 166 CPPDEFINES=['_WINDOWS'], |
| 168 LINKFLAGS=['/SUBSYSTEM:WINDOWS'], | 167 LINKFLAGS=['/SUBSYSTEM:WINDOWS'], |
| 169 ) | 168 ) |
| 170 env.Append( | 169 env.Append( |
| 171 CPPDEFINES=['_CONSOLE'], | 170 CPPDEFINES=['_CONSOLE'], |
| 172 LINKFLAGS=['/SUBSYSTEM:CONSOLE'], | 171 LINKFLAGS=['/SUBSYSTEM:CONSOLE'], |
| 173 ) | 172 ) |
| 174 | 173 |
| 174 # Make sure link methods are lists, so we can append to them below |
| 175 env['LINKCOM'] = [env['LINKCOM']] |
| 176 env['SHLINKCOM'] = [env['SHLINKCOM']] |
| 177 |
| 178 # Support manifest file generation and consumption |
| 179 if env.get('MANIFEST_FILE'): |
| 180 env.Append( |
| 181 LINKCOM=[SCons.Script.Action(RunManifestExe, '$MANIFEST_COMSTR')], |
| 182 SHLINKCOM=[SCons.Script.Action(RunManifestDll, '$SHMANIFEST_COMSTR')], |
| 183 ) |
| 184 |
| 185 # If manifest file should be autogenerated, add the -manifest link line and |
| 186 # delete the generated manfest after running mt.exe. |
| 187 if env.get('MANFEST_FILE_GENERATED_BY_LINK'): |
| 188 env.Append( |
| 189 LINKFLAGS=['-manifest'], |
| 190 LINKCOM=[SCons.Script.Delete('$MANFEST_FILE_GENERATED_BY_LINK')], |
| 191 SHLINKCOM=[SCons.Script.Delete('$MANFEST_FILE_GENERATED_BY_LINK')], |
| 192 ) |
| 193 |
| 194 # Wait for the output file to be writable before releasing control to |
| 195 # SCons. Windows virus scanners temporarily lock modified executable files |
| 196 # for scanning, which causes SCons's env.Install() to fail intermittently. |
| 197 env.Append( |
| 198 LINKCOM=[SCons.Script.Action(WaitForWritable, None)], |
| 199 SHLINKCOM=[SCons.Script.Action(WaitForWritable, None)], |
| 200 ) |
| 201 |
| 175 #------------------------------------------------------------------------------ | 202 #------------------------------------------------------------------------------ |
| 176 | 203 |
| 177 | 204 |
| 178 def generate(env): | 205 def generate(env): |
| 179 # NOTE: SCons requires the use of this name, which fails gpylint. | 206 # NOTE: SCons requires the use of this name, which fails gpylint. |
| 180 """SCons entry point for this tool.""" | 207 """SCons entry point for this tool.""" |
| 181 | 208 |
| 182 # Bring in the outside PATH, INCLUDE, and LIB if not blocked. | 209 # Bring in the outside PATH, INCLUDE, and LIB if not blocked. |
| 183 if not env.get('MSVC_BLOCK_ENVIRONMENT_CHANGES'): | 210 if not env.get('MSVC_BLOCK_ENVIRONMENT_CHANGES'): |
| 184 env.AppendENVPath('PATH', os.environ.get('PATH', '[]')) | 211 env.AppendENVPath('PATH', os.environ.get('PATH', '[]')) |
| (...skipping 30 matching lines...) Expand all Loading... |
| 215 exclusive_groups=('target_platform')) | 242 exclusive_groups=('target_platform')) |
| 216 env.SetBits('windows') | 243 env.SetBits('windows') |
| 217 | 244 |
| 218 env.Replace( | 245 env.Replace( |
| 219 TARGET_PLATFORM='WINDOWS', | 246 TARGET_PLATFORM='WINDOWS', |
| 220 COMPONENT_PLATFORM_SETUP=ComponentPlatformSetup, | 247 COMPONENT_PLATFORM_SETUP=ComponentPlatformSetup, |
| 221 | 248 |
| 222 # A better rebuild command (actually cleans, then rebuild) | 249 # A better rebuild command (actually cleans, then rebuild) |
| 223 MSVSREBUILDCOM=''.join(['$MSVSSCONSCOM -c "$MSVSBUILDTARGET" && ', | 250 MSVSREBUILDCOM=''.join(['$MSVSSCONSCOM -c "$MSVSBUILDTARGET" && ', |
| 224 '$MSVSSCONSCOM "$MSVSBUILDTARGET"']), | 251 '$MSVSSCONSCOM "$MSVSBUILDTARGET"']), |
| 252 ) |
| 225 | 253 |
| 226 CCFLAG_INCLUDE='/FI', # Command line option to include a header | 254 env.SetDefault( |
| 255 # Command line option to include a header |
| 256 CCFLAG_INCLUDE='/FI', |
| 257 |
| 258 # Generate PDBs matching target name by default. |
| 259 PDB='${TARGET.base}.pdb', |
| 260 |
| 261 # Code coverage related. |
| 262 COVERAGE_LINKFLAGS='/PROFILE', # Requires vc_80 or higher. |
| 263 COVERAGE_LINKCOM_EXTRAS='$COVERAGE_VSINSTR /COVERAGE $TARGET', |
| 264 # NOTE: need to ignore error in return type here, the tool has issues. |
| 265 # Thus a - is added. |
| 266 COVERAGE_START_CMD=[ |
| 267 # If a previous build was cancelled or crashed, VSPerfCmd may still |
| 268 # be running, which causes future coverage runs to fail. Make sure |
| 269 # it's shut down before starting coverage up again. |
| 270 '-$COVERAGE_VSPERFCMD -shutdown', |
| 271 '$COVERAGE_VSPERFCMD -start:coverage ' |
| 272 '-output:${COVERAGE_OUTPUT_FILE}.pre'], |
| 273 COVERAGE_STOP_CMD=[ |
| 274 '-$COVERAGE_VSPERFCMD -shutdown', |
| 275 '$COVERAGE_ANALYZER -sym_path=. ${COVERAGE_OUTPUT_FILE}.pre.coverage', |
| 276 SCons.Script.Copy('$COVERAGE_OUTPUT_FILE', |
| 277 '${COVERAGE_OUTPUT_FILE}.pre.coverage.lcov'), |
| 278 ], |
| 279 COVERAGE_EXTRA_PATHS=['$COVERAGE_ANALYZER_DIR'], |
| 280 |
| 281 # Manifest options |
| 282 # When link.exe is run with '-manifest', it always generated a manifest |
| 283 # with this name. |
| 284 MANFEST_FILE_GENERATED_BY_LINK='${TARGET}.manifest', |
| 285 # Manifest file to use as input to mt.exe. Can be overridden to pass in |
| 286 # a pregenerated manifest file. |
| 287 MANIFEST_FILE='$MANFEST_FILE_GENERATED_BY_LINK', |
| 288 MANIFEST_COM=('mt.exe -nologo -manifest "$MANIFEST_FILE" ' |
| 289 '-outputresource:"$TARGET";1'), |
| 290 MANIFEST_COMSTR='$MANIFEST_COM', |
| 291 SHMANIFEST_COM=('mt.exe -nologo -manifest "$MANIFEST_FILE" ' |
| 292 '-outputresource:"$TARGET";2'), |
| 293 SHMANIFEST_COMSTR='$SHMANIFEST_COM', |
| 227 ) | 294 ) |
| 228 | 295 |
| 229 env.Append( | 296 env.Append( |
| 230 HOST_PLATFORMS=['WINDOWS'], | 297 HOST_PLATFORMS=['WINDOWS'], |
| 231 CPPDEFINES=['OS_WINDOWS=OS_WINDOWS'], | 298 CPPDEFINES=['OS_WINDOWS=OS_WINDOWS'], |
| 232 | 299 |
| 233 # Turn up the warning level | 300 # Turn up the warning level |
| 234 CCFLAGS=['/W3'], | 301 CCFLAGS=['/W3'], |
| 235 | 302 |
| 236 # Force x86 platform for now | 303 # Force x86 platform, generate manifests |
| 237 LINKFLAGS=['/MACHINE:X86'], | 304 LINKFLAGS=['/MACHINE:X86'], |
| 238 ARFLAGS=['/MACHINE:X86'], | 305 ARFLAGS=['/MACHINE:X86'], |
| 239 | 306 |
| 240 # Settings for debug | 307 # Settings for debug |
| 241 CCFLAGS_DEBUG=[ | 308 CCFLAGS_DEBUG=[ |
| 242 '/Od', # disable optimizations | 309 '/Od', # disable optimizations |
| 243 '/RTC1', # enable fast checks | 310 '/RTC1', # enable fast checks |
| 244 '/MTd', # link with LIBCMTD.LIB debug lib | 311 '/MTd', # link with LIBCMTD.LIB debug lib |
| 245 ], | 312 ], |
| 246 LINKFLAGS_DEBUG=['/DEBUG'], | 313 LINKFLAGS_DEBUG=['/DEBUG'], |
| 247 | 314 |
| 248 # Settings for optimized | 315 # Settings for optimized |
| 249 CCFLAGS_OPTIMIZED=[ | 316 CCFLAGS_OPTIMIZED=[ |
| 250 '/O1', # optimize for size | 317 '/O1', # optimize for size |
| 251 '/MT', # link with LIBCMT.LIB (multi-threaded, static linked crt) | 318 '/MT', # link with LIBCMT.LIB (multi-threaded, static linked crt) |
| 252 '/GS', # enable security checks | 319 '/GS', # enable security checks |
| 253 ], | 320 ], |
| 321 LINKFLAGS_OPTIMIZED=['/PDBPATH:none'], |
| 254 | 322 |
| 255 # Settings for component_builders | 323 # Settings for component_builders |
| 256 COMPONENT_LIBRARY_LINK_SUFFIXES=['.lib'], | 324 COMPONENT_LIBRARY_LINK_SUFFIXES=['.lib'], |
| 257 COMPONENT_LIBRARY_DEBUG_SUFFIXES=['.pdb'], | 325 COMPONENT_LIBRARY_DEBUG_SUFFIXES=['.pdb'], |
| 258 ) | 326 ) |
| 259 | 327 |
| 260 # Add manifests to EXEs and DLLs | 328 # TODO(sgk): mslink.py creates a shlibLinkAction which doesn't specify |
| 261 env['MANIFEST_FILE'] = '${TARGET}.manifest' # To allow override. | 329 # '$SHLINKCOMSTR' as its command string. This breaks --brief. For now, |
| 262 wait_action = SCons.Script.Action(WaitForWritable, | 330 # hack into the existing action and override its command string. |
| 263 lambda target, source, env: ''), | 331 env['SHLINKCOM'].list[0].cmdstr = '$SHLINKCOMSTR' |
| 264 env['LINKCOM'] = [ | |
| 265 env['LINKCOM'], | |
| 266 SCons.Script.Action(RunManifestExe, lambda target, source, env: ''), | |
| 267 SCons.Script.Delete('${TARGET}.manifest'), | |
| 268 wait_action, | |
| 269 ] | |
| 270 env['SHLINKCOM'] = [ | |
| 271 env['SHLINKCOM'], | |
| 272 SCons.Script.Action(RunManifestDll, lambda target, source, env: ''), | |
| 273 SCons.Script.Delete('${TARGET}.manifest'), | |
| 274 wait_action, | |
| 275 ] | |
| 276 env['WINDOWS_INSERT_MANIFESTS'] = True | |
| 277 env.Append(LINKFLAGS=['-manifest']) | |
| OLD | NEW |