From 3a4b94c7576555c01df681760d640b6fae195a37 Mon Sep 17 00:00:00 2001 From: Daniel Scharrer <~@ds.me> Date: Thu, 2 Jan 2025 00:28:28 +0100 Subject: [PATCH] CMake: Use LLD if available --- CMakeLists.txt | 6 ++++- README.md | 2 ++ cmake/BuildType.cmake | 53 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 58 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b554ead..54250b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,12 +50,16 @@ option(DEBUG_EXTRA "Expensive debug options" OFF) option(SET_WARNING_FLAGS "Adjust compiler warning flags" ON) option(SET_NOISY_WARNING_FLAGS "Enable noisy compiler warnings" OFF) option(SET_OPTIMIZATION_FLAGS "Adjust compiler optimization flags" ON) -suboption(USE_LDGOLD "Use the Gold linker" BOOL ${SET_OPTIMIZATION_FLAGS}) set(default_FASTLINK OFF) if(DEVELOPER OR CONTINUOUS_INTEGRATION) set(default_FASTLINK ON) endif() suboption(FASTLINK "Optimize (incremental) linking speed" BOOL ${default_FASTLINK}) +set(default_USE_LD "default") +if(SET_OPTIMIZATION_FLAGS OR FASTLINK) + set(default_USE_LD "best") +endif() +suboption(USE_LD "The linker to use (mold, lld, gold, bfd, best or default)" STRING "${default_USE_LD}") set(default_USE_LTO OFF) if(SET_OPTIMIZATION_FLAGS AND NOT FASTLINK) set(default_USE_LTO ON) diff --git a/README.md b/README.md index 6a297b7..3a5e826 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,7 @@ The default build settings are tuned for users - if you plan to make changes to | `DEVELOPER` | `OFF` | Enable build options suitable for developers⁵. | `FASTLINK` | `OFF`⁶ | Optimize for link speed. | `USE_LTO` | `ON`² | Use link-time code generation. +| `USE_LD` | `best`⁸ | Linker to use - `default`, `mold`, `lld`, `gold`, `bfd` or `best` | `BUILD_TESTS` | `OFF`⁶ | Build unit tests that can be run using `make check` | `RUN_TESTS` | `OFF`⁷ | Automatically run tests | `RUN_TARGET` | (none) | Wrapper to run binaries produced in the build process @@ -78,6 +79,7 @@ The default build settings are tuned for users - if you plan to make changes to 5. Currently this and enables `DEBUG`, `BUILD_TESTS`, `RUN_TESTS` and `FASTLINK` for faster incremental builds and improved debug output, unless those options have been explicitly specified by the user. 6. Enabled automatically if `DEVELOPER` is enabled. 7. Enabled automatically if `DEVELOPER` is enabled unless cross-compiling without `RUN_TARGET` set +8. Disabled automatically (set to `default`) if both `SET_OPTIMIZATION_FLAGS` and `FASTLINK` are disabled. `best` will select the most suited linker based on availability and other settings such as `USE_LTO`. Install options: diff --git a/cmake/BuildType.cmake b/cmake/BuildType.cmake index ee54dd2..a4e9af9 100644 --- a/cmake/BuildType.cmake +++ b/cmake/BuildType.cmake @@ -130,8 +130,52 @@ if(MSVC) else(MSVC) - if(USE_LDGOLD) + set(linker_used) + if(NOT linker_used AND USE_LD STREQUAL "mold") + # Does not really support LTO yet + add_ldflag("-fuse-ld=mold") + if(FLAG_FOUND) + set(linker_used "mold") + elseif(STRICT_USE AND NOT USE_LD STREQUAL "best") + message(FATAL_ERROR "Requested linker is not available") + endif() + endif() + if(NOT linker_used AND (USE_LD STREQUAL "lld" OR + (USE_LD STREQUAL "best" AND (NOT USE_LTO OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")))) + # Only supports LTO with LLVM-based compilers and old versions are unstable + if(USE_LD STREQUAL "best") + execute_process(COMMAND ${CMAKE_CXX_COMPILER} "-fuse-ld=lld" "-Wl,-version" + OUTPUT_VARIABLE _LLD_Version ERROR_QUIET) + endif() + if(USE_LD STREQUAL "best" AND _LLD_Version MATCHES "LLD [0-8]\\.[0-9\\.]*") + message(STATUS "Not using ancient ${CMAKE_MATCH_0}") + elseif(USE_LD STREQUAL "best" AND CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND + CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9) + message(STATUS "Not using ancient Clang ${CMAKE_CXX_COMPILER_VERSION}") + else() + add_ldflag("-fuse-ld=lld") + if(FLAG_FOUND) + set(linker_used "lld") + elseif(STRICT_USE AND NOT USE_LD STREQUAL "best") + message(FATAL_ERROR "Requested linker is not available") + endif() + endif() + endif() + if(NOT linker_used AND (USE_LD STREQUAL "gold" OR USE_LD STREQUAL "best")) add_ldflag("-fuse-ld=gold") + if(FLAG_FOUND) + set(linker_used "gold") + elseif(STRICT_USE AND NOT USE_LD STREQUAL "best") + message(FATAL_ERROR "Requested linker is not available") + endif() + endif() + if(NOT linker_used AND (USE_LD STREQUAL "bfd")) + add_ldflag("-fuse-ld=bfd") + if(FLAG_FOUND) + set(linker_used "bfd") + elseif(STRICT_USE AND NOT USE_LD STREQUAL "best") + message(FATAL_ERROR "Requested linker is not available") + endif() endif() if(USE_LTO) @@ -146,7 +190,12 @@ else(MSVC) if(FASTLINK) # Optimize for link speed in developer builds - add_cxxflag("-gsplit-dwarf") + if(linker_used STREQUAL "mold" OR linker_used STREQUAL "lld") + # mold and lld are fast enough without -gsplit-dwarf that we don't need to deal with its issues + else() + add_cxxflag("-gsplit-dwarf") + add_cxxflag("-gdwarf-4") # -gsplit-dwarf is broken with DWARF 5 + endif() elseif(SET_OPTIMIZATION_FLAGS)