blob: 3c3903d85a75c617c9ca9365e6a85cab1c39da99 [file] [log] [blame]
# Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os
import shutil
import sys
p = ARGUMENTS.get('PROGRESS')
if p == 'spinner':
Progress(['/\r', '|\r', '\\\r', '-\r'], interval=5, file=open('con', 'w'))
elif p == 'name':
Progress('$TARGET\r', overwrite=True, file=open('con', 'w'))
default_warnings = ['no-missing-sconscript', 'no-no-parallel-support']
default_warnings = ['no-no-parallel-support']
SetOption('warn', default_warnings + GetOption('warn'))
load = ARGUMENTS.get('LOAD')
if load:
load = load.split(',')
else:
load = []
root_env = Environment(
tools = ['component_setup'],
CHROME_SRC_DIR = '$MAIN_DIR/..',
DESTINATION_ROOT = '$MAIN_DIR/Hammer',
TARGET_ROOT = '$DESTINATION_ROOT',
LIBS_DIR = '$COMPONENT_LIBRARY_DIR',
# Disable running of tests thru scons for now.
COMPONENT_TEST_CMDLINE = '',
BASE_DIR = '$OBJ_ROOT/base',
BREAKPAD_DIR = '$OBJ_ROOT/breakpad',
CHROME_DIR = '$OBJ_ROOT/chrome',
GEARS_DIR = '$OBJ_ROOT/gears',
GOOGLE_UPDATE_DIR = '$OBJ_ROOT/google_update',
GOOGLEURL_DIR = '$OBJ_ROOT/googleurl',
NET_DIR = '$OBJ_ROOT/net',
RLZ_DIR = '$OBJ_ROOT/rlz',
SANDBOX_DIR = '$OBJ_ROOT/sandbox',
SDCH_DIR = '$OBJ_ROOT/sdch',
SKIA_DIR = '$OBJ_ROOT/skia',
TESTING_DIR = '$OBJ_ROOT/testing',
THIRD_PARTY_DIR = '$OBJ_ROOT/third_party',
V8_DIR = '$OBJ_ROOT/v8',
WEBKIT_DIR = '$OBJ_ROOT/webkit',
GTEST_DIR = '$TESTING_DIR/gtest',
BSDIFF_DIR = '$THIRD_PARTY_DIR/bsdiff',
BSPATCH_DIR = '$THIRD_PARTY_DIR/bspatch',
BZIP2_DIR = '$THIRD_PARTY_DIR/bzip2',
ICU38_DIR = '$THIRD_PARTY_DIR/icu38',
LIBEVENT_DIR = '$THIRD_PARTY_DIR/libevent',
LIBJPEG_DIR = '$THIRD_PARTY_DIR/libjpeg',
LIBPNG_DIR = '$THIRD_PARTY_DIR/libpng',
LIBXML_DIR = '$THIRD_PARTY_DIR/libxml',
LIBXSLT_DIR = '$THIRD_PARTY_DIR/libxslt',
LZMA_SDK_DIR = '$THIRD_PARTY_DIR/lzma_sdk',
MODP_B64_DIR = '$THIRD_PARTY_DIR/modp_b64',
NPAPI_DIR = '$THIRD_PARTY_DIR/npapi',
ZLIB_DIR = '$THIRD_PARTY_DIR/zlib',
THIRD_PARTY_WEBKIT_DIR = '$THIRD_PARTY_DIR/WebKit',
PYTHON=sys.executable,
PERL = 'perl',
PERL_INCLUDE_FLAG = '-I ',
PERL_INCLUDE_SUFFIX = '',
_PERL_INCLUDE_FLAGS = ('${_concat(PERL_INCLUDE_FLAG, '
'PERL_INCLUDE_PATH, '
'PERL_INCLUDE_SUFFIX,'
'__env__, RDirs, TARGET, SOURCE)}'),
)
root_env.Append(LIBPATH = ['$V8_DIR'])
def ChromeProgram(env, *args, **kw):
return env.ComponentProgram(*args, **kw)
root_env.AddMethod(ChromeProgram)
def ChromeTestProgram(env, *args, **kw):
return env.ComponentTestProgram(*args, **kw)
root_env.AddMethod(ChromeTestProgram)
def ChromeStaticLibrary(env, *args, **kw):
kw['COMPONENT_STATIC'] = True
return env.ComponentLibrary(*args, **kw)
root_env.AddMethod(ChromeStaticLibrary)
def ChromeSharedLibrary(env, *args, **kw):
kw['COMPONENT_STATIC'] = False
return [env.ComponentLibrary(*args, **kw)[0]]
root_env.AddMethod(ChromeSharedLibrary, "ChromeSharedLibrary")
def ChromeObject(env, *args, **kw):
return env.ComponentObject(*args, **kw)
root_env.AddMethod(ChromeObject)
# TODO(bradnelson): pull this functionality into hammer.
# Auto select the number of processors
if root_env['PLATFORM'] in ['win32', 'cygwin']:
cpus = int(os.environ.get('NUMBER_OF_PROCESSORS', 1))
elif root_env['PLATFORM'] in ['linux', 'linux2', 'posix']:
# TODO(evanm): this is Linux-specific, not posix.
# Parse /proc/cpuinfo for processor count.
cpus = len([l for l in open('/proc/cpuinfo') if l.startswith('processor\t')])
SetOption('num_jobs', cpus + 1)
if ARGUMENTS.get('VERBOSE') in (None, '0'):
root_env['CCCOMSTR'] = 'Compiling $TARGET ...'
root_env['CXXCOMSTR'] = 'Compiling $TARGET ...'
root_env['SHCCCOMSTR'] = 'Compiling $TARGET ...'
root_env['SHCXXCOMSTR'] = 'Compiling $TARGET ...'
root_env['ARCOMSTR'] = 'Archiving $TARGET ...'
root_env['LINKCOMSTR'] = 'Linking $TARGET ...'
root_env['BINDINGSCOMSTR'] = 'Building bindings in $TARGET ...'
# Use timestamps change, followed by MD5 for speed
root_env.Decider('MD5-timestamp')
# The list of all leaf (fully described) environments.
environment_list = []
# --------------------------------------------------------------------------
# Decide which things to load.
# Don't put anything platform depended here, this is just to gate things
# in or out for speed.
included = [c for c in load if not c.startswith('-')]
excluded = [c[1:] for c in load if c.startswith('-')]
if not included:
included = ['all']
components = ['all']
def LoadComponent(c):
components.append(c)
return (not GetOption('help') and
c in included or
('all' in included and not c in excluded))
sconscripts = []
if LoadComponent('base'):
sconscripts.append('$BASE_DIR/base.scons')
if LoadComponent('breakpad'):
sconscripts.append('$BREAKPAD_DIR/SConscript')
if LoadComponent('chrome'):
sconscripts.append('$CHROME_DIR/SConscript')
if LoadComponent('gears'):
sconscripts.append('$GEARS_DIR/SConscript')
if LoadComponent('google_update'):
sconscripts.append('$GOOGLE_UPDATE_DIR/SConscript')
if LoadComponent('googleurl'):
# googleurl comes from a different repository so we provide the SConscript
# file.
sconscripts.append('$GOOGLEURL_DIR/googleurl.scons')
if LoadComponent('net'):
sconscripts.append('$NET_DIR/net.scons')
if LoadComponent('rlz'):
sconscripts.append('$RLZ_DIR/SConscript')
if LoadComponent('sandbox'):
sconscripts.append('$SANDBOX_DIR/sandbox.scons')
if LoadComponent('sdch'):
sconscripts.append('$SDCH_DIR/SConscript')
if LoadComponent('skia'):
sconscripts.append('$SKIA_DIR/SConscript')
if LoadComponent('testing'):
sconscripts.append('$TESTING_DIR/SConscript.gtest')
if LoadComponent('third_party'):
sconscripts.extend([
'$BSDIFF_DIR/SConscript',
'$BZIP2_DIR/bzip2.scons',
'$ICU38_DIR/icu38.scons',
'$LIBPNG_DIR/libpng.scons',
'$LZMA_SDK_DIR/SConscript',
'$MODP_B64_DIR/modp_b64.scons',
'$ZLIB_DIR/zlib.scons',
'$LIBJPEG_DIR/SConscript',
'$LIBXML_DIR/SConscript',
'$LIBXSLT_DIR/SConscript',
'$BSPATCH_DIR/SConscript',
])
if LoadComponent('v8') and root_env.Dir('$CHROME_SRC_DIR/v8').exists():
sconscripts.append('build/SConscript.v8')
if LoadComponent('webkit'):
sconscripts.append('$WEBKIT_DIR/SConscript')
# Add the final list into the root environment to be build in BuildComponents.
root_env.Append(BUILD_SCONSCRIPTS = sconscripts)
# --------------------------------------------------------------------------
# Windows specific
windows_env = root_env.Clone()
environment_list.append(windows_env)
windows_env.Tool('target_platform_windows')
windows_env.Tool('target_debug')
windows_env.Tool('midl')
windows_env.Replace(
BUILD_TYPE = 'debug-windows',
BUILD_TYPE_DESCRIPTION = 'Windows debug build',
BUILD_GROUPS = ['default'],
)
# TODO(bradnelson): this is needed for now because target_platform_windows
# has OS_WINDOWS defined in a weird way.
windows_env.FilterOut(CPPDEFINES = ['OS_WINDOWS=OS_WINDOWS'])
windows_env['PDB'] = '${TARGET.base}.pdb'
# TODO(bradnelson): this should not need to be gated on host platform.
if root_env['PLATFORM'] in ['win32', 'cygwin']:
msvs_env = Environment(tools=['msvc', 'mslink', 'msvs'])['ENV']
msvs_drive = msvs_env['PATH'][0]
else:
msvs_env = {'PATH': '', 'INCLUDE': '', 'LIB': ''}
msvs_drive = 'C'
# Use the absolute path for MSVC because it might not be on the same drive
# as our source checkout.
visual_studio_path = msvs_drive + ':/Program Files/Microsoft Visual Studio 8'
windows_env.Replace(
CSCRIPT = 'c:\\Windows\\System32\\cscript',
PLATFORMSDK_VISTA_REL = '../third_party/platformsdk_vista_6_0',
PLATFORMSDK_VISTA = '$CHROME_SRC_DIR/third_party/platformsdk_vista_6_0',
VISUAL_STUDIO = visual_studio_path,
CYGWIN_DIR = windows_env.Dir('$CHROME_SRC_DIR/third_party/cygwin'),
CYGWIN_BIN_DIR = '$CYGWIN_DIR/bin',
PERL = '$CYGWIN_BIN_DIR/perl.exe',
MSVS_ENV = msvs_env,
YACC = '$CYGWIN_BIN_DIR/bison.exe',
)
windows_env.Append(
ARFLAGS = [
'/nologo',
],
CCFLAGS = [
'/nologo',
'/Od', # no optimization
'/RTC1',
'/MTd', # static link to crt, and debug version
'/Gy',
'/GR-',
'/W3',
'/Z7',
'/errorReport:prompt',
'/wd4503',
'/wd4819',
],
CPPDEFINES = [
'_CRT_SECURE_NO_DEPRECATE',
'_CRT_NONSTDC_NO_WARNINGS',
'_CRT_NONSTDC_NO_DEPRECATE',
'_SCL_SECURE_NO_DEPRECATE',
'_DEBUG',
'_CRT_RAND_S',
('_WIN32_WINNT', '0x0600'),
('WINVER', '0x0600'),
'WIN32',
'_WINDOWS',
('_HAS_EXCEPTIONS', 0),
'NOMINMAX',
'_UNICODE',
'UNICODE',
'CERT_CHAIN_PARA_HAS_EXTRA_FIELDS',
'WIN32_LEAN_AND_MEAN',
],
CPPPATH = [
'$PLATFORMSDK_VISTA/files/Include',
'$PLATFORMSDK_VISTA/files/VC/INCLUDE',
'$VISUAL_STUDIO/VC/atlmfc/include',
],
LIBS = [
'advapi32.lib',
'comdlg32.lib',
'gdi32.lib',
'kernel32.lib',
'msimg32.lib',
'odbc32.lib',
'odbccp32.lib',
'ole32.lib',
'oleaut32.lib',
'psapi.lib',
'shell32.lib',
'user32.lib',
'usp10.lib',
'uuid.lib',
'version.lib',
'wininet.lib',
'winspool.lib',
'ws2_32.lib',
'DelayImp.lib',
],
LINKFLAGS = [
'/nologo',
'/DEBUG',
],
ICU_LIBS = ['icu'],
)
windows_env.Append(
LIBPATH = [
'$PLATFORMSDK_VISTA/files/Lib',
'$PLATFORMSDK_VISTA/files/VC/LIB',
'$VISUAL_STUDIO/VC/atlmfc/lib',
],
)
# TODO(sgk): remove once we upgrade to SCons 0.98.4
for var in ['INCLUDE', 'LIB', 'PATH']:
msvs_env[var] = msvs_env[var].split('|', 1)[0]
windows_env['ENV'][var] = windows_env['ENV'][var].split('|', 1)[0]
# Force scons to handle long include lines correctly.
pchcom_fixed = windows_env['PCHCOM']
pchcom_fixed = pchcom_fixed.replace('${TARGETS[0]}', '$TARGET')
pchcom_fixed = pchcom_fixed.replace('${TARGETS[1]}', '$TARGETS1')
windows_env.Replace(
CCCOM = "${TEMPFILE('%s')}" % windows_env['CCCOM'],
CXXCOM = "${TEMPFILE('%s')}" % windows_env['CXXCOM'],
SHCCCOM = "${TEMPFILE('%s')}" % windows_env['SHCCCOM'],
SHCXXCOM = "${TEMPFILE('%s')}" % windows_env['SHCXXCOM'],
PCHCOM = "${TEMPFILE('%s')}" % pchcom_fixed,
TARGETS1 = '${TARGETS[1]}',
)
windows_env['ENV']['PROGRAMFILES'] = os.environ.get('PROGRAMFILES', '')
windows_env['ENV']['SystemDrive'] = os.environ.get('SystemDrive', '')
windows_env['ENV']['USERPROFILE'] = os.environ.get('USERPROFILE', '')
windows_env.AppendENVPath('PATH', ';C:\\WINDOWS\\system32')
# --------------------------------------------------------------------------
# Linux specific
linux_env = root_env.Clone()
environment_list.append(linux_env)
linux_env.Tool('target_platform_linux')
linux_env.Tool('target_debug')
linux_env.Tool('yacc')
linux_env.Replace(
BUILD_TYPE = 'debug-linux',
BUILD_TYPE_DESCRIPTION = 'Linux debug build',
BUILD_GROUPS = ['default'],
)
# TODO(bradnelson): this is needed for now because target_platform_linux has
# OS_LINUX defined in a weird way.
linux_env.FilterOut(CPPDEFINES = ['OS_LINUX=OS_LINUX'])
# Copy some environment variables from the outer environment to the
# SCons.Environment if they exist.
for envvar in ('CC', 'CXX'):
if envvar in os.environ:
linux_env[envvar] = os.environ[envvar]
# Copy these environment variables from the outer environment to the
# environment that the build commands run in.
# $HOME is needed by distcc so it can find its lock file.
for envvar in ('HOME', 'DISTCC_HOSTS', 'CCACHE_DIR'):
if envvar in os.environ:
linux_env['ENV'][envvar] = os.environ[envvar]
excluded_warnings = [
# TODO: Clean up uses of ext/hash_map and remove this.
# (see unordered_map and base/hash_tables.h)
'-Wno-deprecated', # Needed for using ext/hash_map on GCC 4.3
'-Wno-unknown-pragmas', # In wtf's ref counting system
]
linux_env.Append(
BUILD_SCONSCRIPTS = [
'$LIBEVENT_DIR/libevent.scons',
],
CCFLAGS = ['-m32', '-g', '-pthread'],
CXXFLAGS = ['-Wall', '-Werror'] + excluded_warnings,
LINKFLAGS = ['-m32', '-pthread'],
)
linux_env.Replace(
# We have several cases where archives depend on each other in a cyclic
# fashion. (V8Bindings, libport and WebCore being the most significant
# example.) Since the GNU linker does only a single pass over the archives
# we need some extra trickery to deal with these unavoidable cycles. That
# trickery is --start-group and --end-group (aka -( and -) ). That causes ld
# to loop over the group until no more undefined symbols are found. In an
# ideal world we would only make groups from those libraries which we knew
# to be in cycles. However, that's tough with SCons, so we bodge it by
# making all the archives a group by redefining the linking command here.
SHLINKCOM = ('$SHLINK -shared -o $TARGET $SHLINKFLAGS $SOURCES '
'$_LIBDIRFLAGS '
'-Wl,--start-group $_LIBFLAGS -Wl,--end-group'),
LINKCOM = ('$LINK -o $TARGET $LINKFLAGS $SOURCES '
'$_LIBDIRFLAGS '
'-Wl,--start-group $_LIBFLAGS -Wl,--end-group'),
)
linux_env.Replace(
PERL = '/usr/bin/perl',
PERL_INCLUDE_FLAG = '-I ',
PERL_INCLUDE_SUFFIX = '',
_PERL_INCLUDE_FLAGS = ('${_concat(PERL_INCLUDE_FLAG, '
'PERL_INCLUDE_PATH, '
'PERL_INCLUDE_SUFFIX,'
'__env__, RDirs, TARGET, SOURCE)}'),
)
linux_env.FilterOut(
BUILD_SCONSCRIPTS = [
'$BSPATCH_DIR/SConscript',
'$BSDIFF_DIR/SConscript',
'$GEARS_DIR/SConscript',
'$GOOGLE_UPDATE_DIR/SConscript',
'$RLZ_DIR/SConscript',
'$SANDBOX_DIR/sandbox.scons',
],
)
linux_env.Append(
# We need rt for clock_gettime.
LIBS = ['rt'],
ICU_LIBS = ['icu'],
)
# Build with support for gcov when COVERAGE=1.
if ARGUMENTS.get('COVERAGE') == '1':
linux_env.Append(CCFLAGS=['-fprofile-arcs', '-ftest-coverage'])
linux_env.Append(LINKFLAGS=['-fprofile-arcs'])
# Build with system-provided NSS and GTK.
if root_env['PLATFORM'] in ['linux', 'linux2', 'posix']:
linux_env.ParseConfig('pkg-config --cflags --libs nss')
linux_env.ParseConfig('pkg-config --cflags --libs gtk+-2.0')
linux_env.ParseConfig('pkg-config --cflags --libs pangoft2')
# --------------------------------------------------------------------------
# Mac specific
mac_env = root_env.Clone()
environment_list.append(mac_env)
mac_env.Tool('target_platform_mac')
mac_env.Tool('target_debug')
mac_env.Replace(
BUILD_TYPE = 'debug-mac',
BUILD_TYPE_DESCRIPTION = 'Mac debug build',
BUILD_GROUPS = ['default'],
)
mac_env.Replace(
# Reproduce XCode's behavior of using gcc even to link C++,
# and distinguishing it the -x c++ option.
CC = 'gcc-4.2',
CXX = 'g++-4.2',
LINK = '$CXX',
)
mac_env.FilterOut(
BUILD_SCONSCRIPTS = [
'$BSPATCH_DIR/SConscript',
'$BSDIFF_DIR/SConscript',
'$LIBJPEG_DIR/SConscript',
'$LIBXML_DIR/SConscript',
'$LIBXSLT_DIR/SConscript',
'$BREAKPAD_DIR/SConscript',
'$CHROME_DIR/SConscript',
'$GEARS_DIR/SConscript',
'$GOOGLE_UPDATE_DIR/SConscript',
'$RLZ_DIR/SConscript',
'$SANDBOX_DIR/sandbox.scons',
'build/SConscript.v8',
'$WEBKIT_DIR/SConscript',
],
)
mac_env.Append(
BUILD_SCONSCRIPTS = [
'$LIBEVENT_DIR/libevent.scons',
],
CFLAGS = [
'-std=c99',
],
CXXFLAGS = [
'-fvisibility-inlines-hidden',
'${str(SOURCE).endswith(".mm") and "-fobjc-gc" or ""}',
],
CCFLAGS = [
'-fmessage-length=0',
'-pipe',
'-O0',
'-mdynamic-no-pic',
'-Werror',
'-Wnewline-eof',
'-fvisibility=hidden',
'-gdwarf-2',
'-Wall',
'-Wendif-labels',
'-fstack-protector',
'-fstack-protector-all',
],
CPPDEFINES = [
'DEBUG',
],
FRAMEWORKPATH = [
mac_env.Dir('${TARGET_ROOT}'),
'/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks',
],
FRAMEWORKS = [
'AppKit',
'ApplicationServices',
'Foundation',
],
ICU_LIBS = ['icui18n', 'icuuc', 'icudata'],
)
# Add --clobber (for the buildbot).
# NOTE: seems to be crucial to do this before any builders are invoked.
AddOption('--clobber', action='store_true', dest='clobber', default=False,
help='Delete build directory before building.')
if GetOption('clobber'):
shutil.rmtree(root_env.Dir('$DESTINATION_ROOT').abspath, True)
# sconsign file gets put here at the moment.
shutil.rmtree(root_env.Dir('$MAIN_DIR/scons-out').abspath, True)
# -------------------------------------------------------------------------
# Overlay things from a layer below.
for env in environment_list:
env.Dir('$OBJ_ROOT').addRepository(env.Dir('$CHROME_SRC_DIR'))
env.Dir('$OBJ_ROOT/googleurl').addRepository(env.Dir('$CHROME_SRC_DIR/build'))
# We pre-resolve some common targets. We end up spending lots of time
# resolving these over and over again.
env.Replace(
CHROME_SRC_DIR = str(env.Dir('$CHROME_SRC_DIR')),
DESTINATION_ROOT = str(env.Dir('$DESTINATION_ROOT')),
TARGET_ROOT = str(env.Dir('$TARGET_ROOT')),
OBJ_ROOT = str(env.Dir('$OBJ_ROOT')),
WEBKIT_DIR = str(env.Dir('$WEBKIT_DIR')),
)
help_fmt = """
Usage: hammer [SCONS_OPTIONS] [VARIABLES] [TARGET] ...
Supported build variables:
LOAD=[module,...] Comma-separated list of components to load in the
dependency graph ('-' prefix excludes):
%s
PROGRESS=type Display a progress indicator:
name: print each evaluated target name
spinner: print a spinner every 5 targets
VERBOSE=1 Display full command lines
"""
if GetOption('help'):
import textwrap
tw = textwrap.TextWrapper(
width = 78,
initial_indent = ' '*32,
subsequent_indent = ' '*32,
)
components = tw.fill(', '.join(components))
Help(help_fmt % components)
Import('build_component')
Default(Alias(build_component))
# -------------------------------------------------------------------------
# Invoke all the SConscripts in each of the environments that make sense on
# this host-platform.
BuildComponents(environment_list)
# -------------------------------------------------------------------------