From 3f640ef3d20db848a4d38299cb66db8a3c14b3b1 Mon Sep 17 00:00:00 2001 From: Cody Tapscott Date: Fri, 15 Jul 2022 18:51:41 -0700 Subject: [PATCH 1/4] CMake: Improve usage of `llvm-config`, esp. for consistent linking This commit reworks the LLVM/Clang/LLD discovery process for CMake. The biggest changes are that: 1. We search for LLVM from most preferred directory to least, skipping any `llvm-config` that is the wrong version, or that doesn't support the requested link mode ("static" or "shared"). 2. `ZIG_PREFER_CLANG_CPP_DYLIB` has been renamed to `ZIG_SHARED_LLVM`, to better align with `ZIG_STATIC_LLVM`. 3. We only search for LLVM in the same directory alongside LLVM. 4. LLVM's link mode is forwarded to Clang, so that we can look for the appropriate shared/static libraries. 5. We use `--link-static` when querying `--system-libs` from llvm-config, so that this will include libz and other dependencies for statically linking LLD --- CMakeLists.txt | 6 +- cmake/Findclang.cmake | 44 ++----- cmake/Findlld.cmake | 35 ++---- cmake/Findllvm.cmake | 260 +++++++++++++++++++++--------------------- 4 files changed, 155 insertions(+), 190 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b1e34b6068cffcbb1bb6e5b356bb3bf42498a24d..abb1146f23b45c5b58b3533445dbda550da5ad1f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,9 +66,9 @@ endif() message(STATUS "Configuring zig version ${ZIG_VERSION}") set(ZIG_STATIC off CACHE BOOL "Attempt to build a static zig executable (not compatible with glibc)") +set(ZIG_SHARED_LLVM off CACHE BOOL "Prefer linking against shared LLVM libraries") set(ZIG_STATIC_LLVM off CACHE BOOL "Prefer linking against static LLVM libraries") set(ZIG_STATIC_ZLIB off CACHE BOOL "Prefer linking against static zlib") -set(ZIG_PREFER_CLANG_CPP_DYLIB off CACHE BOOL "Try to link against -lclang-cpp") set(ZIG_USE_CCACHE off CACHE BOOL "Use ccache if available") if(CCACHE_PROGRAM AND ZIG_USE_CCACHE) @@ -80,6 +80,10 @@ if(ZIG_STATIC) set(ZIG_STATIC_ZLIB ON) endif() +if (ZIG_SHARED_LLVM AND ZIG_STATIC_LLVM) + message(SEND_ERROR "-DZIG_SHARED_LLVM and -DZIG_STATIC_LLVM cannot both be enabled simultaneously") +endif() + string(REGEX REPLACE "\\\\" "\\\\\\\\" ZIG_LIBC_LIB_DIR_ESCAPED "${ZIG_LIBC_LIB_DIR}") string(REGEX REPLACE "\\\\" "\\\\\\\\" ZIG_LIBC_STATIC_LIB_DIR_ESCAPED "${ZIG_LIBC_STATIC_LIB_DIR}") string(REGEX REPLACE "\\\\" "\\\\\\\\" ZIG_LIBC_INCLUDE_DIR_ESCAPED "${ZIG_LIBC_INCLUDE_DIR}") diff --git a/cmake/Findclang.cmake b/cmake/Findclang.cmake index b6c4032022d3b130fa7aca08f4e90469ded91767..37097d0c0b06bab08c6736f9c06e877768b2ea52 100644 --- a/cmake/Findclang.cmake +++ b/cmake/Findclang.cmake @@ -7,53 +7,29 @@ # CLANG_LIBRARIES # CLANG_LIBDIRS +#TODO: FIXME find_path(CLANG_INCLUDE_DIRS NAMES clang/Frontend/ASTUnit.h - PATHS - /usr/lib/llvm/14/include - /usr/lib/llvm-14/include - /usr/lib/llvm-14.0/include - /usr/local/llvm140/include - /usr/local/llvm14/include - /usr/local/opt/llvm@14/include - /opt/homebrew/opt/llvm@14/include - /mingw64/include + HINTS ${LLVM_INCLUDE_DIRS} + NO_DEFAULT_PATH # Only look for clang next to LLVM ) -if(ZIG_PREFER_CLANG_CPP_DYLIB) +if(${LLVM_LINK_MODE} STREQUAL "shared") find_library(CLANG_LIBRARIES NAMES + libclang-cpp.so.14 clang-cpp-14.0 clang-cpp140 clang-cpp NAMES_PER_DIR - PATHS - ${CLANG_LIBDIRS} - /usr/lib/llvm/14/lib - /usr/lib/llvm/14/lib64 - /usr/lib/llvm-14/lib - /usr/local/llvm140/lib - /usr/local/llvm14/lib - /usr/local/opt/llvm@14/lib - /opt/homebrew/opt/llvm@14/lib + HINTS "${LLVM_LIBDIRS}" + NO_DEFAULT_PATH # Only look for Clang next to LLVM ) -endif() - -if(NOT CLANG_LIBRARIES) +else() macro(FIND_AND_ADD_CLANG_LIB _libname_) string(TOUPPER ${_libname_} _prettylibname_) find_library(CLANG_${_prettylibname_}_LIB NAMES ${_libname_} NAMES_PER_DIR - PATHS - ${CLANG_LIBDIRS} - /usr/lib/llvm/14/lib - /usr/lib/llvm-14/lib - /usr/lib/llvm-14.0/lib - /usr/local/llvm140/lib - /usr/local/llvm14/lib - /usr/local/opt/llvm@14/lib - /opt/homebrew/opt/llvm@14/lib - /mingw64/lib - /c/msys64/mingw64/lib - c:\\msys64\\mingw64\\lib + HINTS "${LLVM_LIBDIRS}" + NO_DEFAULT_PATH # Only look for Clang next to LLVM ) if(CLANG_${_prettylibname_}_LIB) set(CLANG_LIBRARIES ${CLANG_LIBRARIES} ${CLANG_${_prettylibname_}_LIB}) diff --git a/cmake/Findlld.cmake b/cmake/Findlld.cmake index 67a2cc32743b5722a1df707e34d91a23e8775196..fed89b6ef56756a5b79222185d0bfadee8a15199 100644 --- a/cmake/Findlld.cmake +++ b/cmake/Findlld.cmake @@ -7,21 +7,13 @@ # LLD_LIBRARIES find_path(LLD_INCLUDE_DIRS NAMES lld/Common/Driver.h - PATHS - /usr/lib/llvm-14/include - /usr/local/llvm140/include - /usr/local/llvm14/include - /usr/local/opt/llvm@14/include - /opt/homebrew/opt/llvm@14/include - /mingw64/include) + HINTS ${LLVM_INCLUDE_DIRS} + NO_DEFAULT_PATH # Only look for LLD next to LLVM +) find_library(LLD_LIBRARY NAMES lld-14.0 lld140 lld NAMES_PER_DIR - PATHS - /usr/lib/llvm-14/lib - /usr/local/llvm140/lib - /usr/local/llvm14/lib - /usr/local/opt/llvm@14/lib - /opt/homebrew/opt/llvm@14/lib + HINTS ${LLVM_LIBDIRS} + NO_DEFAULT_PATH # Only look for LLD next to LLVM ) if(EXISTS ${LLD_LIBRARY}) set(LLD_LIBRARIES ${LLD_LIBRARY}) @@ -29,18 +21,11 @@ else() macro(FIND_AND_ADD_LLD_LIB _libname_) string(TOUPPER ${_libname_} _prettylibname_) find_library(LLD_${_prettylibname_}_LIB NAMES ${_libname_} NAMES_PER_DIR - PATHS - ${LLD_LIBDIRS} - /usr/lib/llvm-14/lib - /usr/local/llvm140/lib - /usr/local/llvm14/lib - /usr/local/opt/llvm@14/lib - /opt/homebrew/opt/llvm@14/lib - /mingw64/lib - /c/msys64/mingw64/lib - c:/msys64/mingw64/lib) - if(LLD_${_prettylibname_}_LIB) - set(LLD_LIBRARIES ${LLD_LIBRARIES} ${LLD_${_prettylibname_}_LIB}) + HINTS ${LLVM_LIBDIRS} + NO_DEFAULT_PATH # Only look for LLD next to LLVM + ) + if(LLD_${_prettylibname_}_LIB) + set(LLD_LIBRARIES ${LLD_LIBRARIES} ${LLD_${_prettylibname_}_LIB}) endif() endmacro(FIND_AND_ADD_LLD_LIB) diff --git a/cmake/Findllvm.cmake b/cmake/Findllvm.cmake index e693e549374c2d28910af5bf895c8232cd0c4a07..ba93bd8914cfbd39a98807ede8c0bded2747411f 100644 --- a/cmake/Findllvm.cmake +++ b/cmake/Findllvm.cmake @@ -6,175 +6,169 @@ # LLVM_INCLUDE_DIRS # LLVM_LIBRARIES # LLVM_LIBDIRS +# LLVM_LINK_MODE -find_path(LLVM_INCLUDE_DIRS NAMES llvm/IR/IRBuilder.h - PATHS - /usr/lib/llvm/14/include - /usr/lib/llvm-14/include - /usr/lib/llvm-14.0/include - /usr/lib/llvm14/include - /usr/local/llvm14/include - /usr/local/llvm140/include - /usr/local/opt/llvm@14/include - /opt/homebrew/opt/llvm@14/include - /mingw64/include -) -if(ZIG_PREFER_CLANG_CPP_DYLIB) - find_library(LLVM_LIBRARIES - NAMES - LLVM-14.0 - LLVM-14 - LLVM-140 - LLVM - NAMES_PER_DIR - PATHS - ${LLVM_LIBDIRS} - /usr/lib/llvm/14/lib - /usr/lib/llvm/14/lib64 - /usr/lib/llvm-14/lib - /usr/lib/llvm14/lib - /usr/local/llvm14/lib - /usr/local/llvm140/lib - /usr/local/opt/llvm@14/lib - /opt/homebrew/opt/llvm@14/lib - ) +if(ZIG_USE_LLVM_CONFIG) + while(1) + unset(LLVM_CONFIG_EXE CACHE) + find_program(LLVM_CONFIG_EXE + NAMES llvm-config-14 llvm-config-14.0 llvm-config140 llvm-config14 llvm-config NAMES_PER_DIR + PATHS + "/mingw64/bin" + "/c/msys64/mingw64/bin" + "c:/msys64/mingw64/bin" + "C:/Libraries/llvm-14.0.0/bin") - find_program(LLVM_CONFIG_EXE - NAMES llvm-config-14 llvm-config-14.0 llvm-config140 llvm-config14 llvm-config NAMES_PER_DIR - PATHS - "/mingw64/bin" - "/c/msys64/mingw64/bin" - "c:/msys64/mingw64/bin" - "C:/Libraries/llvm-14.0.0/bin") + if ("${LLVM_CONFIG_EXE}" STREQUAL "LLVM_CONFIG_EXE-NOTFOUND") + if (DEFINED LLVM_CONFIG_ERROR_MESSAGE) + message(FATAL_ERROR ${LLVM_CONFIG_ERROR_MESSAGE}) + else() + message(FATAL_ERROR "unable to find llvm-config") + endif() + endif() - if ("${LLVM_CONFIG_EXE}" STREQUAL "LLVM_CONFIG_EXE-NOTFOUND") - message(FATAL_ERROR "unable to find llvm-config") - endif() + # Check that this LLVM is the right version + execute_process( + COMMAND ${LLVM_CONFIG_EXE} --version + OUTPUT_VARIABLE LLVM_CONFIG_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE) - if ("${LLVM_CONFIG_EXE}" STREQUAL "LLVM_CONFIG_EXE-NOTFOUND") - message(FATAL_ERROR "unable to find llvm-config") - endif() + get_filename_component(LLVM_CONFIG_DIR "${LLVM_CONFIG_EXE}" DIRECTORY) + if("${LLVM_CONFIG_VERSION}" VERSION_LESS 14 OR "${LLVM_CONFIG_VERSION}" VERSION_EQUAL 15 OR "${LLVM_CONFIG_VERSION}" VERSION_GREATER 15) + # Save the error message, in case this is the last llvm-config we find + set(LLVM_CONFIG_ERROR_MESSAGE "expected LLVM 14.x but found ${LLVM_CONFIG_VERSION} using ${LLVM_CONFIG_EXE}") - execute_process( - COMMAND ${LLVM_CONFIG_EXE} --version - OUTPUT_VARIABLE LLVM_CONFIG_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE) + # Ignore this directory and try the search again + list(APPEND CMAKE_IGNORE_PATH "${LLVM_CONFIG_DIR}") + continue() + endif() - if("${LLVM_CONFIG_VERSION}" VERSION_LESS 14) - message(FATAL_ERROR "expected LLVM 14.x but found ${LLVM_CONFIG_VERSION} using ${LLVM_CONFIG_EXE}") - endif() - if("${LLVM_CONFIG_VERSION}" VERSION_EQUAL 15) - message(FATAL_ERROR "expected LLVM 14.x but found ${LLVM_CONFIG_VERSION} using ${LLVM_CONFIG_EXE}") - endif() - if("${LLVM_CONFIG_VERSION}" VERSION_GREATER 15) - message(FATAL_ERROR "expected LLVM 14.x but found ${LLVM_CONFIG_VERSION} using ${LLVM_CONFIG_EXE}") - endif() -elseif(ZIG_USE_LLVM_CONFIG) - find_program(LLVM_CONFIG_EXE - NAMES llvm-config-14 llvm-config-14.0 llvm-config140 llvm-config14 llvm-config NAMES_PER_DIR - PATHS - "/mingw64/bin" - "/c/msys64/mingw64/bin" - "c:/msys64/mingw64/bin" - "C:/Libraries/llvm-14.0.0/bin") + # Check that this LLVM supports linking as a shared/static library, if requested + if (ZIG_SHARED_LLVM OR ZIG_STATIC_LLVM) + if (ZIG_SHARED_LLVM) + set(STATIC_OR_SHARED_LINK "--link-shared") + elseif (ZIG_STATIC_LLVM) + set(STATIC_OR_SHARED_LINK "--link-static") + endif() - if ("${LLVM_CONFIG_EXE}" STREQUAL "LLVM_CONFIG_EXE-NOTFOUND") - message(FATAL_ERROR "unable to find llvm-config") - endif() + execute_process( + COMMAND ${LLVM_CONFIG_EXE} --libs ${STATIC_OR_SHARED_LINK} + OUTPUT_QUIET + ERROR_VARIABLE LLVM_CONFIG_ERROR + OUTPUT_STRIP_TRAILING_WHITESPACE) - if ("${LLVM_CONFIG_EXE}" STREQUAL "LLVM_CONFIG_EXE-NOTFOUND") - message(FATAL_ERROR "unable to find llvm-config") - endif() + if (LLVM_CONFIG_ERROR) + # Save the error message, in case this is the last llvm-config we find + if (ZIG_SHARED_LLVM) + set(LLVM_CONFIG_ERROR_MESSAGE "LLVM 14.x found at ${LLVM_CONFIG_EXE} does not support linking as a shared library") + else() + set(LLVM_CONFIG_ERROR_MESSAGE "LLVM 14.x found at ${LLVM_CONFIG_EXE} does not support linking as a static library") + endif() - execute_process( - COMMAND ${LLVM_CONFIG_EXE} --version - OUTPUT_VARIABLE LLVM_CONFIG_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE) + # Ignore this directory and try the search again + list(APPEND CMAKE_IGNORE_PATH "${LLVM_CONFIG_DIR}") + continue() + endif() + endif() - if("${LLVM_CONFIG_VERSION}" VERSION_LESS 14) - message(FATAL_ERROR "expected LLVM 14.x but found ${LLVM_CONFIG_VERSION} using ${LLVM_CONFIG_EXE}") - endif() - if("${LLVM_CONFIG_VERSION}" VERSION_EQUAL 15) - message(FATAL_ERROR "expected LLVM 14.x but found ${LLVM_CONFIG_VERSION} using ${LLVM_CONFIG_EXE}") - endif() - if("${LLVM_CONFIG_VERSION}" VERSION_GREATER 15) - message(FATAL_ERROR "expected LLVM 14.x but found ${LLVM_CONFIG_VERSION} using ${LLVM_CONFIG_EXE}") - endif() - - execute_process( - COMMAND ${LLVM_CONFIG_EXE} --targets-built - OUTPUT_VARIABLE LLVM_TARGETS_BUILT_SPACES - OUTPUT_STRIP_TRAILING_WHITESPACE) - string(REPLACE " " ";" LLVM_TARGETS_BUILT "${LLVM_TARGETS_BUILT_SPACES}") - function(NEED_TARGET TARGET_NAME) + execute_process( + COMMAND ${LLVM_CONFIG_EXE} --targets-built + OUTPUT_VARIABLE LLVM_TARGETS_BUILT_SPACES + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REPLACE " " ";" LLVM_TARGETS_BUILT "${LLVM_TARGETS_BUILT_SPACES}") + function(NEED_TARGET TARGET_NAME) list (FIND LLVM_TARGETS_BUILT "${TARGET_NAME}" _index) if (${_index} EQUAL -1) - message(FATAL_ERROR "LLVM (according to ${LLVM_CONFIG_EXE}) is missing target ${TARGET_NAME}. Zig requires LLVM to be built with all default targets enabled.") + # Save the error message, in case this is the last llvm-config we find + set(LLVM_CONFIG_ERROR_MESSAGE "LLVM (according to ${LLVM_CONFIG_EXE}) is missing target ${TARGET_NAME}. Zig requires LLVM to be built with all default targets enabled.") + + # Ignore this directory and try the search again + list(APPEND CMAKE_IGNORE_PATH "${LLVM_CONFIG_DIR}") + continue() endif() - endfunction(NEED_TARGET) - NEED_TARGET("AArch64") - NEED_TARGET("AMDGPU") - NEED_TARGET("ARM") - NEED_TARGET("AVR") - NEED_TARGET("BPF") - NEED_TARGET("Hexagon") - NEED_TARGET("Lanai") - NEED_TARGET("Mips") - NEED_TARGET("MSP430") - NEED_TARGET("NVPTX") - NEED_TARGET("PowerPC") - NEED_TARGET("RISCV") - NEED_TARGET("Sparc") - NEED_TARGET("SystemZ") - NEED_TARGET("VE") - NEED_TARGET("WebAssembly") - NEED_TARGET("X86") - NEED_TARGET("XCore") + endfunction(NEED_TARGET) + NEED_TARGET("AArch64") + NEED_TARGET("AMDGPU") + NEED_TARGET("ARM") + NEED_TARGET("AVR") + NEED_TARGET("BPF") + NEED_TARGET("Hexagon") + NEED_TARGET("Lanai") + NEED_TARGET("Mips") + NEED_TARGET("MSP430") + NEED_TARGET("NVPTX") + NEED_TARGET("PowerPC") + NEED_TARGET("RISCV") + NEED_TARGET("Sparc") + NEED_TARGET("SystemZ") + NEED_TARGET("VE") + NEED_TARGET("WebAssembly") + NEED_TARGET("X86") + NEED_TARGET("XCore") - if(ZIG_STATIC_LLVM) + # Got it! + break() + endwhile() + + if(ZIG_SHARED_LLVM OR ZIG_STATIC_LLVM) execute_process( - COMMAND ${LLVM_CONFIG_EXE} --libfiles --link-static + COMMAND ${LLVM_CONFIG_EXE} --libfiles ${STATIC_OR_SHARED_LINK} OUTPUT_VARIABLE LLVM_LIBRARIES_SPACES OUTPUT_STRIP_TRAILING_WHITESPACE) string(REPLACE " " ";" LLVM_LIBRARIES "${LLVM_LIBRARIES_SPACES}") execute_process( - COMMAND ${LLVM_CONFIG_EXE} --system-libs --link-static - OUTPUT_VARIABLE LLVM_SYSTEM_LIBS_SPACES - OUTPUT_STRIP_TRAILING_WHITESPACE) - string(REPLACE " " ";" LLVM_SYSTEM_LIBS "${LLVM_SYSTEM_LIBS_SPACES}") - - execute_process( - COMMAND ${LLVM_CONFIG_EXE} --libdir --link-static + COMMAND ${LLVM_CONFIG_EXE} --libdir ${STATIC_OR_SHARED_LINK} OUTPUT_VARIABLE LLVM_LIBDIRS_SPACES OUTPUT_STRIP_TRAILING_WHITESPACE) string(REPLACE " " ";" LLVM_LIBDIRS "${LLVM_LIBDIRS_SPACES}") - endif() - if(NOT LLVM_LIBRARIES) + + execute_process( + COMMAND ${LLVM_CONFIG_EXE} --shared-mode ${STATIC_OR_SHARED_LINK} + OUTPUT_VARIABLE LLVM_LINK_MODE + OUTPUT_STRIP_TRAILING_WHITESPACE) + else() execute_process( COMMAND ${LLVM_CONFIG_EXE} --libs OUTPUT_VARIABLE LLVM_LIBRARIES_SPACES OUTPUT_STRIP_TRAILING_WHITESPACE) string(REPLACE " " ";" LLVM_LIBRARIES "${LLVM_LIBRARIES_SPACES}") - execute_process( - COMMAND ${LLVM_CONFIG_EXE} --system-libs - OUTPUT_VARIABLE LLVM_SYSTEM_LIBS_SPACES - OUTPUT_STRIP_TRAILING_WHITESPACE) - string(REPLACE " " ";" LLVM_SYSTEM_LIBS "${LLVM_SYSTEM_LIBS_SPACES}") - execute_process( COMMAND ${LLVM_CONFIG_EXE} --libdir OUTPUT_VARIABLE LLVM_LIBDIRS_SPACES OUTPUT_STRIP_TRAILING_WHITESPACE) string(REPLACE " " ";" LLVM_LIBDIRS "${LLVM_LIBDIRS_SPACES}") + + execute_process( + COMMAND ${LLVM_CONFIG_EXE} --shared-mode + OUTPUT_VARIABLE LLVM_LINK_MODE + OUTPUT_STRIP_TRAILING_WHITESPACE) endif() + # We always ask for the system libs corresponding to static linking, + # since we always statically link LLD which needs these libraries + execute_process( + COMMAND ${LLVM_CONFIG_EXE} --system-libs --link-static + OUTPUT_VARIABLE LLVM_SYSTEM_LIBS_SPACES + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REPLACE " " ";" LLVM_SYSTEM_LIBS "${LLVM_SYSTEM_LIBS_SPACES}") + set(LLVM_LIBRARIES ${LLVM_LIBRARIES} ${LLVM_SYSTEM_LIBS}) + execute_process( + COMMAND ${LLVM_CONFIG_EXE} --includedir + OUTPUT_VARIABLE LLVM_INCLUDE_DIRS_SPACES + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REPLACE " " ";" LLVM_INCLUDE_DIRS "${LLVM_INCLUDE_DIRS_SPACES}") + if(NOT LLVM_LIBRARIES) - find_library(LLVM_LIBRARIES NAMES LLVM LLVM-14 LLVM-14.0 NAMES_PER_DIR) + find_library(LLVM_LIBRARIES + NAMES LLVM LLVM-14 LLVM-14.0 NAMES_PER_DIR + HINTS "${LLVM_CONFIG_DIR}/../lib" "${LLVM_CONFIG_DIR}/../lib64" "${LLVM_CONFIG_DIR}/../${CMAKE_LIBRARY_ARCHITECTURE}") + + # TODO: Make this fallthrough work endif() link_directories("${CMAKE_PREFIX_PATH}/lib") @@ -185,10 +179,13 @@ else() macro(FIND_AND_ADD_LLVM_LIB _libname_) string(TOUPPER ${_libname_} _prettylibname_) - find_library(LLVM_${_prettylibname_}_LIB NAMES ${_libname_} NAMES_PER_DIR PATHS ${LLVM_LIBDIRS}) + find_library(LLVM_${_prettylibname_}_LIB + NAMES ${_libname_} NAMES_PER_DIR) set(LLVM_LIBRARIES ${LLVM_LIBRARIES} ${LLVM_${_prettylibname_}_LIB}) endmacro(FIND_AND_ADD_LLVM_LIB) + set(LLVM_LINK_MODE "static") + # This list can be re-generated with `llvm-config --libfiles` and then # reformatting using your favorite text editor. Note we do not execute # `llvm-config` here because we are cross compiling. @@ -352,6 +349,9 @@ else() FIND_AND_ADD_LLVM_LIB(LLVMBinaryFormat) FIND_AND_ADD_LLVM_LIB(LLVMSupport) FIND_AND_ADD_LLVM_LIB(LLVMDemangle) + + get_filename_component(LLVM_LIBDIRS "${LLVM_LLVMCORE_LIB}" DIRECTORY) + find_path(LLVM_INCLUDE_DIRS NAMES llvm/IR/IRBuilder.h) endif() include(FindPackageHandleStandardArgs) -- 2.54.0 From 4113a790b0da56d7081aca52d0ca4e349d27a6a1 Mon Sep 17 00:00:00 2001 From: Cody Tapscott Date: Sat, 16 Jul 2022 08:26:45 -0700 Subject: [PATCH 2/4] CMake: Search more permissively for LLD This change relaxes the restriction added in the prior commit that LLD should be alongside LLVM. This also leaves unresolved the issue of making sure the link mode (static or shared) of LLD matches that of LLVM/Clang. That would be an unfortunate restriction, since LLD seems to be provided only as a static lib on some distros. --- cmake/Findclang.cmake | 1 - cmake/Findlld.cmake | 28 ++++++++++++++++++++++----- cmake/Findllvm.cmake | 44 ++++++++++++++++++++++++++----------------- 3 files changed, 50 insertions(+), 23 deletions(-) diff --git a/cmake/Findclang.cmake b/cmake/Findclang.cmake index 37097d0c0b06bab08c6736f9c06e877768b2ea52..d2b898a74a2c53af5281f18f101b29dda7901d54 100644 --- a/cmake/Findclang.cmake +++ b/cmake/Findclang.cmake @@ -7,7 +7,6 @@ # CLANG_LIBRARIES # CLANG_LIBDIRS -#TODO: FIXME find_path(CLANG_INCLUDE_DIRS NAMES clang/Frontend/ASTUnit.h HINTS ${LLVM_INCLUDE_DIRS} NO_DEFAULT_PATH # Only look for clang next to LLVM diff --git a/cmake/Findlld.cmake b/cmake/Findlld.cmake index fed89b6ef56756a5b79222185d0bfadee8a15199..17e27e10f0a09fcf6a84cad364ef4fc3964f2937 100644 --- a/cmake/Findlld.cmake +++ b/cmake/Findlld.cmake @@ -8,12 +8,22 @@ find_path(LLD_INCLUDE_DIRS NAMES lld/Common/Driver.h HINTS ${LLVM_INCLUDE_DIRS} - NO_DEFAULT_PATH # Only look for LLD next to LLVM -) + PATHS + /usr/lib/llvm-14/include + /usr/local/llvm140/include + /usr/local/llvm14/include + /usr/local/opt/llvm@14/include + /opt/homebrew/opt/llvm@14/include + /mingw64/include) find_library(LLD_LIBRARY NAMES lld-14.0 lld140 lld NAMES_PER_DIR HINTS ${LLVM_LIBDIRS} - NO_DEFAULT_PATH # Only look for LLD next to LLVM + PATHS + /usr/lib/llvm-14/lib + /usr/local/llvm140/lib + /usr/local/llvm14/lib + /usr/local/opt/llvm@14/lib + /opt/homebrew/opt/llvm@14/lib ) if(EXISTS ${LLD_LIBRARY}) set(LLD_LIBRARIES ${LLD_LIBRARY}) @@ -22,8 +32,16 @@ else() string(TOUPPER ${_libname_} _prettylibname_) find_library(LLD_${_prettylibname_}_LIB NAMES ${_libname_} NAMES_PER_DIR HINTS ${LLVM_LIBDIRS} - NO_DEFAULT_PATH # Only look for LLD next to LLVM - ) + PATHS + ${LLD_LIBDIRS} + /usr/lib/llvm-14/lib + /usr/local/llvm140/lib + /usr/local/llvm14/lib + /usr/local/opt/llvm@14/lib + /opt/homebrew/opt/llvm@14/lib + /mingw64/lib + /c/msys64/mingw64/lib + c:/msys64/mingw64/lib) if(LLD_${_prettylibname_}_LIB) set(LLD_LIBRARIES ${LLD_LIBRARIES} ${LLD_${_prettylibname_}_LIB}) endif() diff --git a/cmake/Findllvm.cmake b/cmake/Findllvm.cmake index ba93bd8914cfbd39a98807ede8c0bded2747411f..d62a154b842323259c56ea3a62ff1a0acf8e0340 100644 --- a/cmake/Findllvm.cmake +++ b/cmake/Findllvm.cmake @@ -56,7 +56,7 @@ if(ZIG_USE_LLVM_CONFIG) COMMAND ${LLVM_CONFIG_EXE} --libs ${STATIC_OR_SHARED_LINK} OUTPUT_QUIET ERROR_VARIABLE LLVM_CONFIG_ERROR - OUTPUT_STRIP_TRAILING_WHITESPACE) + ERROR_STRIP_TRAILING_WHITESPACE) if (LLVM_CONFIG_ERROR) # Save the error message, in case this is the last llvm-config we find @@ -124,6 +124,12 @@ if(ZIG_USE_LLVM_CONFIG) OUTPUT_STRIP_TRAILING_WHITESPACE) string(REPLACE " " ";" LLVM_LIBDIRS "${LLVM_LIBDIRS_SPACES}") + execute_process( + COMMAND ${LLVM_CONFIG_EXE} --system-libs ${STATIC_OR_SHARED_LINK} + OUTPUT_VARIABLE LLVM_SYSTEM_LIBS_SPACES + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REPLACE " " ";" LLVM_SYSTEM_LIBS "${LLVM_SYSTEM_LIBS_SPACES}") + execute_process( COMMAND ${LLVM_CONFIG_EXE} --shared-mode ${STATIC_OR_SHARED_LINK} OUTPUT_VARIABLE LLVM_LINK_MODE @@ -141,21 +147,33 @@ if(ZIG_USE_LLVM_CONFIG) OUTPUT_STRIP_TRAILING_WHITESPACE) string(REPLACE " " ";" LLVM_LIBDIRS "${LLVM_LIBDIRS_SPACES}") + execute_process( + COMMAND ${LLVM_CONFIG_EXE} --system-libs + OUTPUT_VARIABLE LLVM_SYSTEM_LIBS_SPACES + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REPLACE " " ";" LLVM_SYSTEM_LIBS "${LLVM_SYSTEM_LIBS_SPACES}") + execute_process( COMMAND ${LLVM_CONFIG_EXE} --shared-mode OUTPUT_VARIABLE LLVM_LINK_MODE OUTPUT_STRIP_TRAILING_WHITESPACE) endif() - # We always ask for the system libs corresponding to static linking, - # since we always statically link LLD which needs these libraries - execute_process( - COMMAND ${LLVM_CONFIG_EXE} --system-libs --link-static - OUTPUT_VARIABLE LLVM_SYSTEM_LIBS_SPACES - OUTPUT_STRIP_TRAILING_WHITESPACE) - string(REPLACE " " ";" LLVM_SYSTEM_LIBS "${LLVM_SYSTEM_LIBS_SPACES}") + if (${LLVM_LINK_MODE} STREQUAL "shared") + # We always ask for the system libs corresponding to static linking, + # since on some distros LLD is only available as a static library + # and we need these libraries to link it successfully + execute_process( + COMMAND ${LLVM_CONFIG_EXE} --system-libs --link-static + OUTPUT_VARIABLE LLVM_STATIC_SYSTEM_LIBS_SPACES + ERROR_QUIET # Some installations have no static libs, we just ignore the failure + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REPLACE " " ";" LLVM_STATIC_SYSTEM_LIBS "${LLVM_STATIC_SYSTEM_LIBS_SPACES}") - set(LLVM_LIBRARIES ${LLVM_LIBRARIES} ${LLVM_SYSTEM_LIBS}) + set(LLVM_LIBRARIES ${LLVM_LIBRARIES} ${LLVM_SYSTEM_LIBS} ${LLVM_STATIC_SYSTEM_LIBS}) + else() + set(LLVM_LIBRARIES ${LLVM_LIBRARIES} ${LLVM_SYSTEM_LIBS}) + endif() execute_process( COMMAND ${LLVM_CONFIG_EXE} --includedir @@ -163,14 +181,6 @@ if(ZIG_USE_LLVM_CONFIG) OUTPUT_STRIP_TRAILING_WHITESPACE) string(REPLACE " " ";" LLVM_INCLUDE_DIRS "${LLVM_INCLUDE_DIRS_SPACES}") - if(NOT LLVM_LIBRARIES) - find_library(LLVM_LIBRARIES - NAMES LLVM LLVM-14 LLVM-14.0 NAMES_PER_DIR - HINTS "${LLVM_CONFIG_DIR}/../lib" "${LLVM_CONFIG_DIR}/../lib64" "${LLVM_CONFIG_DIR}/../${CMAKE_LIBRARY_ARCHITECTURE}") - - # TODO: Make this fallthrough work - endif() - link_directories("${CMAKE_PREFIX_PATH}/lib") link_directories("${LLVM_LIBDIRS}") else() -- 2.54.0 From 5337934bcd174987e813e192cb5ef173c13eff37 Mon Sep 17 00:00:00 2001 From: Cody Tapscott Date: Sat, 23 Jul 2022 09:02:51 -0700 Subject: [PATCH 3/4] CMake: Add ZIG_LLVM_LINK_MODE to config.h This is currently unused, but it will be needed soon so that we can avoid linking static libc++ if LLVM/Clang is configured as a shared library. --- build.zig | 9 +++++++++ src/stage1/config.h.in | 1 + 2 files changed, 10 insertions(+) diff --git a/build.zig b/build.zig index 31347f8e7edfad452ee1b0f09785f16a3a82145f..220c9760f7b9c0e51228160e9d8190e9e6fc2285 100644 --- a/build.zig +++ b/build.zig @@ -660,6 +660,7 @@ fn addCMakeLibraryList(exe: *std.build.LibExeObjStep, list: []const u8) void { } const CMakeConfig = struct { + llvm_linkage: std.build.LibExeObjStep.Linkage, cmake_binary_dir: []const u8, cmake_prefix_path: []const u8, cxx_compiler: []const u8, @@ -698,6 +699,7 @@ fn findAndParseConfigH(b: *Builder, config_h_path_option: ?[]const u8) ?CMakeCon }; var ctx: CMakeConfig = .{ + .llvm_linkage = undefined, .cmake_binary_dir = undefined, .cmake_prefix_path = undefined, .cxx_compiler = undefined, @@ -741,6 +743,7 @@ fn findAndParseConfigH(b: *Builder, config_h_path_option: ?[]const u8) ?CMakeCon .prefix = "#define ZIG_DIA_GUIDS_LIB ", .field = "dia_guids_lib", }, + // .prefix = ZIG_LLVM_LINK_MODE parsed manually below }; var lines_it = mem.tokenize(u8, config_h_text, "\r\n"); @@ -753,6 +756,12 @@ fn findAndParseConfigH(b: *Builder, config_h_path_option: ?[]const u8) ?CMakeCon @field(ctx, mapping.field) = toNativePathSep(b, quoted); } } + if (mem.startsWith(u8, line, "#define ZIG_LLVM_LINK_MODE ")) { + var it = mem.split(u8, line, "\""); + _ = it.next().?; // skip the stuff before the quote + const quoted = it.next().?; // the stuff inside the quote + ctx.llvm_linkage = if (mem.eql(u8, quoted, "shared")) .dynamic else .static; + } } return ctx; } diff --git a/src/stage1/config.h.in b/src/stage1/config.h.in index 4d375652ff5d91c481db4cab6e94255a58845ef9..2be083999654ecf8a620d1048a2dddf318e7ca8f 100644 --- a/src/stage1/config.h.in +++ b/src/stage1/config.h.in @@ -16,6 +16,7 @@ // Used by build.zig for communicating build information to self hosted build. #define ZIG_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@" +#define ZIG_LLVM_LINK_MODE "@LLVM_LINK_MODE@" #define ZIG_CMAKE_PREFIX_PATH "@CMAKE_PREFIX_PATH@" #define ZIG_CXX_COMPILER "@CMAKE_CXX_COMPILER@" #define ZIG_LLD_INCLUDE_PATH "@LLD_INCLUDE_DIRS@" -- 2.54.0 From abc1ae538fee14af12bb5ffd35024d96da861961 Mon Sep 17 00:00:00 2001 From: Cody Tapscott Date: Mon, 25 Jul 2022 10:29:38 -0700 Subject: [PATCH 4/4] CMake: Search for Clang in CMAKE_LIBRARY_PATH, CMAKE_PREFIX_PATH, and CMAKE_FRAMEWORK_PATH On some systems (esp. systems that use unique hashed file-paths for library-versions like Nix), we can't expect LLVM and Clang to share lib/bin directories. The best we can do is find the matching clang libraries in the CMAKE_LIBRARY_PATH provided by the environment --- cmake/Findclang.cmake | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/cmake/Findclang.cmake b/cmake/Findclang.cmake index d2b898a74a2c53af5281f18f101b29dda7901d54..8fd1a202e14d0dc602a7d1166600d17200382957 100644 --- a/cmake/Findclang.cmake +++ b/cmake/Findclang.cmake @@ -9,7 +9,9 @@ find_path(CLANG_INCLUDE_DIRS NAMES clang/Frontend/ASTUnit.h HINTS ${LLVM_INCLUDE_DIRS} - NO_DEFAULT_PATH # Only look for clang next to LLVM + # Only look for Clang next to LLVM or in { CMAKE_PREFIX_PATH, CMAKE_LIBRARY_PATH, CMAKE_FRAMEWORK_PATH } + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH ) if(${LLVM_LINK_MODE} STREQUAL "shared") @@ -21,14 +23,18 @@ if(${LLVM_LINK_MODE} STREQUAL "shared") clang-cpp NAMES_PER_DIR HINTS "${LLVM_LIBDIRS}" - NO_DEFAULT_PATH # Only look for Clang next to LLVM + # Only look for Clang next to LLVM or in { CMAKE_PREFIX_PATH, CMAKE_LIBRARY_PATH, CMAKE_FRAMEWORK_PATH } + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH ) else() macro(FIND_AND_ADD_CLANG_LIB _libname_) string(TOUPPER ${_libname_} _prettylibname_) find_library(CLANG_${_prettylibname_}_LIB NAMES ${_libname_} NAMES_PER_DIR HINTS "${LLVM_LIBDIRS}" - NO_DEFAULT_PATH # Only look for Clang next to LLVM + # Only look for Clang next to LLVM or in { CMAKE_PREFIX_PATH, CMAKE_LIBRARY_PATH, CMAKE_FRAMEWORK_PATH } + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH ) if(CLANG_${_prettylibname_}_LIB) set(CLANG_LIBRARIES ${CLANG_LIBRARIES} ${CLANG_${_prettylibname_}_LIB}) -- 2.54.0