#!/usr/bin/python2.4 #
#
#
#
#
#
#
#
#
import os
_msc_ver = 1400
_PUBLISHER_NAME = 'Google' _PRODUCT_NAME = 'Update' _ACTIVEX_NAME = 'npGoogleOneClick' _BHO_NAME = 'GoopdateBho'
_BUILD_SERVER_CERTIFICATE_HASH = 'fe5008fe0da7a2033816752d6eafe95214f5a7e1'
_PROXY_CLSID_IS = ('{0x29a96789, 0x9595, 0x4947, ' '{0xbe, 0xdb, 0xf, 0xcc, 0x77, 0x6f, 0x7d, 0xb8}}')
#
# execfile('VERSION')
win_env = Environment()
win_env['PLATFORM_SDK_DIR'] = '$PLATFORM_SDK_VISTA_6_0_DIR'
win_env.Tool('component_setup') win_env.Tool('target_platform_windows')
win_env.Tool('masm')
win_env.Tool('atlmfc_vc80')
win_env.Tool('code_signing') _signtool_path = os.path.join(os.environ['OMAHA_VISTASDK_DIR'], 'bin\signtool.exe') win_env['SIGNTOOL'] = '"' + _signtool_path + '"'
win_env.FilterOut(CPPDEFINES = ['OS_WINDOWS=OS_WINDOWS'])
win_env.Tool('component_targets_msvs')
del win_env['MANIFEST_FILE']
if win_env['ENV'].has_key('SYSTEMROOT'): if win_env['ENV'].has_key('SystemRoot'): del win_env['ENV']['SYSTEMROOT'] del os.environ['SYSTEMROOT']
win_env['COMPONENT_TEST_SUBSYSTEM_WINDOWS'] = 1
AddOption( '--authenticode_file', action='store', nargs=1, type='string', default='$MAIN_DIR/data/OmahaTestCert.pfx' )
default_cert_password = 'test' AddOption( '--authenticode_password', action='store', nargs=1, type='string', default=default_cert_password )
AddOption( '--patching_certificate', action='store', nargs=1, type='string', default='$MAIN_DIR/data/OmahaTestCert.cer' )
AddOption( '--official_build_path', action='store', nargs=1, type='string', default=None )
DeclareBit('use_precompiled_headers', 'Use precompiled headers in build') DeclareBit('official_installers', 'Building using checked-in binaries') DeclareBit('build_server', 'Running on the build server') DeclareBit('test_certificate', 'Files will be signed with the test certificate') DeclareBit('bin', 'Building from pre-built binaries') DeclareBit('min', 'Building minimal set of projects') DeclareBit('all', 'Building all Projects') DeclareBit('msvs', 'Building Visual Studio solution files')
win_env.SetBitFromOption('official_installers', False)
win_env.SetBitFromOption('build_server', False)
win_env.SetBitFromOption('bin', False)
win_env.SetBitFromOption('min', False)
win_env.SetBitFromOption('all', False)
win_env.SetBitFromOption('msvs', False)
if win_env.Bit('build_server'): win_env.SetBits('all')
if win_env.Bit('all'): win_env.ClearBits('min')
if not win_env.Bit('build_server'): win_env.Replace( CERTIFICATE_PATH=GetOption('authenticode_file'), CERTIFICATE_PASSWORD=GetOption('authenticode_password'), )
# Store whether we're using the default test cert separately, because # we won't always know what the default password was. if GetOption('authenticode_password') is default_cert_password: win_env.SetBits('test_certificate')
win_env.SetBitFromOption('use_precompiled_headers', True)
if win_env.Bit('use_precompiled_headers'): print 'Using precompiled headers.'
def _EnablePrecompile(self_env, target_name): if self_env.Bit('use_precompiled_headers'):
# We enable all warnings on all levels. The goal is to fix the code that # we have written and to programmatically disable the warnings for the # code we do not control. This list of warnings should shrink as the code # gets fixed. self_env.FilterOut(CCFLAGS=['/W3']) self_env.Append( CCFLAGS = [ '/W4', '/Wall', ], INCLUDES = [ '$MAIN_DIR/precompile/precompile.h' ], )
self_env['PCHSTOP'] = '$MAIN_DIR/precompile/precompile.h'
pch_env = self_env.Clone() # Must manually force-include the header, as the precompilation step does # not evaluate $INCLUDES pch_env.Append(CCFLAGS = ['/FI$MAIN_DIR/precompile/precompile.h']) # Append 'pch' to the target base name to prevent target name collisions. # One case where this might have occurred is when a .cc file has the same # base name as the target program/library. pch_output = pch_env.PCH( target=target_name.replace('.', '') + '_pch' + '.pch', source='$MAIN_DIR/precompile/precompile.cc', )
self_env['PCH'] = pch_output[0]
# Return the pch .obj file that is created, so it can be # included with the inputs of a module return [pch_output[1]]
win_env.AddMethod(_EnablePrecompile, 'EnablePrecompile')
def _SignDotNetManifest(self_env, target, unsigned_manifest): sign_manifest_cmd =('@mage -Sign $SOURCE -ToFile $TARGET -TimestampUri ' 'http://timestamp.verisign.com/scripts/timstamp.dll ')
if self_env.Bit('build_server'): # If signing fails with the following error, the hash may not match any # certificates: "Internal error, please try again. Object reference not set # to an instance of an object." sign_manifest_cmd += ('-CertHash ' + self_env['build_server_certificate_hash']) else: sign_manifest_cmd += '-CertFile %s -Password %s' % ( GetOption('authenticode_file'), GetOption('authenticode_password'))
signed_manifest = self_env.Command( target=target, source=unsigned_manifest, action=sign_manifest_cmd )
return signed_manifest
win_env.AddMethod(_SignDotNetManifest, 'SignDotNetManifest')
def _SetProductVersion(self_env, version_major, version_minor, version_build, version_patch): build_two_versions = False
if (self_env.Bit('build_server') or 'OMAHA_BUILD_TWO_VERSIONS' in os.environ.keys()): build_two_versions = True
if build_two_versions: self_env['product_version_series'] = [0, 1] else: self_env['product_version_series'] = [0]
if version_patch > 0: original_value = version_patch value_name = 'patch' else: original_value = version_build value_name = 'build' if 2 * (original_value / 2) == original_value: raise Exception('ERROR: By convention, the %s number in VERSION ' '(currently %d) should be odd.' % (value_name, original_value))
ver_descriptions = [] versions = [] for delta in self_env['product_version_series']: # If we're doing a patch, increment that; else, increment build vp = version_patch vb = version_build if vp > 0: vp = vp + delta else: vb = vb + delta v = (version_major, version_minor, vb, vp) versions.append(v) ver_descriptions.append('%d.%d.%d.%d' % (version_major, version_minor, vb, vp))
self_env['product_version'] = versions
# print the version string so we know what build are we building on the # build server print 'Working on versions: %s' % ', '.join(ver_descriptions)
win_env.AddMethod(_SetProductVersion, 'SetProductVersion') win_env.SetProductVersion(version_major, version_minor, version_build, version_patch)
win_env['msc_ver'] = _msc_ver;
win_env['build_server_certificate_hash'] = _BUILD_SERVER_CERTIFICATE_HASH
def _SetActiveXFilenames(self_env, activex_version): activex_name = _ACTIVEX_NAME + activex_version self_env['ACTIVEX_FILENAME'] = activex_name + '.dll' self_env['ACTIVEX_UNSIGNED_FILENAME'] = activex_name + '_unsigned.dll'
win_env.AddMethod(_SetActiveXFilenames, 'SetActiveXFilenames') win_env.SetActiveXFilenames(oneclick_plugin_version)
win_env['BHO_FILENAME'] = '%s.dll' % (_BHO_NAME) win_env['BHO_UNSIGNED_FILENAME'] = '%s_unsigned.dll' % (_BHO_NAME)
win_env.Append( # Add windows specific compiler flags. CCFLAGS = [ '/nologo', '/c', '/Zc:forScope', '/D_HAS_EXCEPTIONS=0', '/DCOMPILER_MSVC', '/J', '/DSTL_MSVC', '/GR-', '/D_CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES=1', '/D_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1', '/D_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1', '/WX', # warnings as errors
# # Disable the following level 4 warnings below. # '/wd4127', # conditional expression is constant '/wd4189', # local variable is initialized but not referenced '/wd4505', # unreferenced local function has been removed
# # Disable the pedantic warnings below. # '/wd4191', # unsafe conversion from 'type of expression' to # 'type required' '/wd4217', # member template functions cannot be used for # copy-assignment... '/wd4365', # conversion from 'type_1' to 'type_2', # signed/unsigned mismatch '/wd4512', # assignment operator could not be generated '/wd4514', # unreferenced inline function has been removed '/wd4555', # expression has no effect '/wd4619', # #pragma warning : there is no warning number 'number' '/wd4623', # default constructor could not be generated... '/wd4625', # copy constructor could not be generated... '/wd4626', # assignment operator could not be generated... '/wd4668', # not defined as a preprocessor macro, replacing with '0'. '/wd4710', # function not inlined '/wd4711', # function 'function' selected for inline expansion '/wd4738', # storing 32-bit float result in memory... '/wd4820', # bytes padding added after construct 'member_name' ],
# Where to look for include files. CPPPATH = [ '$MAIN_DIR', '$MAIN_DIR/..', '$MAIN_DIR/third_party/chrome', ],
# Defines for windows environment. CPPDEFINES = [ 'WIN32', '_WINDOWS', 'UNICODE', '_UNICODE', 'WIN32_LEAN_AND_MEAN', 'STRICT', 'SECURITY_WIN32', '_ATL_ALL_WARNINGS', '_ATL_CSTRING_EXPLICIT_CONSTRUCTORS', '_ATL_CSTRING_NO_CRT', '_ATL_NO_ACLAPI', '_ATL_NO_DEFAULT_LIBS', '_ATL_NO_EXCEPTIONS', '_ATL_NO_GLOBAL_SOCKET_STARTUP', '_ATL_NO_PERF_SUPPORT', '_ATL_NO_TRACK_HEAP', '_ATL_NO_UUIDOF', '_CRT_RAND_S', # rand_s support available in Windows XP only. '_WTL_NO_CSTRING', # WTL uses ATL CString instead.
# '_ATL_NO_CONNECTION_POINTS', # '_ATL_NO_DOCHOSTUIHANDLER', # '_ATL_NO_HOSTING',
# Set these C_DEFINES when APPVER=5.0 # (see win32.mak in Platform SDK) # Target Windows XP and IE 6.0 and above. 'WINVER=0x0501', '_WIN32_WINNT=0x0501', '_WIN32_IE=0x0600', '_RICHEDIT_VER=0x0010',
# don't define min and max in windef.h 'NOMINMAX',
# Logging is enabled in all modes for # diagnostics purposes. 'LOGGING', 'PUBLISHER_NAME_ANSI=\"%s\"' % _PUBLISHER_NAME, 'PRODUCT_NAME_ANSI=\"%s\"' % _PRODUCT_NAME, 'ACTIVEX_NAME=_T(\"%s\")' % _ACTIVEX_NAME, 'PROXY_CLSID_IS=%s' % _PROXY_CLSID_IS, 'OFFICIAL_BUILD=%d' % win_env.Bit('build_server'), 'TEST_CERTIFICATE=%d' % win_env.Bit('test_certificate'), 'ACTIVEX_FILENAME=_T(\"%s\")' % win_env['ACTIVEX_FILENAME'], 'ACTIVEX_VERSION_ANSI=\"%s\"' % oneclick_plugin_version, 'BHO_NAME=_T(\"%s\")' % _BHO_NAME, 'BHO_FILENAME=_T(\"%s\")' % win_env['BHO_FILENAME'], ],
# Link in some windows libraries. LIBS = [ 'advapi32', 'comdlg32', 'gdi32', 'kernel32', 'odbc32', 'odbccp32', 'ole32', 'oleaut32', 'shell32', 'user32', 'uuid', 'winspool', ],
# Common linker flags. LINKFLAGS = [ '/nologo', '/SUBSYSTEM:WINDOWS', '/MACHINE:X86', '/RELEASE', '/MAP', '/NODEFAULTLIB', ],
# Shared library specific linker flags. SHLINKFLAGS = [ '/nologo', '/SUBSYSTEM:WINDOWS', '/MACHINE:x86', ],
# Resource compiler flags. RCFLAGS = [ '/l 1033', # /l == default language ID '/DOFFICIAL_BUILD=%d' % win_env.Bit('build_server'), '/DPUBLISHER_NAME_ANSI=\"%s\"' % _PUBLISHER_NAME, '/DPRODUCT_NAME_ANSI=\"%s\"' % _PRODUCT_NAME, '/DACTIVEX_NAME=_T(\"%s\")' % _ACTIVEX_NAME, '/DACTIVEX_FILENAME=_T(\"%s\")' % win_env['ACTIVEX_FILENAME'], '/DACTIVEX_VERSION_ANSI=\"%s\"' % oneclick_plugin_version, '/DBHO_NAME=_T(\"%s\")' % _BHO_NAME, '/DBHO_FILENAME=_T(\"%s\")' % win_env['BHO_FILENAME'], ], )
if win_env.Bit('build_server'): print 'OFFICIAL_BUILD=1' print 'TEST_CERTIFICATE=%d' % win_env.Bit('test_certificate')
win_env['languages'] = [ 'ar', 'bg', 'bn', 'ca', 'cs', 'da', 'de', 'el', 'en', 'en-GB', 'es', 'es-419', 'et', 'fa', 'fi', 'fil', 'fr', 'gu', 'hi', 'hr', 'hu', 'id', 'is', 'it', 'iw', 'ja', 'kn', 'ko', 'lt', 'lv', 'ml', 'mr', 'ms', 'nl', 'no', 'or', 'pl', 'pt-BR', 'pt-PT', 'ro', 'ru', 'sk', 'sl', 'sr', 'sv', 'ta', 'te', 'th', 'tr', 'uk', 'ur', 'vi', 'zh-CN', 'zh-TW', ]
win_env['additional_shell_languages'] = [ 'am', 'sw', 'userdefault', 'zh-HK', ]
win_env.AppendENVPath('PATH', os.environ['OMAHA_PYTHON_DIR'])
_sdk_path = os.environ['OMAHA_VISTASDK_DIR'] for mid_dir in ['', 'vc']: for env_var, sub_dir in [('PATH', 'bin'), ('INCLUDE', 'include'), ('LIB', 'lib')]: var_path = os.path.join(_sdk_path, mid_dir, sub_dir) if os.path.exists(var_path): win_env.PrependENVPath(env_var, var_path)
if not win_env.Bit('official_installers'): win_env.Append(CPPPATH = os.environ['OMAHA_WTL_DIR'])
# Make sure csc.exe can be located. win_env.AppendENVPath('PATH', os.environ['OMAHA_NET_DIR'])
win_env.AppendENVPath('PATH', os.environ['OMAHA_WIX_DIR'])
win_env.Tool('wix')
_base_dirs = [ '.', # ./build.scons is used to copy some files to staging. 'common', 'core', 'goopdate', 'google_update', 'mi_exe_stub', 'net', 'recovery', 'service', 'setup', 'statsreport', 'testing', 'third_party', 'tools', 'worker', ]
_normal_dirs = [ 'bho', 'clickonce', 'installers', 'plugins', ]
_official_installers_dirs = [ 'enterprise', 'installers', ]
_extra_dirs = [ 'enterprise', 'standalone', 'test', ]
#
# _dirs_to_build = set()
if win_env.Bit('official_installers'): # Only want to build very specific subdirs. _dirs_to_build.update(_official_installers_dirs) elif not win_env.Bit('bin'): # All other configs get the base dirs. _dirs_to_build.update(_base_dirs)
if win_env.Bit('min'): print '*** Building Minimal Set of Projects ***' else: _dirs_to_build.update(_normal_dirs)
if win_env.Bit('all'): _dirs_to_build.update(_extra_dirs)
if os.path.exists(win_env.Dir('$MAIN_DIR/internal').abspath): _dirs_to_build.update(['internal'])
win_env['BUILD_SCONSCRIPTS'] = list(_dirs_to_build)
windows_debug_env = win_env.Clone( # Give this build a name and a description. BUILD_TYPE = 'dbg-win', BUILD_TYPE_DESCRIPTION = 'Windows debug build', )
windows_debug_env.Tool('target_debug')
windows_debug_env.Append( CCFLAGS = [ '/RTC1', '/Od', '/MTd', ], CPPDEFINES = [ '_DEBUG', 'DEBUG', ], )
windows_optimized_env = win_env.Clone( # Give this build a name and a description. BUILD_TYPE = 'opt-win', BUILD_TYPE_DESCRIPTION = 'Windows optimized build', )
windows_optimized_env.Tool('target_optimized')
windows_optimized_env.Append( CCFLAGS = [ '/O1', # Optimize for small size. '/GS', '/FD', '/GL', # Global optimization goes with link flag '/LTCG' '/MT', ], CPPDEFINES = [ 'NDEBUG', 'SHIPPING' # code in 'common' needs this ], ARFLAGS = [ '/LTCG', # Set LTCG for creation of .lib files too. ], LINKFLAGS = [ '/incremental:no', '/opt:ref', '/opt:icf=32', '/opt:nowin98', '/LTCG', # Link-time code generation goes with cl flag '/GL' ], )
windows_coverage_env = windows_debug_env.Clone( BUILD_TYPE = 'coverage-win', BUILD_TYPE_DESCRIPTION = 'Windows coverage build', )
windows_coverage_env.FilterOut(BUILD_GROUPS=['all'])
windows_coverage_env.Tool('code_coverage')
for env_var in os.environ: if not env_var in windows_coverage_env['ENV']: windows_coverage_env['ENV'][env_var] = os.environ[env_var]
windows_coverage_env.Alias( 'run_omaha_unittest', '$STAGING_DIR', '$STAGING_DIR/omaha_unittest.exe' ) windows_coverage_env.Append( # TODO(omaha): We cannot run our unit tests on the new build system. Ensure # coverage works with the new test execution system. # COVERAGE_TARGETS=['run_omaha_unittest'], COVERAGE_INSTRUMENTATION_PATHS=['$STAGING_DIR'], # This value should only be used in code if absolutely necessary. CPPDEFINES=['COVERAGE_ENABLED'], )
windows_coverage_env['COVERAGE_START_CMD'] = '@echo Not starting coverage' windows_coverage_env['COVERAGE_STOP_CMD'] = '@echo Not ending coverage'
windows_coverage_env['SIGNTOOL_ORIG'] = windows_coverage_env['SIGNTOOL'] windows_coverage_env['SIGNTOOL'] = '@echo Signing deferred: '
def SigningCommand(env, filename): # Only do signing if there is a certificate file or certificate name. if env.subst('$CERTIFICATE_PATH') or env.subst('$CERTIFICATE_NAME'): # The command used to do signing (target added on below). signing_cmd = '$SIGNTOOL_ORIG sign ' # Add in certificate file if any. if env.subst('$CERTIFICATE_PATH'): signing_cmd += ' /f "$CERTIFICATE_PATH"' # Add certificate password if any. if env.subst('$CERTIFICATE_PASSWORD'): signing_cmd += ' /p "$CERTIFICATE_PASSWORD"' # Add certificate store if any. if env.subst('$CERTIFICATE_NAME'): # The command used to do signing (target added on below). signing_cmd += ' /s "$CERTIFICATE_STORE" /n "$CERTIFICATE_NAME"' # Add timestamp server if any. if env.subst('$TIMESTAMP_SERVER'): signing_cmd += ' /t "$TIMESTAMP_SERVER"' # Add in target name signing_cmd += ' "%s"' % filename return signing_cmd else: return 'echo no signing needed'
def _IsInstrumentableFileType(file): if (file.endswith('.exe') or file.endswith('.dll')): return True return False
def _IsSignableFileType(file): if (file.endswith('.exe') or file.endswith('.dll') or file.endswith('.msi') or file.endswith('.msp')): return True return False
def _PostCoverageSigningInstall(dest, source, env): if _IsInstrumentableFileType(dest) or not _IsSignableFileType(dest): # Install the file to staging. Includes instrumentation if appropriate. env'PRECOVERAGE_SIGN_INSTALL' else: # For signable but not instrumentable files, copy the files rather than # using PRECOVERAGE_SIGN_INSTALL as this works around unnecessary rebuilds # caused by http://code.google.com/p/swtoolkit/issues/detail?id=13. env.Execute('copy "%s" "%s"' % (source, dest))
if (_IsSignableFileType(dest) and (-1 == dest.find('_unsigned')) and (-1 == dest.find('_unittest')) and os.path.split(os.path.split(dest)[0])[1] == 'staging'): env.Execute(SigningCommand(env, dest))
windows_coverage_env['PRECOVERAGE_SIGN_INSTALL'] = ( windows_coverage_env['INSTALL']) windows_coverage_env['INSTALL'] = _PostCoverageSigningInstall
windows_debug_env.Append(BUILD_GROUPS = ['default'])
BuildEnvironments( [ windows_debug_env, windows_optimized_env, windows_coverage_env, ] )
if win_env.Bit('msvs'): source_project = win_env.ComponentVSDirProject('all_source', ['$MAIN_DIR'])
# 'all_*' values do not appear to be populated until after BuildEnvironments # is called. Thus, the solution will be specific to either debug or optimized. # ComponentVSSourceProject() might be more desirable, but it does not appear # to work. windows_debug_env.ComponentVSSolution('omaha_dbg', ['all_programs', 'all_libraries'], projects=[source_project])