From 054135f26d246cd5ef6a73f1bf5d6a9968ba54ad Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Tue, 2 Dec 2025 17:54:56 +0800 Subject: [PATCH 1/2] Fix linking of static archives with GCC with LTO Currently if you try to build llvm-test-suite with GCC and LTO, the MicroBenchmarks will fail to link. Digging through the logs you'll find a warning earlier on: libbenchmark.a(benchmark.cc.o): plugin needed to handle lto object This is caused by CMake creating the library with ar and not gcc-ar, even though CMake finds gcc-ar: // A wrapper around 'ar' adding the appropriate '--plugin' option for the GCC compiler CMAKE_C_COMPILER_AR:FILEPATH=/home/igalia/luke/riscv-lnt/gcc-install/bin/riscv64-linux-gnu-gcc-ar The fix is to set CMAKE_INTERPROCEDURAL_OPTIMIZATION which gets CMake to properly use the right ar/ranlib/etc. when using LTO. We can set this in the cmake/caches/*LTO.cmake presets instead of manually adding the -flto flag which fixes the link error. Unfortunately, CMake also sets -flto=thin for whatever reason on Clang. There's no way to configure it to do fat LTO, and there's a ton of open issues about this upstream: https://gitlab.kitware.com/cmake/cmake/-/issues/23136 It seems like the best way to workaround this is to just append -flto=auto in CXXFLAGS/LDFLAGS for Clang. --- CMakeLists.txt | 16 ++++++++++++++-- cmake/caches/OfastLTO.cmake | 3 ++- cmake/caches/OsLTO.cmake | 3 ++- cmake/caches/ReleaseLTO.cmake | 3 ++- cmake/caches/ReleaseThinLTO.cmake | 4 +++- 5 files changed, 23 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 21b997134b..45f73ee706 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -337,12 +337,24 @@ if(TEST_SUITE_COLLECT_STATS) list(APPEND CFLAGS -save-stats=obj) list(APPEND CXXFLAGS -save-stats=obj) # Collect stats for LTO step too. - if (${CMAKE_C_FLAGS} MATCHES ".*-flto.*" AND - ${CMAKE_CXX_FLAGS} MATCHES ".*-flto.*") + if ((${CMAKE_C_FLAGS} MATCHES ".*-flto.*" AND + ${CMAKE_CXX_FLAGS} MATCHES ".*-flto.*") OR + CMAKE_INTERPROCEDURAL_OPTIMIZATION) list(APPEND LDFLAGS -save-stats=obj) endif() endif() +# When CMAKE_INTERPROCEDURAL_OPTIMIZATION is set, CMake implicitly uses +# -flto=thin on Clang, but -flto=auto on GCC. Append -flto=auto on Clang so they +# are equivalent. This needs to be done in CXXFLAGS/LDFLAGS so it appears after +# -flto=thin and overrides it. +# https://gitlab.kitware.com/cmake/cmake/-/blob/b65b7687cc541265f894567174a4c0ee65ea03d6/Modules/Compiler/Clang.cmake#L78-82 +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_INTERPROCEDURAL_OPTIMIZATION + AND NOT TEST_SUITE_THIN_LTO) + list(APPEND CXXFLAGS -flto=auto) + list(APPEND LDFLAGS -flto=auto) +endif() + # Detect and include subdirectories # This allows to: Place additional test-suites into the toplevel test-suite # directory where they will be picked up automatically. Alternatively you may diff --git a/cmake/caches/OfastLTO.cmake b/cmake/caches/OfastLTO.cmake index c24eb394a4..644e9ddd17 100644 --- a/cmake/caches/OfastLTO.cmake +++ b/cmake/caches/OfastLTO.cmake @@ -1,4 +1,5 @@ -set(OPTFLAGS "${OPTFLAGS} -Ofast -flto") +set(OPTFLAGS "${OPTFLAGS} -Ofast") set(CMAKE_C_FLAGS_RELEASE "${OPTFLAGS}" CACHE STRING "") set(CMAKE_CXX_FLAGS_RELEASE "${OPTFLAGS}" CACHE STRING "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") +set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON CACHE BOOL "") diff --git a/cmake/caches/OsLTO.cmake b/cmake/caches/OsLTO.cmake index 469c3f34a2..5c5d6c42f4 100644 --- a/cmake/caches/OsLTO.cmake +++ b/cmake/caches/OsLTO.cmake @@ -1,5 +1,6 @@ -set(OPTFLAGS "${OPTFLAGS} -Os -flto") +set(OPTFLAGS "${OPTFLAGS} -Os") set(CMAKE_C_FLAGS_RELEASE "${OPTFLAGS}" CACHE STRING "") set(CMAKE_CXX_FLAGS_RELEASE "${OPTFLAGS}" CACHE STRING "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") +set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON CACHE BOOL "") diff --git a/cmake/caches/ReleaseLTO.cmake b/cmake/caches/ReleaseLTO.cmake index 0adf468cba..676b33ae38 100644 --- a/cmake/caches/ReleaseLTO.cmake +++ b/cmake/caches/ReleaseLTO.cmake @@ -1,5 +1,5 @@ # Aggressive settings to produce fast code. -set(OPTFLAGS "${OPTFLAGS} -O3 -fomit-frame-pointer -flto -DNDEBUG") +set(OPTFLAGS "${OPTFLAGS} -O3 -fomit-frame-pointer -DNDEBUG") if(APPLE) set(OPTFLAGS "${OPTFLAGS} -mdynamic-no-pic") endif() @@ -7,3 +7,4 @@ endif() set(CMAKE_C_FLAGS_RELEASE "${OPTFLAGS}" CACHE STRING "") set(CMAKE_CXX_FLAGS_RELEASE "${OPTFLAGS}" CACHE STRING "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") +set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON CACHE BOOL "") diff --git a/cmake/caches/ReleaseThinLTO.cmake b/cmake/caches/ReleaseThinLTO.cmake index f8dc62f2e2..3f7ff52269 100644 --- a/cmake/caches/ReleaseThinLTO.cmake +++ b/cmake/caches/ReleaseThinLTO.cmake @@ -1,4 +1,4 @@ -set(OPTFLAGS "${OPTFLAGS} -O3 -fomit-frame-pointer -flto=thin -DNDEBUG") +set(OPTFLAGS "${OPTFLAGS} -O3 -fomit-frame-pointer -DNDEBUG") if(APPLE) set(OPTFLAGS "${OPTFLAGS} -mdynamic-no-pic") endif() @@ -6,3 +6,5 @@ endif() set(CMAKE_C_FLAGS_RELEASE "${OPTFLAGS}" CACHE STRING "") set(CMAKE_CXX_FLAGS_RELEASE "${OPTFLAGS}" CACHE STRING "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") +set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON CACHE BOOL "") +set(TEST_SUITE_THIN_LTO ON CACHE BOOL "") From a21aee06643a9a3d1c8f2476101a489f4df65c5b Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Wed, 3 Dec 2025 01:08:46 +0800 Subject: [PATCH 2/2] Set CFLAGS --- CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 45f73ee706..b0e41612c2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -346,11 +346,12 @@ endif() # When CMAKE_INTERPROCEDURAL_OPTIMIZATION is set, CMake implicitly uses # -flto=thin on Clang, but -flto=auto on GCC. Append -flto=auto on Clang so they -# are equivalent. This needs to be done in CXXFLAGS/LDFLAGS so it appears after -# -flto=thin and overrides it. +# are equivalent. This needs to be done in CFLAGS/CXXFLAGS/LDFLAGS so it appears +# after -flto=thin and overrides it. # https://gitlab.kitware.com/cmake/cmake/-/blob/b65b7687cc541265f894567174a4c0ee65ea03d6/Modules/Compiler/Clang.cmake#L78-82 if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_INTERPROCEDURAL_OPTIMIZATION AND NOT TEST_SUITE_THIN_LTO) + list(APPEND CFLAGS -flto=auto) list(APPEND CXXFLAGS -flto=auto) list(APPEND LDFLAGS -flto=auto) endif()