#!/usr/bin/env python3 import os import subprocess import shutil import argparse import sys def get_build_config(build_type): """Return build configuration based on build type""" configs = { "debug": { "build_dir": "build-debug", "install_dir": "./build-debug-install", "build_type": "Debug", "sanitizer": "Address", "shared_libs": True, }, "thread": { "build_dir": "build-thread", "install_dir": "./build-thread-install", "build_type": "Debug", "sanitizer": "Thread", "shared_libs": True, }, "release": { "build_dir": "build-release", "install_dir": "./build-release-install", "build_type": "Release", "sanitizer": None, "shared_libs": False, }, } if build_type not in configs: print(f"Error: Unsupported build type '{build_type}'") print(f"Supported build types: {', '.join(configs.keys())}") sys.exit(1) return configs[build_type] def build_llvm(config): """Execute LLVM build process""" print(f"Starting LLVM build ({config['build_type']} mode)") # Build CMake command config_args = [ "cmake", "-G", "Ninja", "-S", "./llvm", "-B", config["build_dir"], "-DLLVM_USE_LINKER=lld", "-DCMAKE_C_COMPILER=clang", "-DCMAKE_CXX_COMPILER=clang++", "-DCMAKE_BUILD_TYPE=" + config["build_type"], # Only build native to speed up building llvm. "-DLLVM_TARGETS_TO_BUILD=Native", "-DLLVM_ENABLE_PROJECTS=clang;clang-tools-extra", "-DCMAKE_INSTALL_PREFIX=" + config["install_dir"], ] # Add optional configurations # Build shared lib to reduce binary size and speed up linking if config["shared_libs"]: config_args.append("-DBUILD_SHARED_LIBS=ON") if config["sanitizer"]: config_args.append(f"-DLLVM_USE_SANITIZER={config['sanitizer']}") # CMake build command list cmake_commands = [ config_args, ["cmake", "--build", config["build_dir"]], ["cmake", "--install", config["build_dir"]], ] # Execute CMake commands for i, command in enumerate(cmake_commands): print(f"Executing command {i + 1}/{len(cmake_commands)}: {' '.join(command)}") try: subprocess.run(command, check=True) except subprocess.CalledProcessError as e: print(f"Build failed: {e}") sys.exit(1) def copy_header_files(config): """Copy header files to installation directory""" print("Copying header files...") src = "./clang/lib/Sema/" dst = os.path.join(config["install_dir"], "include/clang/Sema/") files = ["CoroutineStmtBuilder.h", "TypeLocBuilder.h", "TreeTransform.h"] # Ensure target directory exists os.makedirs(dst, exist_ok=True) for file in files: src_file = os.path.join(src, file) dst_file = os.path.join(dst, file) if os.path.exists(src_file): print(f"Copying {src_file} to {dst_file}") shutil.copy(src_file, dst_file) else: print(f"Warning: Source file does not exist {src_file}") def main(): parser = argparse.ArgumentParser( description="Build LLVM libraries with different build configurations", formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" Build type descriptions: debug - Debug mode with Address Sanitizer, builds shared libraries thread - Debug mode with Thread Sanitizer, builds shared libraries release - Release mode without sanitizer, builds static libraries Examples: python build-llvm-libs.py debug python build-llvm-libs.py thread python build-llvm-libs.py release """, ) parser.add_argument( "build_type", choices=["debug", "thread", "release"], help="Build type (debug/thread/release)", ) parser.add_argument( "--skip-copy", action="store_true", help="Skip header file copying step" ) args = parser.parse_args() # Get build configuration config = get_build_config(args.build_type) print("=== LLVM Build Configuration ===") print(f"Build type: {args.build_type}") print(f"Build directory: {config['build_dir']}") print(f"Install directory: {config['install_dir']}") print(f"CMake build type: {config['build_type']}") if config["sanitizer"]: print(f"Sanitizer: {config['sanitizer']}") print(f"Shared libraries: {config['shared_libs']}") print("=" * 30) # Execute build build_llvm(config) # Copy header files (unless skipped) if not args.skip_copy: copy_header_files(config) print(f"\n✅ LLVM {args.build_type} build completed!") print(f"Install directory: {config['install_dir']}") if __name__ == "__main__": main()