#!/usr/bin/env python # Copyright 2019 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. """A script for fetching LLVM monorepo and building clang-tools-extra binaries. Example: build clangd and clangd-indexer tools/clang/scripts/build_clang_tools_extra.py --fetch out/Release clangd \ clangd-indexer """ from __future__ import print_function import argparse import errno import os import subprocess import sys import update def GetCheckoutDir(out_dir): """Returns absolute path to the checked-out llvm repo.""" return os.path.join(out_dir, 'tools', 'clang', 'third_party', 'llvm') def GetBuildDir(out_dir): return os.path.join(GetCheckoutDir(out_dir), 'build') def CreateDirIfNotExists(dir): if not os.path.exists(dir): os.makedirs(dir) def FetchLLVM(checkout_dir, revision): """Clone llvm repo into |out_dir| or update if it already exists.""" CreateDirIfNotExists(os.path.dirname(checkout_dir)) try: # First, try to clone the repo. args = [ 'git', 'clone', 'https://github.com/llvm/llvm-project.git', checkout_dir, ] subprocess.check_call(args, shell=sys.platform == 'win32') except subprocess.CalledProcessError: # Otherwise, try to update it. print('-- Attempting to update existing repo') args = ['git', 'pull', '--rebase', 'origin', 'master'] subprocess.check_call(args, cwd=checkout_dir, shell=sys.platform == 'win32') if revision: args = ['git', 'checkout', revision] subprocess.check_call(args, cwd=checkout_dir, shell=sys.platform == 'win32') def BuildTargets(build_dir, targets): """Build targets from llvm repo at |build_dir|.""" CreateDirIfNotExists(build_dir) # From that dir, run cmake cmake_args = [ 'cmake', '-GNinja', '-DLLVM_ENABLE_PROJECTS=clang;clang-tools-extra', '-DCMAKE_BUILD_TYPE=Release', '-DLLVM_ENABLE_ASSERTIONS=On', '../llvm', ] subprocess.check_call(cmake_args, cwd=build_dir) ninja_commands = ['ninja'] + targets subprocess.check_call(ninja_commands, cwd=build_dir) def main(): parser = argparse.ArgumentParser(description='Build clang_tools_extra.') parser.add_argument('--fetch', action='store_true', help='fetch LLVM source') parser.add_argument( '--revision', help='LLVM revision to use', default=update.CLANG_REVISION) parser.add_argument('OUT_DIR', help='where we put the LLVM source repository') parser.add_argument('TARGETS', nargs='+', help='targets being built') args = parser.parse_args() if args.fetch: print('Fetching LLVM source') FetchLLVM(GetCheckoutDir(args.OUT_DIR), args.revision) print('Building targets: %s' % ', '.join(args.TARGETS)) BuildTargets(GetBuildDir(args.OUT_DIR), args.TARGETS) if __name__ == '__main__': sys.exit(main())