# Native output is independent of the optional -r execution engine. find_package(Clang REQUIRED CONFIG HINTS "${LLVM_INSTALL_PREFIX}/lib/cmake/clang") cpsc_find_dependency(PATH LLD_DIR NAMES LLDConfig.cmake PATH_SUFFIXES lib/cmake/lld cmake) find_package(LLD REQUIRED CONFIG HINTS "${LLVM_INSTALL_PREFIX}/lib/cmake/lld") cpsc_find_dependency(PROGRAM PERL_EXECUTABLE NAMES perl REQUIRED) find_package(Perl REQUIRED) if(NOT LLVM_ENABLE_ZLIB) message(FATAL_ERROR "Native link resources require LLVM built with zlib support") endif() if(MINGW) set(cpsc_native_platform windows) set(cpsc_linker_libraries lldMinGW lldCOFF) elseif(APPLE) set(cpsc_native_platform macos) set(cpsc_linker_libraries lldMachO) else() set(cpsc_native_platform linux) set(cpsc_linker_libraries lldELF) endif() foreach(cpsc_native_library clangDriver ${cpsc_linker_libraries}) get_target_property(cpsc_native_type ${cpsc_native_library} TYPE) if(NOT cpsc_native_type STREQUAL "STATIC_LIBRARY") message(FATAL_ERROR "Native output requires static ${cpsc_native_library}; found ${cpsc_native_type}. See doc/build.md for static dependency setup.") endif() endforeach() set(cpsc_native_flags) get_filename_component(cpsc_lld_prefix "${LLD_DIR}/../../.." ABSOLUTE) if(APPLE) set(cpsc_linker_names ld64.lld) else() set(cpsc_linker_names ld.lld-23 ld.lld) endif() find_program(CPSC_NATIVE_LINKER NAMES ${cpsc_linker_names} HINTS "${cpsc_lld_prefix}/bin" ${CPSC_LOCAL_BIN_DIRS}) if(NOT CPSC_NATIVE_LINKER) message(FATAL_ERROR "Install the LLD 23 executable to prepare native link resources") endif() list(APPEND cpsc_native_flags "--flag=--ld-path=${CPSC_NATIVE_LINKER}") target_link_options(cpsc PRIVATE -fuse-ld=lld "--ld-path=${CPSC_NATIVE_LINKER}") if(CMAKE_SYSROOT) list(APPEND cpsc_native_flags "--flag=--sysroot=${CMAKE_SYSROOT}") endif() if(APPLE) if(NOT CMAKE_OSX_SYSROOT) execute_process(COMMAND xcrun --show-sdk-path OUTPUT_VARIABLE CMAKE_OSX_SYSROOT OUTPUT_STRIP_TRAILING_WHITESPACE RESULT_VARIABLE cpsc_sdk_result) if(NOT cpsc_sdk_result EQUAL 0) message(FATAL_ERROR "Cannot locate the macOS SDK") endif() endif() list(APPEND cpsc_native_flags "--flag=-isysroot" "--flag=${CMAKE_OSX_SYSROOT}") if(CMAKE_OSX_DEPLOYMENT_TARGET) list(APPEND cpsc_native_flags "--flag=-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") endif() endif() set(cpsc_runtime_generator "${CMAKE_SOURCE_DIR}/tools/driver/prepare-native-runtime.pl") set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${cpsc_runtime_generator}") execute_process(COMMAND "${PERL_EXECUTABLE}" "${cpsc_runtime_generator}" "--compiler=${CMAKE_CXX_COMPILER}" "--output=${CMAKE_BINARY_DIR}/native-runtime/NativeRuntime.inc" "--platform=${cpsc_native_platform}" ${cpsc_native_flags} RESULT_VARIABLE cpsc_runtime_result OUTPUT_VARIABLE cpsc_runtime_output ERROR_VARIABLE cpsc_runtime_error) if(NOT cpsc_runtime_result EQUAL 0) message(FATAL_ERROR "Cannot prepare native link resources: ${cpsc_runtime_error}") endif() message(STATUS "${cpsc_runtime_output}") include("${CMAKE_BINARY_DIR}/native-runtime/native-runtime-inputs.cmake") target_sources(cpsc PRIVATE tools/driver/NativeCompiler.cc) target_include_directories(cpsc PRIVATE ${CLANG_INCLUDE_DIRS} ${LLD_INCLUDE_DIRS} "${CMAKE_BINARY_DIR}/native-runtime") target_link_libraries(cpsc PRIVATE clangDriver ${cpsc_linker_libraries}) if(MINGW AND TARGET LibXml2::LibXml2) # LLD's COFF manifest support reaches libxml2 through LLVMWindowsManifest. # An explicit .dll.a in that interface bypasses the driver's -static flag. cpsc_find_dependency(LIBRARY CPSC_STATIC_xml2 REQUIRED NAMES libxml2.a) cpsc_find_dependency(LIBRARY CPSC_STATIC_iconv REQUIRED NAMES libiconv.a) add_library(CPSCStaticXML2 INTERFACE) # The prebuilt LLVM archive uses dllimport references. Load XML definitions # before LLD resolves those references to local symbols. target_link_libraries(CPSCStaticXML2 INTERFACE -Wl,--whole-archive "${CPSC_STATIC_xml2}" -Wl,--no-whole-archive "${CPSC_STATIC_iconv}" "${CPSC_STATIC_z}" bcrypt) get_target_property(cpsc_manifest_libs LLVMWindowsManifest INTERFACE_LINK_LIBRARIES) list(TRANSFORM cpsc_manifest_libs REPLACE "^LibXml2::LibXml2$" CPSCStaticXML2) set_property(TARGET LLVMWindowsManifest PROPERTY INTERFACE_LINK_LIBRARIES "${cpsc_manifest_libs}") endif() # Distribution Clang/LLD archives can still name the shared LLVM umbrella # library in their imported interfaces. Resolve those edges to static archives. add_library(CPSCStaticLLVM INTERFACE) foreach(cpsc_llvm_library IN LISTS LLVM_AVAILABLE_LIBS) # Standalone tools and HTTP/debuginfod clients are not driver/linker # dependencies. Keep their optional LibEdit/CURL packages optional. if(cpsc_llvm_library MATCHES "^LLVM(LineEditor|BOLT.*|Exegesis.*|OptDriver|HTTP|Debuginfod)$") continue() endif() if(TARGET ${cpsc_llvm_library}) get_target_property(cpsc_llvm_type ${cpsc_llvm_library} TYPE) if(cpsc_llvm_type STREQUAL "STATIC_LIBRARY") target_link_libraries(CPSCStaticLLVM INTERFACE ${cpsc_llvm_library}) endif() endif() endforeach() foreach(cpsc_import IN LISTS CLANG_EXPORTED_TARGETS LLD_EXPORTED_TARGETS LLVM_AVAILABLE_LIBS) if(NOT TARGET ${cpsc_import}) continue() endif() get_target_property(cpsc_interface ${cpsc_import} INTERFACE_LINK_LIBRARIES) if(cpsc_interface) list(FIND cpsc_interface LLVM cpsc_shared_llvm_index) if(NOT cpsc_shared_llvm_index EQUAL -1) list(REMOVE_ITEM cpsc_interface LLVM) if(NOT cpsc_import IN_LIST LLVM_AVAILABLE_LIBS) list(APPEND cpsc_interface CPSCStaticLLVM) endif() endif() if(CPSC_STATIC_z) list(TRANSFORM cpsc_interface REPLACE "^ZLIB::ZLIB$" "${CPSC_STATIC_z}") endif() if(CPSC_STATIC_zstd) list(TRANSFORM cpsc_interface REPLACE "^zstd::libzstd.*$" "${CPSC_STATIC_zstd}") endif() set_property(TARGET ${cpsc_import} PROPERTY INTERFACE_LINK_LIBRARIES "${cpsc_interface}") endif() endforeach()