# llvm_ExternalProject_BuildCmd(out_var target)
# Utility function for constructing command lines for external project targets
function(llvm_ExternalProject_BuildCmd out_var target bin_dir
)
cmake_parse_arguments(ARG "" "CONFIGURATION" "" ${ARGN})
if(NOT ARG_CONFIGURATION
)
set(ARG_CONFIGURATION
"$<CONFIG>")
if (CMAKE_GENERATOR
MATCHES "Make")
# Use special command for Makefiles to support parallelism.
set(${out_var} "$(MAKE)" "-C" "${bin_dir}" "${target}" PARENT_SCOPE)
set(tool_args
"${LLVM_EXTERNAL_PROJECT_BUILD_TOOL_ARGS}")
if(NOT tool_args
STREQUAL "")
string(CONFIGURE "${tool_args}" tool_args @ONLY
)
string(PREPEND tool_args
"-- ")
set(${out_var} ${CMAKE_COMMAND} --build
${bin_dir} --target
${target}
--config ${ARG_CONFIGURATION} ${tool_args} PARENT_SCOPE)
# is_msvc_triple(out_var triple)
# Checks whether the passed triple refers to an MSVC environment
if (triple
MATCHES ".*-windows-msvc.*")
set(${out_var} TRUE PARENT_SCOPE)
set(${out_var} FALSE PARENT_SCOPE)
# llvm_ExternalProject_Add(name source_dir ...
# USE_TOOLCHAIN
# Use just-built tools (see TOOLCHAIN_TOOLS)
# EXCLUDE_FROM_ALL
# Exclude this project from the all target
# NO_INSTALL
# Don't generate install targets for this project
# ALWAYS_CLEAN
# Always clean the sub-project before building
# CMAKE_ARGS arguments...
# Optional cmake arguments to pass when configuring the project
# TOOLCHAIN_TOOLS targets...
# Targets for toolchain tools (defaults to clang;lld)
# DEPENDS targets...
# Targets that this project depends on
# EXTRA_TARGETS targets...
# Extra targets in the subproject to generate targets for
# PASSTHROUGH_PREFIXES prefix...
# Extra variable prefixes (name is always included) to pass down
# STRIP_TOOL path
# Use provided strip tool instead of the default one.
# TARGET_TRIPLE triple
# Optional target triple to pass to the compiler
# )
function(llvm_ExternalProject_Add name source_dir
)
cmake_parse_arguments(ARG
"USE_TOOLCHAIN;EXCLUDE_FROM_ALL;NO_INSTALL;ALWAYS_CLEAN"
"SOURCE_DIR"
"CMAKE_ARGS;TOOLCHAIN_TOOLS;RUNTIME_LIBRARIES;DEPENDS;EXTRA_TARGETS;PASSTHROUGH_PREFIXES;STRIP_TOOL;TARGET_TRIPLE"
${ARGN})
canonicalize_tool_name(${name} nameCanon)
if(arg
MATCHES "^-DCMAKE_SYSTEM_NAME=")
string(REGEX REPLACE "^-DCMAKE_SYSTEM_NAME=(.*)$" "\\1" _cmake_system_name
"${arg}")
# If CMAKE_SYSTEM_NAME is not set explicitly in the arguments passed to us,
# reflect CMake's own default.
if (NOT _cmake_system_name
)
set(_cmake_system_name
"${CMAKE_HOST_SYSTEM_NAME}")
if(NOT ARG_TARGET_TRIPLE
)
set(target_triple
${LLVM_DEFAULT_TARGET_TRIPLE})
set(target_triple
${ARG_TARGET_TRIPLE})
is_msvc_triple(is_msvc_target ${target_triple})
if(NOT ARG_TOOLCHAIN_TOOLS
)
set(ARG_TOOLCHAIN_TOOLS clang
)
# AIX 64-bit XCOFF and big AR format is not yet supported in some of these tools.
if(NOT _cmake_system_name
STREQUAL AIX
)
list(APPEND ARG_TOOLCHAIN_TOOLS lld llvm-ar llvm-ranlib llvm-nm llvm-objdump
)
if(_cmake_system_name
STREQUAL Darwin
)
list(APPEND ARG_TOOLCHAIN_TOOLS llvm-libtool-darwin llvm-lipo
)
list(APPEND ARG_TOOLCHAIN_TOOLS llvm-lib
)
# TODO: These tools don't fully support Mach-O format yet.
list(APPEND ARG_TOOLCHAIN_TOOLS llvm-objcopy llvm-strip llvm-readelf
)
foreach(tool
${ARG_TOOLCHAIN_TOOLS})
list(APPEND TOOLCHAIN_TOOLS
${tool})
# $<TARGET_FILE:tgt> only works on add_executable or add_library targets
# The below logic mirrors cmake's own implementation
if(NOT target_type
STREQUAL "OBJECT_LIBRARY" AND
NOT target_type STREQUAL "UTILITY" AND
NOT target_type STREQUAL "GLOBAL_TARGET" AND
NOT target_type STREQUAL "INTERFACE_LIBRARY")
list(APPEND TOOLCHAIN_BINS $<TARGET_FILE:
${tool}>
)
if(NOT ARG_RUNTIME_LIBRARIES
)
set(ARG_RUNTIME_LIBRARIES compiler-rt libcxx
)
foreach(lib
${ARG_RUNTIME_LIBRARIES})
list(APPEND RUNTIME_LIBRARIES
${lib})
if(clang IN_LIST TOOLCHAIN_TOOLS
)
set(CLANG_IN_TOOLCHAIN On
)
if(RUNTIME_LIBRARIES
AND CLANG_IN_TOOLCHAIN
)
list(APPEND TOOLCHAIN_BINS
${RUNTIME_LIBRARIES})
set(STAMP_DIR
${CMAKE_CURRENT_BINARY_DIR}/
${name}-stamps/
)
set(BINARY_DIR
${CMAKE_CURRENT_BINARY_DIR}/
${name}-bins/
)
COMMAND ${CMAKE_COMMAND} -E remove_directory ${BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E remove_directory ${STAMP_DIR}
COMMENT "Clobbering ${name} build and stamp directories"
USES_TERMINAL
)
# Find all variables that start with a prefix and propagate them through
list(APPEND ARG_PASSTHROUGH_PREFIXES
${nameCanon})
foreach(prefix
${ARG_PASSTHROUGH_PREFIXES})
foreach(variableName
${variableNames})
if(variableName
MATCHES "^${prefix}")
string(REPLACE ";" "|" value
"${${variableName}}")
list(APPEND PASSTHROUGH_VARIABLES
-D${variableName}=${value})
if(ARG_USE_TOOLCHAIN
AND NOT CMAKE_CROSSCOMPILING
)
set(compiler_args -DCMAKE_C_COMPILER=
${LLVM_RUNTIME_OUTPUT_INTDIR}/clang-cl
${CMAKE_EXECUTABLE_SUFFIX}
-DCMAKE_CXX_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang-cl${CMAKE_EXECUTABLE_SUFFIX}
-DCMAKE_ASM_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang-cl${CMAKE_EXECUTABLE_SUFFIX})
set(compiler_args -DCMAKE_C_COMPILER=
${LLVM_RUNTIME_OUTPUT_INTDIR}/clang
${CMAKE_EXECUTABLE_SUFFIX}
-DCMAKE_CXX_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang++${CMAKE_EXECUTABLE_SUFFIX}
-DCMAKE_ASM_COMPILER=${LLVM_RUNTIME_OUTPUT_INTDIR}/clang${CMAKE_EXECUTABLE_SUFFIX})
if(lld IN_LIST TOOLCHAIN_TOOLS
)
list(APPEND compiler_args -DCMAKE_LINKER=
${LLVM_RUNTIME_OUTPUT_INTDIR}/lld-link
${CMAKE_EXECUTABLE_SUFFIX})
elseif(NOT _cmake_system_name
STREQUAL Darwin
)
list(APPEND compiler_args -DCMAKE_LINKER=
${LLVM_RUNTIME_OUTPUT_INTDIR}/ld.lld
${CMAKE_EXECUTABLE_SUFFIX})
if(llvm-ar IN_LIST TOOLCHAIN_TOOLS
)
list(APPEND compiler_args -DCMAKE_AR=
${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-lib
${CMAKE_EXECUTABLE_SUFFIX})
list(APPEND compiler_args -DCMAKE_AR=
${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-ar
${CMAKE_EXECUTABLE_SUFFIX})
if(llvm-libtool-darwin IN_LIST TOOLCHAIN_TOOLS
)
list(APPEND compiler_args -DCMAKE_LIBTOOL=
${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-libtool-darwin
${CMAKE_EXECUTABLE_SUFFIX})
if(llvm-lipo IN_LIST TOOLCHAIN_TOOLS
)
list(APPEND compiler_args -DCMAKE_LIPO=
${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-lipo
${CMAKE_EXECUTABLE_SUFFIX})
if(llvm-ranlib IN_LIST TOOLCHAIN_TOOLS
)
list(APPEND compiler_args -DCMAKE_RANLIB=
${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-ranlib
${CMAKE_EXECUTABLE_SUFFIX})
if(llvm-nm IN_LIST TOOLCHAIN_TOOLS
)
list(APPEND compiler_args -DCMAKE_NM=
${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-nm
${CMAKE_EXECUTABLE_SUFFIX})
if(llvm-objdump IN_LIST TOOLCHAIN_TOOLS
)
list(APPEND compiler_args -DCMAKE_OBJDUMP=
${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-objdump
${CMAKE_EXECUTABLE_SUFFIX})
if(llvm-objcopy IN_LIST TOOLCHAIN_TOOLS
)
list(APPEND compiler_args -DCMAKE_OBJCOPY=
${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-objcopy
${CMAKE_EXECUTABLE_SUFFIX})
if(llvm-strip IN_LIST TOOLCHAIN_TOOLS
AND NOT ARG_STRIP_TOOL
)
list(APPEND compiler_args -DCMAKE_STRIP=
${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-strip
${CMAKE_EXECUTABLE_SUFFIX})
if(llvm-readelf IN_LIST TOOLCHAIN_TOOLS
)
list(APPEND compiler_args -DCMAKE_READELF=
${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-readelf
${CMAKE_EXECUTABLE_SUFFIX})
list(APPEND ARG_DEPENDS
${TOOLCHAIN_TOOLS})
list(APPEND compiler_args -DCMAKE_STRIP=
${ARG_STRIP_TOOL})
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp
DEPENDS ${ARG_DEPENDS}
COMMAND ${CMAKE_COMMAND} -E touch ${BINARY_DIR}/CMakeCache.txt
COMMAND ${CMAKE_COMMAND} -E touch ${STAMP_DIR}/${name}-mkdir
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp
COMMENT "Clobbering bootstrap build and stamp directories"
)
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp)
set(exclude
EXCLUDE_FROM_ALL 1
)
set(sysroot_arg -DCMAKE_SYSROOT=
${CMAKE_SYSROOT})
set(compiler_args -DCMAKE_ASM_COMPILER=
${CMAKE_ASM_COMPILER}
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-DCMAKE_LINKER=${CMAKE_LINKER}
-DCMAKE_AR=${CMAKE_AR}
-DCMAKE_RANLIB=${CMAKE_RANLIB}
-DCMAKE_NM=${CMAKE_NM}
-DCMAKE_OBJCOPY=${CMAKE_OBJCOPY}
-DCMAKE_OBJDUMP=${CMAKE_OBJDUMP}
-DCMAKE_STRIP=${CMAKE_STRIP}
-DCMAKE_READELF=${CMAKE_READELF})
set(llvm_config_path
${LLVM_CONFIG_PATH})
if(CMAKE_CXX_COMPILER_ID
MATCHES "Clang")
string(REGEX MATCH "^[0-9]+" CLANG_VERSION_MAJOR
${PACKAGE_VERSION})
set(resource_dir
"${LLVM_LIBRARY_DIR}/clang/${CLANG_VERSION_MAJOR}")
set(flag_types ASM C CXX MODULE_LINKER SHARED_LINKER EXE_LINKER
)
set(${type}_flag -DCMAKE_
${type}_FLAGS=-resource-dir=
${resource_dir})
string(REPLACE ";" "|" flag_string
"${flag_types}")
if(arg
MATCHES "^-DCMAKE_(${flag_string})_FLAGS")
if(arg
MATCHES "^-DCMAKE_${type}_FLAGS")
string(REGEX REPLACE "^-DCMAKE_${type}_FLAGS=(.*)$" "\\1" flag_value
"${arg}")
set(${type}_flag
"${${type}_flag} ${flag_value}")
list(APPEND cmake_args
${arg})
list(APPEND cmake_args
${${type}_flag}
)
set(cmake_args
${ARG_CMAKE_ARGS})
set(llvm_config_path
"$<TARGET_FILE:llvm-config>")
set(cmake_args
${ARG_CMAKE_ARGS})
list(APPEND compiler_args -DCMAKE_C_COMPILER_TARGET=
${ARG_TARGET_TRIPLE})
list(APPEND compiler_args -DCMAKE_CXX_COMPILER_TARGET=
${ARG_TARGET_TRIPLE})
list(APPEND compiler_args -DCMAKE_ASM_COMPILER_TARGET=
${ARG_TARGET_TRIPLE})
ExternalProject_Add(${name}
DEPENDS ${ARG_DEPENDS} llvm-config
${name}-clobber
PREFIX ${CMAKE_BINARY_DIR}/projects/${name}
SOURCE_DIR ${source_dir}
STAMP_DIR ${STAMP_DIR}
BINARY_DIR ${BINARY_DIR}
${exclude}
CMAKE_ARGS ${${nameCanon}_CMAKE_ARGS}
${compiler_args}
-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
${sysroot_arg}
-DLLVM_BINARY_DIR=${PROJECT_BINARY_DIR}
-DLLVM_CONFIG_PATH=${llvm_config_path}
-DLLVM_ENABLE_WERROR=${LLVM_ENABLE_WERROR}
-DLLVM_HOST_TRIPLE=${LLVM_HOST_TRIPLE}
-DLLVM_HAVE_LINK_VERSION_SCRIPT=${LLVM_HAVE_LINK_VERSION_SCRIPT}
-DLLVM_USE_RELATIVE_PATHS_IN_DEBUG_INFO=${LLVM_USE_RELATIVE_PATHS_IN_DEBUG_INFO}
-DLLVM_USE_RELATIVE_PATHS_IN_FILES=${LLVM_USE_RELATIVE_PATHS_IN_FILES}
-DLLVM_LIT_ARGS=${LLVM_LIT_ARGS}
-DLLVM_SOURCE_PREFIX=${LLVM_SOURCE_PREFIX}
-DPACKAGE_VERSION=${PACKAGE_VERSION}
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}
-DCMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER}
-DCMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER}
-DCMAKE_EXPORT_COMPILE_COMMANDS=1
${cmake_args}
${PASSTHROUGH_VARIABLES}
INSTALL_COMMAND ""
STEP_TARGETS configure build
BUILD_ALWAYS 1
USES_TERMINAL_CONFIGURE 1
USES_TERMINAL_BUILD 1
USES_TERMINAL_INSTALL 1
LIST_SEPARATOR |
)
set(force_deps
DEPENDS ${TOOLCHAIN_BINS})
llvm_ExternalProject_BuildCmd(run_clean clean ${BINARY_DIR})
ExternalProject_Add_Step(${name} clean
COMMAND ${run_clean}
COMMENT "Cleaning ${name}..."
DEPENDEES configure
${force_deps}
WORKING_DIRECTORY ${BINARY_DIR}
EXCLUDE_FROM_MAIN 1
USES_TERMINAL 1
)
ExternalProject_Add_StepTargets(${name} clean)
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/${name}-clobber-stamp)
install(CODE
"execute_process\(COMMAND \${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=\${CMAKE_INSTALL_PREFIX} -DCMAKE_INSTALL_DO_STRIP=\${CMAKE_INSTALL_DO_STRIP} -P ${BINARY_DIR}/cmake_install.cmake\)"
COMPONENT ${name})
add_llvm_install_targets(install-${name}
DEPENDS ${name}
COMPONENT ${name})
# Add top-level targets
foreach(target
${ARG_EXTRA_TARGETS})
set(external_target
"${${target}}")
set(external_target
"${target}")
llvm_ExternalProject_BuildCmd(build_runtime_cmd ${external_target} ${BINARY_DIR})
COMMAND ${build_runtime_cmd}
DEPENDS ${name}-configure
WORKING_DIRECTORY ${BINARY_DIR}
VERBATIM
USES_TERMINAL)