from __future__ import print_function
import argparse
import glob
import json
import os
import pipes
import re
import shutil
import subprocess
import sys
from update import (CDS_URL, CHROMIUM_DIR, CLANG_REVISION, LLVM_BUILD_DIR,
FORCE_HEAD_REVISION_FILE, PACKAGE_VERSION, RELEASE_VERSION,
STAMP_FILE, CopyFile, CopyDiaDllTo, DownloadUrl,
DownloadAndUnpack, EnsureDirExists, GetWinSDKDir,
ReadStampFile, RmTree, WriteStampFile)
THIRD_PARTY_DIR = os.path.join(CHROMIUM_DIR, 'third_party')
LLVM_DIR = os.path.join(THIRD_PARTY_DIR, 'llvm')
COMPILER_RT_DIR = os.path.join(LLVM_DIR, 'compiler-rt')
LLVM_BOOTSTRAP_DIR = os.path.join(THIRD_PARTY_DIR, 'llvm-bootstrap')
LLVM_BOOTSTRAP_INSTALL_DIR = os.path.join(THIRD_PARTY_DIR,
'llvm-bootstrap-install')
LLVM_INSTRUMENTED_DIR = os.path.join(THIRD_PARTY_DIR, 'llvm-instrumented')
LLVM_PROFDATA_FILE = os.path.join(LLVM_INSTRUMENTED_DIR, 'profdata.prof')
CHROME_TOOLS_SHIM_DIR = os.path.join(LLVM_DIR, 'llvm', 'tools', 'chrometools')
COMPILER_RT_BUILD_DIR = os.path.join(LLVM_BUILD_DIR, 'compiler-rt')
LLVM_BUILD_TOOLS_DIR = os.path.abspath(
os.path.join(LLVM_DIR, '..', 'llvm-build-tools'))
ANDROID_NDK_DIR = os.path.join(
CHROMIUM_DIR, 'third_party', 'android_ndk')
FUCHSIA_SDK_DIR = os.path.join(CHROMIUM_DIR, 'third_party', 'fuchsia-sdk',
'sdk')
BUG_REPORT_URL = ('https://crbug.com and run'
' tools/clang/scripts/process_crashreports.py'
' (only works inside Google) which will upload a report')
FIRST_LLVM_COMMIT = '97724f18c79c7cc81ced24239eb5e883bf1398ef'
def RunCommand(command, msvc_arch=None, env=None, fail_hard=True):
if msvc_arch and sys.platform == 'win32':
command = [os.path.join(GetWinSDKDir(), 'bin', 'SetEnv.cmd'),
"/" + msvc_arch, '&&'] + command
if sys.platform != 'win32':
command = ' '.join([pipes.quote(c) for c in command])
print('Running', command)
if subprocess.call(command, env=env, shell=True) == 0:
return True
print('Failed.')
if fail_hard:
sys.exit(1)
return False
def CopyDirectoryContents(src, dst):
dst = os.path.realpath(dst) EnsureDirExists(dst)
for f in os.listdir(src):
CopyFile(os.path.join(src, f), dst)
def CheckoutLLVM(commit, dir):
print('Checking out LLVM monorepo %s into %s' % (commit, dir))
if os.path.isdir(dir):
os.chdir(dir)
if (RunCommand(['git', 'diff-index', '--quiet', 'HEAD'], fail_hard=False)
and RunCommand(['git', 'fetch'], fail_hard=False)
and RunCommand(['git', 'checkout', commit], fail_hard=False)
and RunCommand(['git', 'show', FIRST_LLVM_COMMIT], fail_hard=False)):
return
os.chdir(CHROMIUM_DIR) print('Removing %s.' % dir)
RmTree(dir)
clone_cmd = ['git', 'clone', 'https://github.com/llvm/llvm-project/', dir]
if RunCommand(clone_cmd, fail_hard=False):
os.chdir(dir)
if RunCommand(['git', 'checkout', commit], fail_hard=False):
return
print('CheckoutLLVM failed.')
sys.exit(1)
def UrlOpen(url):
return subprocess.check_output(['curl', '--silent', url])
def GetLatestLLVMCommit():
ref = json.loads(UrlOpen(('https://api.github.com/repos/'
'llvm/llvm-project/git/refs/heads/master')))
assert ref['object']['type'] == 'commit'
return ref['object']['sha']
def GetCommitCount(commit):
return subprocess.check_output(['git', 'rev-list', '--count',
FIRST_LLVM_COMMIT + '..' + commit]).rstrip()
def DeleteChromeToolsShim():
OLD_SHIM_DIR = os.path.join(LLVM_DIR, 'tools', 'zzz-chrometools')
shutil.rmtree(OLD_SHIM_DIR, ignore_errors=True)
shutil.rmtree(CHROME_TOOLS_SHIM_DIR, ignore_errors=True)
def CreateChromeToolsShim():
assert not any(i in os.path.basename(CHROME_TOOLS_SHIM_DIR) for i in '-_')
os.mkdir(CHROME_TOOLS_SHIM_DIR)
with file(os.path.join(CHROME_TOOLS_SHIM_DIR, 'CMakeLists.txt'), 'w') as f:
f.write('# Automatically generated by tools/clang/scripts/update.py. ' +
'Do not edit.\n')
f.write('# Since tools/clang is located in another directory, use the \n')
f.write('# two arg version to specify where build artifacts go. CMake\n')
f.write('# disallows reuse of the same binary dir for multiple source\n')
f.write('# dirs, so the build artifacts need to go into a subdirectory.\n')
f.write('if (CHROMIUM_TOOLS_SRC)\n')
f.write(' add_subdirectory(${CHROMIUM_TOOLS_SRC} ' +
'${CMAKE_CURRENT_BINARY_DIR}/a)\n')
f.write('endif (CHROMIUM_TOOLS_SRC)\n')
def AddCMakeToPath(args):
if args.use_system_cmake:
return
if sys.platform == 'win32':
zip_name = 'cmake-3.12.1-win32-x86.zip'
dir_name = ['cmake-3.12.1-win32-x86', 'bin']
elif sys.platform == 'darwin':
zip_name = 'cmake-3.12.1-Darwin-x86_64.tar.gz'
dir_name = ['cmake-3.12.1-Darwin-x86_64', 'CMake.app', 'Contents', 'bin']
else:
zip_name = 'cmake-3.12.1-Linux-x86_64.tar.gz'
dir_name = ['cmake-3.12.1-Linux-x86_64', 'bin']
cmake_dir = os.path.join(LLVM_BUILD_TOOLS_DIR, *dir_name)
if not os.path.exists(cmake_dir):
DownloadAndUnpack(CDS_URL + '/tools/' + zip_name, LLVM_BUILD_TOOLS_DIR)
os.environ['PATH'] = cmake_dir + os.pathsep + os.environ.get('PATH', '')
def AddGnuWinToPath():
if sys.platform != 'win32':
return
gnuwin_dir = os.path.join(LLVM_BUILD_TOOLS_DIR, 'gnuwin')
GNUWIN_VERSION = '12'
GNUWIN_STAMP = os.path.join(gnuwin_dir, 'stamp')
if ReadStampFile(GNUWIN_STAMP) == GNUWIN_VERSION:
print('GNU Win tools already up to date.')
else:
zip_name = 'gnuwin-%s.zip' % GNUWIN_VERSION
DownloadAndUnpack(CDS_URL + '/tools/' + zip_name, LLVM_BUILD_TOOLS_DIR)
WriteStampFile(GNUWIN_VERSION, GNUWIN_STAMP)
os.environ['PATH'] = gnuwin_dir + os.pathsep + os.environ.get('PATH', '')
etc = os.path.join(gnuwin_dir, '..', '..', 'etc')
EnsureDirExists(etc)
with open(os.path.join(etc, 'nsswitch.conf'), 'w') as f:
f.write('passwd: files\n')
f.write('group: files\n')
def AddZlibToPath():
zlib_dir = os.path.join(LLVM_BUILD_TOOLS_DIR, 'zlib-1.2.11')
if not os.path.exists(zlib_dir):
zip_name = 'zlib-1.2.11.tar.gz'
DownloadAndUnpack(CDS_URL + '/tools/' + zip_name, LLVM_BUILD_TOOLS_DIR)
os.chdir(zlib_dir)
zlib_files = [
'adler32', 'compress', 'crc32', 'deflate', 'gzclose', 'gzlib',
'gzread', 'gzwrite', 'inflate', 'infback', 'inftrees', 'inffast',
'trees', 'uncompr', 'zutil'
]
cl_flags = [
'/nologo', '/O2', '/DZLIB_DLL', '/c', '/D_CRT_SECURE_NO_DEPRECATE',
'/D_CRT_NONSTDC_NO_DEPRECATE'
]
try:
RunCommand(['cl.exe'] + [f + '.c' for f in zlib_files] + cl_flags,
msvc_arch='x64')
RunCommand(['lib.exe'] + [f + '.obj' for f in zlib_files] +
['/nologo', '/out:zlib.lib'], msvc_arch='x64')
shutil.rmtree('test')
except Exception as e:
print('Failed to build zlib: ' + str(e))
sys.exit(1)
os.environ['PATH'] = zlib_dir + os.pathsep + os.environ.get('PATH', '')
return zlib_dir
def MaybeDownloadHostGcc(args):
if not sys.platform.startswith('linux') or args.gcc_toolchain:
return
gcc_dir = os.path.join(LLVM_BUILD_TOOLS_DIR, 'gcc530trusty')
if not os.path.exists(gcc_dir):
DownloadAndUnpack(CDS_URL + '/tools/gcc530trusty.tgz', gcc_dir)
args.gcc_toolchain = gcc_dir
def VerifyVersionOfBuiltClangMatchesVERSION():
clang = os.path.join(LLVM_BUILD_DIR, 'bin', 'clang')
if sys.platform == 'win32':
clang += '-cl.exe'
version_out = subprocess.check_output([clang, '--version'])
version_out = re.match(r'clang version ([0-9.]+)', version_out).group(1)
if version_out != RELEASE_VERSION:
print(('unexpected clang version %s (not %s), '
'update RELEASE_VERSION in update.py')
% (version_out, RELEASE_VERSION))
sys.exit(1)
def CopyLibstdcpp(args, build_dir):
if not args.gcc_toolchain:
return
libstdcpp = subprocess.check_output(
[os.path.join(args.gcc_toolchain, 'bin', 'g++'),
'-print-file-name=libstdc++.so.6']).rstrip()
for d in ['lib',
'test/tools/llvm-isel-fuzzer/lib',
'test/tools/llvm-opt-fuzzer/lib',
'unittests/CodeGen/lib',
'unittests/DebugInfo/lib',
'unittests/ExecutionEngine/lib',
'unittests/Support/lib',
'unittests/Target/lib',
'unittests/Transforms/lib',
'unittests/lib',
'unittests/tools/lib',
'unittests/tools/llvm-exegesis/lib']:
EnsureDirExists(os.path.join(build_dir, d))
CopyFile(libstdcpp, os.path.join(build_dir, d))
def gn_arg(v):
if v == 'True':
return True
if v == 'False':
return False
raise argparse.ArgumentTypeError('Expected one of %r or %r' % (
'True', 'False'))
def main():
parser = argparse.ArgumentParser(description='Build Clang.')
parser.add_argument('--bootstrap', action='store_true',
help='first build clang with CC, then with itself.')
parser.add_argument('--disable-asserts', action='store_true',
help='build with asserts disabled')
parser.add_argument('--gcc-toolchain', help='what gcc toolchain to use for '
'building; --gcc-toolchain=/opt/foo picks '
'/opt/foo/bin/gcc')
parser.add_argument('--pgo', action='store_true', help='build with PGO')
parser.add_argument('--llvm-force-head-revision', action='store_true',
help='build the latest revision')
parser.add_argument('--run-tests', action='store_true',
help='run tests after building')
parser.add_argument('--skip-build', action='store_true',
help='do not build anything')
parser.add_argument('--skip-checkout', action='store_true',
help='do not create or update any checkouts')
parser.add_argument('--extra-tools', nargs='*', default=[],
help='select additional chrome tools to build')
parser.add_argument('--use-system-cmake', action='store_true',
help='use the cmake from PATH instead of downloading '
'and using prebuilt cmake binaries')
parser.add_argument('--with-android', type=gn_arg, nargs='?', const=True,
help='build the Android ASan runtime (linux only)',
default=sys.platform.startswith('linux'))
parser.add_argument('--without-android', action='store_false',
help='don\'t build Android ASan runtime (linux only)',
dest='with_android')
parser.add_argument('--without-fuchsia', action='store_false',
help='don\'t build Fuchsia clang_rt runtime (linux/mac)',
dest='with_fuchsia',
default=sys.platform in ('linux2', 'darwin'))
args = parser.parse_args()
if args.pgo and not args.bootstrap:
print('--pgo requires --bootstrap')
return 1
if args.with_android and not os.path.exists(ANDROID_NDK_DIR):
print('Android NDK not found at ' + ANDROID_NDK_DIR)
print('The Android NDK is needed to build a Clang whose -fsanitize=address')
print('works on Android. See ')
print('https://www.chromium.org/developers/how-tos/android-build-instructions')
print('for how to install the NDK, or pass --without-android.')
return 1
if args.llvm_force_head_revision:
args.with_fuchsia = False
if args.with_fuchsia and not os.path.exists(FUCHSIA_SDK_DIR):
print('Fuchsia SDK not found at ' + FUCHSIA_SDK_DIR)
print('The Fuchsia SDK is needed to build libclang_rt for Fuchsia.')
print('Install the Fuchsia SDK by adding fuchsia to the ')
print('target_os section in your .gclient and running hooks, ')
print('or pass --without-fuchsia.')
print('https://chromium.googlesource.com/chromium/src/+/master/docs/fuchsia_build_instructions.md')
print('for general Fuchsia build instructions.')
return 1
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
AddGnuWinToPath()
MaybeDownloadHostGcc(args)
global CLANG_REVISION, PACKAGE_VERSION
if args.llvm_force_head_revision:
CLANG_REVISION = GetLatestLLVMCommit()
if not args.skip_checkout:
CheckoutLLVM(CLANG_REVISION, LLVM_DIR);
if args.llvm_force_head_revision:
PACKAGE_VERSION = 'n%s-%s-0' % (GetCommitCount(CLANG_REVISION),
CLANG_REVISION[:8])
print('Locally building clang %s...' % PACKAGE_VERSION)
WriteStampFile('', STAMP_FILE)
WriteStampFile('', FORCE_HEAD_REVISION_FILE)
AddCMakeToPath(args)
DeleteChromeToolsShim()
if args.skip_build:
return 0
cc, cxx, lld = None, None, None
if args.gcc_toolchain:
cc = os.path.join(args.gcc_toolchain, 'bin', 'gcc')
cxx = os.path.join(args.gcc_toolchain, 'bin', 'g++')
if not os.access(cc, os.X_OK):
print('Invalid --gcc-toolchain: ' + args.gcc_toolchain)
return 1
cflags = []
cxxflags = []
ldflags = []
targets = 'AArch64;ARM;Mips;PowerPC;SystemZ;WebAssembly;X86'
projects = 'clang;compiler-rt;lld;chrometools;clang-tools-extra'
if sys.platform == 'darwin':
projects += ';libcxx'
base_cmake_args = [
'-GNinja',
'-DCMAKE_BUILD_TYPE=Release',
'-DLLVM_ENABLE_ASSERTIONS=%s' % ('OFF' if args.disable_asserts else 'ON'),
'-DLLVM_ENABLE_PROJECTS=' + projects,
'-DLLVM_TARGETS_TO_BUILD=' + targets,
'-DLLVM_ENABLE_PIC=OFF',
'-DLLVM_ENABLE_UNWIND_TABLES=OFF',
'-DLLVM_ENABLE_TERMINFO=OFF',
'-DCLANG_PLUGIN_SUPPORT=OFF',
'-DCLANG_ENABLE_STATIC_ANALYZER=OFF',
'-DCLANG_ENABLE_ARCMT=OFF',
'-DBUG_REPORT_URL=' + BUG_REPORT_URL,
'-DCOMPILER_RT_USE_LIBCXX=NO',
'-DLLVM_INCLUDE_GO_TESTS=OFF',
]
if args.gcc_toolchain:
base_cmake_args.append(
'-DCOMPILER_RT_TEST_COMPILER_CFLAGS=--gcc-toolchain=')
if sys.platform == 'win32':
base_cmake_args.append('-DLLVM_USE_CRT_RELEASE=MT')
zlib_dir = AddZlibToPath()
base_cmake_args.append('-DLLVM_ENABLE_ZLIB=FORCE_ON')
cflags.append('-I' + zlib_dir)
cxxflags.append('-I' + zlib_dir)
if sys.platform == 'darwin':
base_cmake_args.append('-DLIBCXX_CXX_ABI=libcxxabi')
base_cmake_args.append('-DLIBCXX_CXX_ABI_SYSTEM=1')
if sys.platform != 'win32':
base_cmake_args.append('-DLLVM_ENABLE_LIBXML2=FORCE_ON')
if args.bootstrap:
print('Building bootstrap compiler')
if os.path.exists(LLVM_BOOTSTRAP_DIR):
RmTree(LLVM_BOOTSTRAP_DIR)
EnsureDirExists(LLVM_BOOTSTRAP_DIR)
os.chdir(LLVM_BOOTSTRAP_DIR)
projects = 'clang'
if args.pgo:
projects += ';compiler-rt'
if sys.platform != 'darwin':
projects += ';lld'
if sys.platform == 'darwin':
projects += ';libcxx;compiler-rt'
bootstrap_targets = 'X86'
if sys.platform == 'darwin':
bootstrap_targets += ';ARM;AArch64'
bootstrap_args = base_cmake_args + [
'-DLLVM_TARGETS_TO_BUILD=' + bootstrap_targets,
'-DLLVM_ENABLE_PROJECTS=' + projects,
'-DCMAKE_INSTALL_PREFIX=' + LLVM_BOOTSTRAP_INSTALL_DIR,
'-DCMAKE_C_FLAGS=' + ' '.join(cflags),
'-DCMAKE_CXX_FLAGS=' + ' '.join(cxxflags),
'-DLLVM_ENABLE_ASSERTIONS=ON',
]
if sys.platform == 'darwin':
bootstrap_args.extend([
'-DDARWIN_osx_ARCHS=x86_64',
'-DCOMPILER_RT_BUILD_BUILTINS=ON',
'-DCOMPILER_RT_BUILD_CRT=OFF',
'-DCOMPILER_RT_BUILD_LIBFUZZER=OFF',
'-DCOMPILER_RT_BUILD_SANITIZERS=OFF',
'-DCOMPILER_RT_BUILD_XRAY=OFF',
'-DCOMPILER_RT_ENABLE_IOS=OFF',
'-DCOMPILER_RT_ENABLE_WATCHOS=OFF',
'-DCOMPILER_RT_ENABLE_TVOS=OFF',
])
elif args.pgo:
bootstrap_args.extend([
'-DCOMPILER_RT_BUILD_BUILTINS=OFF',
'-DCOMPILER_RT_BUILD_CRT=OFF',
'-DCOMPILER_RT_BUILD_LIBFUZZER=OFF',
'-DCOMPILER_RT_BUILD_PROFILE=ON',
'-DCOMPILER_RT_BUILD_SANITIZERS=OFF',
'-DCOMPILER_RT_BUILD_XRAY=OFF',
])
if cc is not None: bootstrap_args.append('-DCMAKE_C_COMPILER=' + cc)
if cxx is not None: bootstrap_args.append('-DCMAKE_CXX_COMPILER=' + cxx)
if lld is not None: bootstrap_args.append('-DCMAKE_LINKER=' + lld)
RunCommand(['cmake'] + bootstrap_args + [os.path.join(LLVM_DIR, 'llvm')],
msvc_arch='x64')
CopyLibstdcpp(args, LLVM_BOOTSTRAP_DIR)
CopyLibstdcpp(args, LLVM_BOOTSTRAP_INSTALL_DIR)
RunCommand(['ninja'], msvc_arch='x64')
if args.run_tests:
test_targets = [ 'check-all' ]
if sys.platform == 'darwin':
test_targets = [ 'check-llvm', 'check-clang', 'check-builtins' ]
if sys.platform == 'win32':
CopyDiaDllTo(os.path.join(LLVM_BOOTSTRAP_DIR, 'bin'))
RunCommand(['ninja'] + test_targets, msvc_arch='x64')
RunCommand(['ninja', 'install'], msvc_arch='x64')
if sys.platform == 'win32':
cc = os.path.join(LLVM_BOOTSTRAP_INSTALL_DIR, 'bin', 'clang-cl.exe')
cxx = os.path.join(LLVM_BOOTSTRAP_INSTALL_DIR, 'bin', 'clang-cl.exe')
lld = os.path.join(LLVM_BOOTSTRAP_INSTALL_DIR, 'bin', 'lld-link.exe')
cc = cc.replace('\\', '/')
cxx = cxx.replace('\\', '/')
lld = lld.replace('\\', '/')
else:
cc = os.path.join(LLVM_BOOTSTRAP_INSTALL_DIR, 'bin', 'clang')
cxx = os.path.join(LLVM_BOOTSTRAP_INSTALL_DIR, 'bin', 'clang++')
if sys.platform.startswith('linux'):
base_cmake_args.append('-DLLVM_ENABLE_LLD=ON')
if args.gcc_toolchain:
cflags.append('--gcc-toolchain=' + args.gcc_toolchain)
cxxflags.append('--gcc-toolchain=' + args.gcc_toolchain)
print('Bootstrap compiler installed.')
if args.pgo:
print('Building instrumented compiler')
if os.path.exists(LLVM_INSTRUMENTED_DIR):
RmTree(LLVM_INSTRUMENTED_DIR)
EnsureDirExists(LLVM_INSTRUMENTED_DIR)
os.chdir(LLVM_INSTRUMENTED_DIR)
projects = 'clang'
if sys.platform == 'darwin':
projects += ';libcxx;compiler-rt'
instrument_args = base_cmake_args + [
'-DLLVM_ENABLE_PROJECTS=' + projects,
'-DCMAKE_C_FLAGS=' + ' '.join(cflags),
'-DCMAKE_CXX_FLAGS=' + ' '.join(cxxflags),
'-DLLVM_BUILD_INSTRUMENTED=IR',
]
if cc is not None: instrument_args.append('-DCMAKE_C_COMPILER=' + cc)
if cxx is not None: instrument_args.append('-DCMAKE_CXX_COMPILER=' + cxx)
if lld is not None: instrument_args.append('-DCMAKE_LINKER=' + lld)
RunCommand(['cmake'] + instrument_args + [os.path.join(LLVM_DIR, 'llvm')],
msvc_arch='x64')
CopyLibstdcpp(args, LLVM_INSTRUMENTED_DIR)
RunCommand(['ninja'], msvc_arch='x64')
print('Instrumented compiler built.')
training_source = 'pgo_training-1.ii'
with open(training_source, 'w') as f:
DownloadUrl(CDS_URL + '/' + training_source, f)
train_cmd = [os.path.join(LLVM_INSTRUMENTED_DIR, 'bin', 'clang++'),
'-target', 'x86_64-unknown-unknown', '-O2', '-g', '-std=c++14',
'-fno-exceptions', '-fno-rtti', '-w', '-c', training_source]
if sys.platform == 'darwin':
train_cmd.extend(['-stdlib=libc++', '-isysroot',
subprocess.check_output(['xcrun',
'--show-sdk-path']).rstrip()])
RunCommand(train_cmd, msvc_arch='x64')
profdata = os.path.join(LLVM_BOOTSTRAP_INSTALL_DIR, 'bin', 'llvm-profdata')
RunCommand([profdata, 'merge', '-output=' + LLVM_PROFDATA_FILE] +
glob.glob(os.path.join(LLVM_INSTRUMENTED_DIR, 'profiles',
'*.profraw')), msvc_arch='x64')
print('Profile generated.')
compiler_rt_args = [
'-DCOMPILER_RT_BUILD_CRT=OFF',
'-DCOMPILER_RT_BUILD_LIBFUZZER=OFF',
'-DCOMPILER_RT_BUILD_PROFILE=ON',
'-DCOMPILER_RT_BUILD_SANITIZERS=ON',
'-DCOMPILER_RT_BUILD_XRAY=OFF',
]
if sys.platform == 'darwin':
compiler_rt_args.extend([
'-DCOMPILER_RT_BUILD_BUILTINS=ON',
'-DCOMPILER_RT_ENABLE_IOS=ON',
'-DCOMPILER_RT_ENABLE_WATCHOS=OFF',
'-DCOMPILER_RT_ENABLE_TVOS=OFF',
'-DDARWIN_ios_ARCHS=armv7;armv7s;arm64',
'-DDARWIN_iossim_ARCHS=i386;x86_64',
'-DDARWIN_osx_ARCHS=x86_64',
])
else:
compiler_rt_args.append('-DCOMPILER_RT_BUILD_BUILTINS=OFF')
deployment_target = ''
if sys.platform == 'darwin' and args.bootstrap:
cflags = ['-isysroot', subprocess.check_output(
['xcrun', '--show-sdk-path']).rstrip()]
cxxflags = ['-stdlib=libc++'] + cflags
ldflags += ['-stdlib=libc++']
deployment_target = '10.7'
if args.llvm_force_head_revision:
cflags += ['-DLLVM_FORCE_HEAD_REVISION']
cxxflags += ['-DLLVM_FORCE_HEAD_REVISION']
if sys.platform == 'win32':
cflags += ['/Zi', '/GS-']
cxxflags += ['/Zi', '/GS-']
ldflags += ['/DEBUG', '/OPT:REF', '/OPT:ICF']
deployment_env = None
if deployment_target:
deployment_env = os.environ.copy()
deployment_env['MACOSX_DEPLOYMENT_TARGET'] = deployment_target
print('Building final compiler.')
default_tools = ['plugins', 'blink_gc_plugin', 'translation_unit']
chrome_tools = list(set(default_tools + args.extra_tools))
if cc is not None: base_cmake_args.append('-DCMAKE_C_COMPILER=' + cc)
if cxx is not None: base_cmake_args.append('-DCMAKE_CXX_COMPILER=' + cxx)
if lld is not None: base_cmake_args.append('-DCMAKE_LINKER=' + lld)
cmake_args = base_cmake_args + compiler_rt_args + [
'-DCMAKE_C_FLAGS=' + ' '.join(cflags),
'-DCMAKE_CXX_FLAGS=' + ' '.join(cxxflags),
'-DCMAKE_EXE_LINKER_FLAGS=' + ' '.join(ldflags),
'-DCMAKE_SHARED_LINKER_FLAGS=' + ' '.join(ldflags),
'-DCMAKE_MODULE_LINKER_FLAGS=' + ' '.join(ldflags),
'-DCMAKE_INSTALL_PREFIX=' + LLVM_BUILD_DIR,
'-DCHROMIUM_TOOLS_SRC=%s' % os.path.join(CHROMIUM_DIR, 'tools', 'clang'),
'-DCHROMIUM_TOOLS=%s' % ';'.join(chrome_tools)]
if args.pgo:
cmake_args.append('-DLLVM_PROFDATA_FILE=' + LLVM_PROFDATA_FILE)
if sys.platform == 'darwin':
cmake_args += ['-DCOMPILER_RT_ENABLE_IOS=ON',
'-DSANITIZER_MIN_OSX_VERSION=10.7']
CreateChromeToolsShim()
if os.path.exists(LLVM_BUILD_DIR):
RmTree(LLVM_BUILD_DIR)
EnsureDirExists(LLVM_BUILD_DIR)
os.chdir(LLVM_BUILD_DIR)
RunCommand(['cmake'] + cmake_args + [os.path.join(LLVM_DIR, 'llvm')],
msvc_arch='x64', env=deployment_env)
CopyLibstdcpp(args, LLVM_BUILD_DIR)
RunCommand(['ninja'], msvc_arch='x64')
if chrome_tools:
RunCommand(['ninja', 'cr-install'], msvc_arch='x64')
VerifyVersionOfBuiltClangMatchesVERSION()
if sys.platform == 'win32':
platform = 'windows'
elif sys.platform == 'darwin':
platform = 'darwin'
else:
assert sys.platform.startswith('linux')
platform = 'linux'
rt_lib_dst_dir = os.path.join(LLVM_BUILD_DIR, 'lib', 'clang',
RELEASE_VERSION, 'lib', platform)
if sys.platform == 'win32':
if os.path.isdir(COMPILER_RT_BUILD_DIR):
RmTree(COMPILER_RT_BUILD_DIR)
os.makedirs(COMPILER_RT_BUILD_DIR)
os.chdir(COMPILER_RT_BUILD_DIR)
if args.bootstrap:
cflags += ['-m32']
cxxflags += ['-m32']
compiler_rt_args = base_cmake_args + [
'-DCMAKE_C_FLAGS=' + ' '.join(cflags),
'-DCMAKE_CXX_FLAGS=' + ' '.join(cxxflags),
'-DCOMPILER_RT_BUILD_BUILTINS=OFF',
'-DCOMPILER_RT_BUILD_CRT=OFF',
'-DCOMPILER_RT_BUILD_LIBFUZZER=OFF',
'-DCOMPILER_RT_BUILD_PROFILE=ON',
'-DCOMPILER_RT_BUILD_SANITIZERS=OFF',
'-DCOMPILER_RT_BUILD_XRAY=OFF',
]
RunCommand(['cmake'] + compiler_rt_args +
[os.path.join(LLVM_DIR, 'llvm')],
msvc_arch='x86', env=deployment_env)
RunCommand(['ninja', 'compiler-rt'], msvc_arch='x86')
rt_lib_src_dir = os.path.join(COMPILER_RT_BUILD_DIR, 'lib', 'clang',
RELEASE_VERSION, 'lib', platform)
CopyDirectoryContents(rt_lib_src_dir, rt_lib_dst_dir)
if args.with_android:
make_toolchain = os.path.join(
ANDROID_NDK_DIR, 'build', 'tools', 'make_standalone_toolchain.py')
for target_arch in ['aarch64', 'arm', 'i686']:
toolchain_dir = os.path.join(
LLVM_BUILD_DIR, 'android-toolchain-' + target_arch)
api_level = '21' if target_arch == 'aarch64' else '19'
RunCommand([
make_toolchain,
'--api=' + api_level,
'--force',
'--install-dir=%s' % toolchain_dir,
'--stl=libc++',
'--arch=' + {
'aarch64': 'arm64',
'arm': 'arm',
'i686': 'x86',
}[target_arch]])
build_dir = os.path.join(LLVM_BUILD_DIR, 'android-' + target_arch)
if not os.path.exists(build_dir):
os.mkdir(os.path.join(build_dir))
os.chdir(build_dir)
target_triple = target_arch
if target_arch == 'arm':
target_triple = 'armv7'
target_triple += '-linux-android' + api_level
cflags = ['--target=%s' % target_triple,
'--sysroot=%s/sysroot' % toolchain_dir,
'-B%s' % toolchain_dir]
android_args = base_cmake_args + [
'-DCMAKE_C_COMPILER=' + os.path.join(LLVM_BUILD_DIR, 'bin/clang'),
'-DCMAKE_CXX_COMPILER=' + os.path.join(LLVM_BUILD_DIR, 'bin/clang++'),
'-DLLVM_CONFIG_PATH=' + os.path.join(LLVM_BUILD_DIR, 'bin/llvm-config'),
'-DCMAKE_C_FLAGS=' + ' '.join(cflags),
'-DCMAKE_CXX_FLAGS=' + ' '.join(cflags),
'-DCMAKE_ASM_FLAGS=' + ' '.join(cflags),
'-DCOMPILER_RT_BUILD_BUILTINS=OFF',
'-DCOMPILER_RT_BUILD_CRT=OFF',
'-DCOMPILER_RT_BUILD_LIBFUZZER=OFF',
'-DCOMPILER_RT_BUILD_PROFILE=ON',
'-DCOMPILER_RT_BUILD_SANITIZERS=ON',
'-DCOMPILER_RT_BUILD_XRAY=OFF',
'-DSANITIZER_CXX_ABI=libcxxabi',
'-DCMAKE_SHARED_LINKER_FLAGS=-Wl,-u__cxa_demangle',
'-DANDROID=1']
RunCommand(['cmake'] + android_args + [COMPILER_RT_DIR])
libs_want = ['lib/linux/libclang_rt.asan-{0}-android.so']
if target_arch in ['aarch64', 'arm']:
libs_want += [
'lib/linux/libclang_rt.ubsan_standalone-{0}-android.so',
'lib/linux/libclang_rt.profile-{0}-android.a',
]
if target_arch == 'aarch64':
libs_want += ['lib/linux/libclang_rt.hwasan-{0}-android.so']
libs_want = [lib.format(target_arch) for lib in libs_want]
RunCommand(['ninja'] + libs_want)
for p in libs_want:
shutil.copy(p, rt_lib_dst_dir)
if args.with_fuchsia:
for target_arch in ['aarch64', 'x86_64']:
fuchsia_arch_name = {'aarch64': 'arm64', 'x86_64': 'x64'}[target_arch]
toolchain_dir = os.path.join(
FUCHSIA_SDK_DIR, 'arch', fuchsia_arch_name, 'sysroot')
build_dir = os.path.join(LLVM_BUILD_DIR, 'fuchsia-' + target_arch)
if not os.path.exists(build_dir):
os.mkdir(os.path.join(build_dir))
os.chdir(build_dir)
target_spec = target_arch + '-fuchsia'
fuchsia_args = base_cmake_args + [
'-DCMAKE_C_COMPILER=' + os.path.join(LLVM_BUILD_DIR, 'bin/clang'),
'-DCMAKE_CXX_COMPILER=' + os.path.join(LLVM_BUILD_DIR, 'bin/clang++'),
'-DCMAKE_LINKER=' + os.path.join(LLVM_BUILD_DIR, 'bin/clang'),
'-DCMAKE_AR=' + os.path.join(LLVM_BUILD_DIR, 'bin/llvm-ar'),
'-DLLVM_CONFIG_PATH=' + os.path.join(LLVM_BUILD_DIR, 'bin/llvm-config'),
'-DCMAKE_SYSTEM_NAME=Fuchsia',
'-DCMAKE_C_COMPILER_TARGET=%s-fuchsia' % target_arch,
'-DCMAKE_ASM_COMPILER_TARGET=%s-fuchsia' % target_arch,
'-DCOMPILER_RT_BUILD_BUILTINS=ON',
'-DCOMPILER_RT_BUILD_CRT=OFF',
'-DCOMPILER_RT_BUILD_LIBFUZZER=OFF',
'-DCOMPILER_RT_BUILD_PROFILE=OFF',
'-DCOMPILER_RT_BUILD_SANITIZERS=OFF',
'-DCOMPILER_RT_BUILD_XRAY=OFF',
'-DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON',
'-DCMAKE_SYSROOT=%s' % toolchain_dir,
'-DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=ON',
'-DCMAKE_C_COMPILER_WORKS=ON',
'-DCMAKE_ASM_COMPILER_WORKS=ON',
]
RunCommand(['cmake'] +
fuchsia_args +
[os.path.join(COMPILER_RT_DIR, 'lib', 'builtins')])
builtins_a = 'libclang_rt.builtins.a'
RunCommand(['ninja', builtins_a])
fuchsia_lib_dst_dir = os.path.join(LLVM_BUILD_DIR, 'lib', 'clang',
RELEASE_VERSION, 'lib', target_spec)
if not os.path.exists(fuchsia_lib_dst_dir):
os.makedirs(fuchsia_lib_dst_dir)
CopyFile(os.path.join(build_dir, 'lib', target_spec, builtins_a),
fuchsia_lib_dst_dir)
if args.run_tests or args.llvm_force_head_revision:
RunCommand(['ninja', '-C', LLVM_BUILD_DIR, 'cr-check-all'], msvc_arch='x64')
if args.run_tests:
if sys.platform == 'win32':
CopyDiaDllTo(os.path.join(LLVM_BUILD_DIR, 'bin'))
test_targets = [ 'check-all' ]
if sys.platform == 'darwin':
test_targets = [ 'check-llvm', 'check-clang', 'check-lld' ]
RunCommand(['ninja', '-C', LLVM_BUILD_DIR] + test_targets, msvc_arch='x64')
if sys.platform == 'darwin':
for dylib in glob.glob(os.path.join(rt_lib_dst_dir, '*.dylib')):
subprocess.call(['install_name_tool', '-id',
'@executable_path/' + os.path.basename(dylib), dylib])
WriteStampFile(PACKAGE_VERSION, STAMP_FILE)
WriteStampFile(PACKAGE_VERSION, FORCE_HEAD_REVISION_FILE)
print('Clang build was successful.')
return 0
if __name__ == '__main__':
sys.exit(main())