diff --git a/compiler-rt/cmake/Modules/CompilerRTMockLLVMCMakeConfig.cmake b/compiler-rt/cmake/Modules/CompilerRTMockLLVMCMakeConfig.cmake new file mode 100644 --- /dev/null +++ b/compiler-rt/cmake/Modules/CompilerRTMockLLVMCMakeConfig.cmake @@ -0,0 +1,75 @@ +# This macro mocks enough of the changes `LLVMConfig.cmake` makes so that +# compiler-rt can successfully configure itself when a LLVM toolchain is +# available but the corresponding CMake build files are not. +# +# The motivation for this is to be able to generate the compiler-rt +# lit tests suites and run them against an arbitrary LLVM toolchain +# which doesn't ship the LLVM CMake build files. +macro(compiler_rt_mock_llvm_cmake_config) + message(STATUS "Attempting to mock the changes made by LLVMConfig.cmake") + compiler_rt_mock_llvm_cmake_config_set_cmake_path() + compiler_rt_mock_llvm_cmake_config_set_target_triple() + compiler_rt_mock_llvm_cmake_config_include_cmake_files() +endmacro() + +macro(compiler_rt_mock_llvm_cmake_config_set_cmake_path) + # Point `LLVM_CMAKE_PATH` at the source tree in the monorepo. + set(LLVM_CMAKE_PATH "${LLVM_MAIN_SRC_DIR}/cmake/modules") + if (NOT EXISTS "${LLVM_CMAKE_PATH}") + message(FATAL_ERROR "LLVM_CMAKE_PATH (${LLVM_CMAKE_PATH}) does not exist") + endif() + list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}") + message(STATUS "LLVM_CMAKE_PATH: \"${LLVM_CMAKE_PATH}\"") +endmacro() + +function(compiler_rt_mock_llvm_cmake_config_set_target_triple) + # Various bits of compiler-rt depend on the `TARGET_TRIPLE`variable being + # defined. This function tries to set a sensible value for the variable. + # This is a function rather than a macro to avoid polluting the variable + # namespace. + set(COMPILER_OUTPUT "") + + # If the user provides `COMPILER_RT_DEFAULT_TARGET_ONLY` and `CMAKE_C_COMPILER_TARGET` + # (see `construct_compiler_rt_default_triple`) then prefer that to examining the + # compiler. + if (COMPILER_RT_DEFAULT_TARGET_ONLY) + if (NOT "${CMAKE_C_COMPILER_TARGET}" STREQUAL "") + message(STATUS + "Using CMAKE_C_COMPILER_TARGET (${CMAKE_C_COMPILER_TARGET}) as TARGET_TRIPLE") + endif() + set(COMPILER_OUTPUT "${CMAKE_C_COMPILER_TARGET}") + endif() + + # Try asking the compiler for its default target triple. + set(HAD_ERROR FALSE) + if ("${COMPILER_OUTPUT}" STREQUAL "") + if ("${CMAKE_C_COMPILER_ID}" MATCHES "Clang|GNU") + # Note: Clang also supports `-print-target-triple` but gcc doesn't + # support this flag. + execute_process( + COMMAND "${CMAKE_C_COMPILER}" -dumpmachine + RESULT_VARIABLE HAD_ERROR + OUTPUT_VARIABLE COMPILER_OUTPUT + OUTPUT_STRIP_TRAILING_WHITESPACE) + else() + message(FATAL_ERROR + "Fetching target triple from compiler \"${CMAKE_C_COMPILER_ID}\" " + "is not implemented.") + endif() + endif() + + if (HAD_ERROR) + message(FATAL_ERROR "Fetching target triple from compiler failed") + endif() + set(TARGET_TRIPLE "${COMPILER_OUTPUT}") + message(STATUS "TARGET_TRIPLE: \"${TARGET_TRIPLE}\"") + if ("${TARGET_TRIPLE}" STREQUAL "") + message(FATAL_ERROR "TARGET_TRIPLE cannot be empty") + endif() + set(TARGET_TRIPLE "${TARGET_TRIPLE}" PARENT_SCOPE) +endfunction() + +macro(compiler_rt_mock_llvm_cmake_config_include_cmake_files) + # Some compiler-rt CMake code needs to call code in this file. + include("${LLVM_CMAKE_PATH}/AddLLVM.cmake") +endmacro() diff --git a/compiler-rt/cmake/Modules/CompilerRTUtils.cmake b/compiler-rt/cmake/Modules/CompilerRTUtils.cmake --- a/compiler-rt/cmake/Modules/CompilerRTUtils.cmake +++ b/compiler-rt/cmake/Modules/CompilerRTUtils.cmake @@ -283,6 +283,7 @@ "You are not using the monorepo layout. This configuration is DEPRECATED.") endif() + set(FOUND_LLVM_CMAKE_PATH FALSE) if (LLVM_CONFIG_PATH) execute_process( COMMAND ${LLVM_CONFIG_PATH} "--obj-root" "--bindir" "--libdir" "--src-root" "--includedir" @@ -372,9 +373,15 @@ set(LLVM_CMAKE_PATH "${LLVM_BINARY_DIR_CMAKE_STYLE}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm") endif() - list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}") - # Get some LLVM variables from LLVMConfig. - include("${LLVM_CMAKE_PATH}/LLVMConfig.cmake") + if (EXISTS "${LLVM_CMAKE_PATH}") + list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}") + # Get some LLVM variables from LLVMConfig. + include("${LLVM_CMAKE_PATH}/LLVMConfig.cmake") + set(FOUND_LLVM_CMAKE_PATH TRUE) + else() + set(FOUND_LLVM_CMAKE_PATH FALSE) + message(WARNING "LLVM CMake path (${LLVM_CMAKE_PATH}) reported by llvm-config does not exist") + endif() set(LLVM_LIBRARY_OUTPUT_INTDIR ${LLVM_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX}) @@ -393,6 +400,15 @@ "the `llvm-project` repo. " "This will be treated as error in the future.") endif() + + if (NOT FOUND_LLVM_CMAKE_PATH) + # This configuration tries to configure without the prescence of `LLVMConfig.cmake`. It is + # intended for testing purposes (generating the lit test suites) and will likely not support + # a build of the runtimes in compiler-rt. + include(CompilerRTMockLLVMCMakeConfig) + compiler_rt_mock_llvm_cmake_config() + endif() + endmacro() macro(construct_compiler_rt_default_triple)