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 | 262 +++++++++++++++++++++--------------------- 4 files changed, 156 insertions(+), 191 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b1e34b6068..abb1146f23 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 b6c4032022..37097d0c0b 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 67a2cc3274..fed89b6ef5 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 e693e54937..ba93bd8914 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.") - 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") + # 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.") - if(ZIG_STATIC_LLVM) + # 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") + + # 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) 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 37097d0c0b..d2b898a74a 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 fed89b6ef5..17e27e10f0 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 ba93bd8914..d62a154b84 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() 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 31347f8e7e..220c9760f7 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 4d375652ff..2be0839996 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@" 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 d2b898a74a..8fd1a202e1 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})