blob: 84aa62b47f797c258c0b5efffdc50de4c7b2c09c [file] [log] [blame]
#!/usr/bin/env python
#
# Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
#
import optparse
import os
import shutil
import subprocess
import sys
import utils
HOST_OS = utils.GuessOS()
HOST_CPUS = utils.GuessCpus()
armcompilerlocation = '/opt/codesourcery/arm-2009q1'
SCRIPT_DIR = os.path.dirname(sys.argv[0])
DART_ROOT = os.path.realpath(os.path.join(SCRIPT_DIR, '..'))
THIRD_PARTY_ROOT = os.path.join(DART_ROOT, 'third_party')
def BuildOptions():
result = optparse.OptionParser()
result.add_option("-m", "--mode",
help='Build variants (comma-separated).',
metavar='[all,debug,release]',
default='debug')
result.add_option("-v", "--verbose",
help='Verbose output.',
default=False, action="store_true")
result.add_option("-a", "--arch",
help='Target architectures (comma-separated).',
metavar='[all,ia32,x64,simarm,arm,simmips,mips]',
default=utils.GuessArchitecture())
result.add_option("--os",
help='Target OSs (comma-separated).',
metavar='[all,host,android]',
default='host')
result.add_option("-j",
help='The number of parallel jobs to run.',
metavar=HOST_CPUS,
default=str(HOST_CPUS))
result.add_option("--devenv",
help='Path containing devenv.com on Windows',
default='C:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\Common7'
'\\IDE')
result.add_option("--executable",
help='Name of the devenv.com/msbuild executable on Windows (varies for '
'different versions of Visual Studio)', default='devenv.com')
return result
def ProcessOsOption(os):
if os == 'host':
return HOST_OS
return os
def ProcessOptions(options, args):
if options.arch == 'all':
options.arch = 'ia32,x64'
if options.mode == 'all':
options.mode = 'release,debug'
if options.os == 'all':
options.os = 'host,android'
options.mode = options.mode.split(',')
options.arch = options.arch.split(',')
options.os = options.os.split(',')
for mode in options.mode:
if not mode in ['debug', 'release']:
print "Unknown mode %s" % mode
return False
for arch in options.arch:
if not arch in ['ia32', 'x64', 'simarm', 'arm', 'simmips', 'mips']:
print "Unknown arch %s" % arch
return False
options.os = [ProcessOsOption(os) for os in options.os]
for os in options.os:
if not os in ['android', 'freebsd', 'linux', 'macos', 'win32']:
print "Unknown os %s" % os
return False
if os != HOST_OS:
if os != 'android':
print "Unsupported target os %s" % os
return False
if not HOST_OS in ['linux']:
print ("Cross-compilation to %s is not supported on host os %s."
% (os, HOST_OS))
return False
if not arch in ['ia32']:
print ("Cross-compilation to %s is not supported for architecture %s."
% (os, arch))
return False
# We have not yet tweaked the v8 dart build to work with the Android
# NDK/SDK, so don't try to build it.
if args == []:
print "For android builds you must specify a target, such as 'dart'."
return False
if 'v8' in args:
print "The v8 target is not supported for android builds."
return False
return True
def SetTools(arch, toolchainprefix):
toolsOverride = None
if arch == 'arm' and toolchainprefix == None:
toolchainprefix = armcompilerlocation + "/bin/arm-none-linux-gnueabi"
if toolchainprefix:
toolsOverride = {
"CC" : toolchainprefix + "-gcc",
"CXX" : toolchainprefix + "-g++",
"AR" : toolchainprefix + "-ar",
"LINK": toolchainprefix + "-g++",
"NM" : toolchainprefix + "-nm",
}
return toolsOverride
def CheckDirExists(path, docstring):
if not os.path.isdir(path):
raise Exception('Could not find %s directory %s'
% (docstring, path))
def SetCrossCompilationEnvironment(host_os, target_os, target_arch, old_path):
global THIRD_PARTY_ROOT
if host_os not in ['linux']:
raise Exception('Unsupported host os %s' % host_os)
if target_os not in ['android']:
raise Exception('Unsupported target os %s' % target_os)
if target_arch not in ['ia32']:
raise Exception('Unsupported target architecture %s' % target_arch)
CheckDirExists(THIRD_PARTY_ROOT, 'third party tools');
android_tools = os.path.join(THIRD_PARTY_ROOT, 'android_tools')
CheckDirExists(android_tools, 'Android tools')
android_ndk_root = os.path.join(android_tools, 'ndk')
CheckDirExists(android_ndk_root, 'Android NDK')
android_sdk_root = os.path.join(android_tools, 'sdk')
CheckDirExists(android_sdk_root, 'Android SDK')
os.environ['ANDROID_NDK_ROOT'] = android_ndk_root
os.environ['ANDROID_SDK_ROOT'] = android_sdk_root
toolchain_arch = 'x86-4.4.3'
toolchain_dir = 'linux-x86'
android_toolchain = os.path.join(android_ndk_root,
'toolchains', toolchain_arch,
'prebuilt', toolchain_dir, 'bin')
CheckDirExists(android_toolchain, 'Android toolchain')
os.environ['ANDROID_TOOLCHAIN'] = android_toolchain
android_sdk_version = 9
android_sdk_tools = os.path.join(android_sdk_root, 'tools')
CheckDirExists(android_sdk_tools, 'Android SDK tools')
android_sdk_platform_tools = os.path.join(android_sdk_root, 'platform-tools')
CheckDirExists(android_sdk_platform_tools, 'Android SDK platform tools')
pathList = [old_path,
android_ndk_root,
android_sdk_tools,
android_sdk_platform_tools,
# for Ninja - maybe don't need?
android_toolchain
]
os.environ['PATH'] = ':'.join(pathList)
gypDefinesList = [
'target_arch=ia32',
'OS=%s' % target_os,
'android_build_type=0',
'host_os=%s' % host_os,
'linux_fpic=1',
'release_optimize=s',
'linux_use_tcmalloc=0',
'android_sdk=%s', os.path.join(android_sdk_root, 'platforms',
'android-%d' % android_sdk_version),
'android_sdk_tools=%s' % android_sdk_platform_tools
]
os.environ['GYP_DEFINES'] = ' '.join(gypDefinesList)
def Execute(args):
process = subprocess.Popen(args)
process.wait()
if process.returncode != 0:
raise Exception(args[0] + " failed")
def GClientRunHooks():
Execute(['gclient', 'runhooks'])
def RunhooksIfNeeded(host_os, mode, arch, target_os):
if host_os != 'linux':
return
build_root = utils.GetBuildRoot(host_os)
build_cookie_path = os.path.join(build_root, 'lastHooksTargetOS.txt')
old_target_os = None
try:
with open(build_cookie_path) as f:
old_target_os = f.read(1024)
except IOError as e:
pass
if target_os != old_target_os:
try:
os.mkdir(build_root)
except OSError as e:
pass
with open(build_cookie_path, 'w') as f:
f.write(target_os)
GClientRunHooks()
def CurrentDirectoryBaseName():
"""Returns the name of the current directory"""
return os.path.relpath(os.curdir, start=os.pardir)
def Main():
utils.ConfigureJava()
# Parse the options.
parser = BuildOptions()
(options, args) = parser.parse_args()
if not ProcessOptions(options, args):
parser.print_help()
return 1
# Determine which targets to build. By default we build the "all" target.
if len(args) == 0:
if HOST_OS == 'macos':
target = 'All'
else:
target = 'all'
else:
target = args[0]
# Remember path
old_path = os.environ['PATH']
# Build the targets for each requested configuration.
for target_os in options.os:
for mode in options.mode:
for arch in options.arch:
build_config = utils.GetBuildConf(mode, arch)
if HOST_OS == 'macos':
project_file = 'dart.xcodeproj'
if os.path.exists('dart-%s.gyp' % CurrentDirectoryBaseName()):
project_file = 'dart-%s.xcodeproj' % CurrentDirectoryBaseName()
args = ['xcodebuild',
'-project',
project_file,
'-target',
target,
'-configuration',
build_config,
'SYMROOT=%s' % os.path.abspath('xcodebuild')
]
elif HOST_OS == 'win32':
project_file = 'dart.sln'
if os.path.exists('dart-%s.gyp' % CurrentDirectoryBaseName()):
project_file = 'dart-%s.sln' % CurrentDirectoryBaseName()
if target == 'all':
args = [options.devenv + os.sep + options.executable,
'/build',
build_config,
project_file
]
else:
args = [options.devenv + os.sep + options.executable,
'/build',
build_config,
'/project',
target,
project_file
]
else:
make = 'make'
if HOST_OS == 'freebsd':
make = 'gmake'
# work around lack of flock
os.environ['LINK'] = '$(CXX)'
args = [make,
'-j',
options.j,
'BUILDTYPE=' + build_config,
]
if target_os != HOST_OS:
args += ['builddir_name=' + utils.GetBuildDir(HOST_OS, target_os)]
if options.verbose:
args += ['V=1']
args += [target]
if target_os != HOST_OS:
SetCrossCompilationEnvironment(
HOST_OS, target_os, arch, old_path)
RunhooksIfNeeded(HOST_OS, mode, arch, target_os)
toolchainprefix = None
if target_os == 'android':
toolchainprefix = ('%s/i686-linux-android'
% os.environ['ANDROID_TOOLCHAIN'])
toolsOverride = SetTools(arch, toolchainprefix)
if toolsOverride:
printToolOverrides = target_os != 'android'
for k, v in toolsOverride.iteritems():
args.append( k + "=" + v)
if printToolOverrides:
print k + " = " + v
print ' '.join(args)
process = subprocess.Popen(args)
process.wait()
if process.returncode != 0:
print "BUILD FAILED"
return 1
return 0
if __name__ == '__main__':
sys.exit(Main())