https://github.com/tamird updated https://github.com/llvm/llvm-project/pull/189004
>From 407c67b8a362fe75210d500e749cbec91da81e78 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein <[email protected]> Date: Fri, 27 Mar 2026 08:45:11 -0700 Subject: [PATCH 1/3] [CMake] Group SOVERSION logic There are two blocks whose conditions are coupled; combine them to make the conditional logic less error prone. --- llvm/cmake/modules/AddLLVM.cmake | 48 +++++++++++++++----------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/llvm/cmake/modules/AddLLVM.cmake b/llvm/cmake/modules/AddLLVM.cmake index e2d0f74f26058..f528af9b2bdf3 100644 --- a/llvm/cmake/modules/AddLLVM.cmake +++ b/llvm/cmake/modules/AddLLVM.cmake @@ -796,14 +796,28 @@ function(llvm_add_library name) ) endif() - # Set SOVERSION on shared libraries that lack explicit SONAME - # specifier, on *nix systems that are not Darwin. - if(UNIX AND NOT APPLE AND NOT ARG_SONAME) - set_target_properties(${name} - PROPERTIES - # Since 18.1.0, the ABI version is indicated by the major and minor version. - SOVERSION ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}${LLVM_VERSION_SUFFIX} - VERSION ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}${LLVM_VERSION_SUFFIX}) + if(NOT APPLE) + if(ARG_SONAME) + get_target_property(output_name ${name} OUTPUT_NAME) + if(${output_name} STREQUAL "output_name-NOTFOUND") + set(output_name ${name}) + endif() + set(library_name ${output_name}-${LLVM_VERSION_MAJOR}${LLVM_VERSION_SUFFIX}) + set(api_name ${output_name}-${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}${LLVM_VERSION_SUFFIX}) + set_target_properties(${name} PROPERTIES OUTPUT_NAME ${library_name}) + if(UNIX AND NOT CYGWIN) + llvm_install_library_symlink(${api_name} ${library_name} SHARED + COMPONENT ${name}) + llvm_install_library_symlink(${output_name} ${library_name} SHARED + COMPONENT ${name}) + endif() + elseif(UNIX) + set_target_properties(${name} + PROPERTIES + # Since 18.1.0, the ABI version is indicated by the major and minor version. + SOVERSION ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}${LLVM_VERSION_SUFFIX} + VERSION ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}${LLVM_VERSION_SUFFIX}) + endif() endif() endif() @@ -819,24 +833,6 @@ function(llvm_add_library name) endif() endif() - if(ARG_SHARED) - if(NOT APPLE AND ARG_SONAME) - get_target_property(output_name ${name} OUTPUT_NAME) - if(${output_name} STREQUAL "output_name-NOTFOUND") - set(output_name ${name}) - endif() - set(library_name ${output_name}-${LLVM_VERSION_MAJOR}${LLVM_VERSION_SUFFIX}) - set(api_name ${output_name}-${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}${LLVM_VERSION_SUFFIX}) - set_target_properties(${name} PROPERTIES OUTPUT_NAME ${library_name}) - if(UNIX AND NOT CYGWIN) - llvm_install_library_symlink(${api_name} ${library_name} SHARED - COMPONENT ${name}) - llvm_install_library_symlink(${output_name} ${library_name} SHARED - COMPONENT ${name}) - endif() - endif() - endif() - if(ARG_STATIC) set(libtype PUBLIC) else() >From d40e5fffa3f417e4efd40f216d8c50c6d910f83b Mon Sep 17 00:00:00 2001 From: Tamir Duberstein <[email protected]> Date: Mon, 30 Mar 2026 09:28:32 -0400 Subject: [PATCH 2/3] [CMake] Extract Mach-O version helper Use CMake's native MACHO_COMPATIBILITY_VERSION and MACHO_CURRENT_VERSION properties rather than manually pass linker flags. These properties are available since CMake 3.17.0, released in 2020. --- clang/tools/libclang/CMakeLists.txt | 6 +----- llvm/cmake/modules/AddLLVM.cmake | 7 +++++++ llvm/tools/llvm-shlib/CMakeLists.txt | 7 +++---- llvm/tools/lto/CMakeLists.txt | 4 +--- llvm/tools/remarks-shlib/CMakeLists.txt | 5 +---- 5 files changed, 13 insertions(+), 16 deletions(-) diff --git a/clang/tools/libclang/CMakeLists.txt b/clang/tools/libclang/CMakeLists.txt index 09322a424f488..9b7ee51bb0c24 100644 --- a/clang/tools/libclang/CMakeLists.txt +++ b/clang/tools/libclang/CMakeLists.txt @@ -170,11 +170,7 @@ if(ENABLE_SHARED) # implicitly be exported from libclang. target_compile_definitions(libclang PRIVATE CLANG_BUILD_STATIC) elseif(APPLE) - set(LIBCLANG_LINK_FLAGS " -Wl,-compatibility_version -Wl,1") - set(LIBCLANG_LINK_FLAGS "${LIBCLANG_LINK_FLAGS} -Wl,-current_version -Wl,${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}") - - set_property(TARGET libclang APPEND_STRING PROPERTY - LINK_FLAGS ${LIBCLANG_LINK_FLAGS}) + llvm_set_macho_current_version(libclang ${LLVM_VERSION_MAJOR}) else() set_target_properties(libclang PROPERTIES diff --git a/llvm/cmake/modules/AddLLVM.cmake b/llvm/cmake/modules/AddLLVM.cmake index f528af9b2bdf3..7b2424bf67e7d 100644 --- a/llvm/cmake/modules/AddLLVM.cmake +++ b/llvm/cmake/modules/AddLLVM.cmake @@ -246,6 +246,13 @@ function(add_llvm_symbol_exports target_name export_file) set(LLVM_COMMON_DEPENDS ${LLVM_COMMON_DEPENDS} PARENT_SCOPE) endfunction(add_llvm_symbol_exports) +function(llvm_set_macho_current_version target major) + set_target_properties(${target} PROPERTIES + MACHO_COMPATIBILITY_VERSION 1 + MACHO_CURRENT_VERSION + ${major}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}) +endfunction() + if (NOT DEFINED LLVM_LINKER_DETECTED AND NOT WIN32) # Detect what linker we have here. if(APPLE) diff --git a/llvm/tools/llvm-shlib/CMakeLists.txt b/llvm/tools/llvm-shlib/CMakeLists.txt index 53003d90160fe..acf10b8a515b4 100644 --- a/llvm/tools/llvm-shlib/CMakeLists.txt +++ b/llvm/tools/llvm-shlib/CMakeLists.txt @@ -96,9 +96,7 @@ if(LLVM_BUILD_LLVM_DYLIB) endif() if (APPLE) - set_property(TARGET LLVM APPEND_STRING PROPERTY - LINK_FLAGS - " -compatibility_version 1 -current_version ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}") + llvm_set_macho_current_version(LLVM ${LLVM_VERSION_MAJOR}) endif() if(TARGET libLLVMExports) @@ -140,9 +138,10 @@ if(LLVM_BUILD_LLVM_C_DYLIB AND NOT MSVC) target_link_libraries(LLVM-C PUBLIC LLVM) add_dependencies(LLVM-C libLLVMCExports) + llvm_set_macho_current_version(LLVM-C ${LLVM_VERSION_MAJOR}) set_property(TARGET LLVM-C APPEND_STRING PROPERTY LINK_FLAGS - " -compatibility_version 1 -current_version ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH} -Wl,-reexport_library ${LIB_PATH}") + " -Wl,-reexport_library ${LIB_PATH}") endif() if(LLVM_BUILD_LLVM_C_DYLIB AND MSVC) diff --git a/llvm/tools/lto/CMakeLists.txt b/llvm/tools/lto/CMakeLists.txt index bc0952b1980b6..6be458dca7aac 100644 --- a/llvm/tools/lto/CMakeLists.txt +++ b/llvm/tools/lto/CMakeLists.txt @@ -45,9 +45,7 @@ if(LLVM_ENABLE_PIC) if(LLVM_LTO_VERSION_OFFSET) math(EXPR LTO_VERSION "${LLVM_VERSION_MAJOR} + ${LLVM_LTO_VERSION_OFFSET}") endif() - set_property(TARGET LTO APPEND_STRING PROPERTY - LINK_FLAGS - " -compatibility_version 1 -current_version ${LTO_VERSION}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}") + llvm_set_macho_current_version(LTO ${LTO_VERSION}) if(LLVM_USE_SANITIZER) execute_process(COMMAND ${CMAKE_CXX_COMPILER} -print-file-name=lib OUTPUT_VARIABLE clang_lib_dir) diff --git a/llvm/tools/remarks-shlib/CMakeLists.txt b/llvm/tools/remarks-shlib/CMakeLists.txt index bc4bd67e2c9ec..1b14827e68cd3 100644 --- a/llvm/tools/remarks-shlib/CMakeLists.txt +++ b/llvm/tools/remarks-shlib/CMakeLists.txt @@ -25,10 +25,7 @@ if(LLVM_ENABLE_PIC) COMPONENT Remarks) if (APPLE) - set(REMARKS_VERSION ${LLVM_VERSION_MAJOR}) - set_property(TARGET Remarks APPEND_STRING PROPERTY - LINK_FLAGS - " -compatibility_version 1 -current_version ${REMARKS_VERSION}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}") + llvm_set_macho_current_version(Remarks ${LLVM_VERSION_MAJOR}) endif() endif() >From 818612db7af4af93d1d36e11a7045403eb1cf742 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein <[email protected]> Date: Thu, 26 Mar 2026 19:43:05 -0700 Subject: [PATCH 3/3] [CMake] Version Darwin dylib identities Make Darwin shared libraries built through AddLLVM use versioned dylib names and install names by default, and add a narrow opt-out for downstream users that still depend on the legacy unversioned install name. This makes LLVM_VERSION_SUFFIX affect the Mach-O dylib identity rather than only an extra filesystem alias. Distinct LLVM builds should not advertise the same @rpath/libLLVM.dylib identity when they are not interchangeable. Implement this with VERSION/SOVERSION on Darwin too. Targets with non-default Mach-O compatibility and current versions now set the corresponding MACHO_* properties so CMake still owns the dylib name and install_name while preserving their existing embedded version policy. libclang continues to use its own existing ABI version policy for the Darwin dylib identity instead of falling back to the generic LLVM one. libLTO keeps a dedicated Darwin escape hatch so it can remain unversioned by default even when Darwin versioned dylib identities are enabled. Export the new default through LLVMConfig.cmake as well so in-tree and out-of-tree consumers see the same behavior, and pass the option through clang bootstrap so later stages do not silently flip back to the default. The current split is historical. 5e96fe90 deliberately kept Darwin libraries unversioned while changing Linux naming for ldconfig, and 6b929d5b later reintroduced VERSION/SOVERSION on Unix while explicitly excluding Darwin. 61e900b4 then wired Darwin builds to use @rpath-based install names, which made the unversioned policy part of the runtime identity instead of just a filename choice. Linux continued to evolve in 91a38462 toward a more conventional versioned libLLVM identity, but Darwin kept the older model. Keep an escape hatch with LLVM_VERSIONED_DYLIB_NAME_ON_DARWIN=OFF for the plausible compatibility case where a downstream consumer still expects the legacy unversioned @rpath/libLLVM.dylib identity. --- clang/CMakeLists.txt | 2 ++ clang/tools/libclang/CMakeLists.txt | 5 +++++ llvm/CMakeLists.txt | 15 +++++++++++++++ llvm/cmake/modules/AddLLVM.cmake | 2 +- llvm/cmake/modules/LLVMConfig.cmake.in | 1 + llvm/docs/CMake.rst | 13 +++++++++++++ llvm/tools/lto/CMakeLists.txt | 9 +++++++++ 7 files changed, 46 insertions(+), 1 deletion(-) diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt index b3bc56209fc9e..3a1dc908b6240 100644 --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -724,6 +724,8 @@ if (CLANG_ENABLE_BOOTSTRAP) LLVM_VERSION_MAJOR LLVM_VERSION_MINOR LLVM_VERSION_PATCH + LLVM_VERSIONED_DYLIB_NAME_ON_DARWIN + LLVM_UNVERSIONED_LIBLTO_ON_DARWIN CLANG_VERSION_MAJOR CLANG_VERSION_MINOR CLANG_VERSION_PATCHLEVEL diff --git a/clang/tools/libclang/CMakeLists.txt b/clang/tools/libclang/CMakeLists.txt index 9b7ee51bb0c24..30b8dffecbc38 100644 --- a/clang/tools/libclang/CMakeLists.txt +++ b/clang/tools/libclang/CMakeLists.txt @@ -170,6 +170,11 @@ if(ENABLE_SHARED) # implicitly be exported from libclang. target_compile_definitions(libclang PRIVATE CLANG_BUILD_STATIC) elseif(APPLE) + if(LLVM_VERSIONED_DYLIB_NAME_ON_DARWIN) + set_target_properties(libclang PROPERTIES + VERSION ${LIBCLANG_LIBRARY_VERSION} + ${LIBCLANG_SOVERSION_ARG}) + endif() llvm_set_macho_current_version(libclang ${LLVM_VERSION_MAJOR}) else() set_target_properties(libclang diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index 6dbe47600cb2f..82d98d40d9a14 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -16,6 +16,21 @@ if(NOT LLVM_NO_INSTALL_NAME_DIR_FOR_BUILD_TREE) set(CMAKE_BUILD_WITH_INSTALL_NAME_DIR ON) endif() +# Darwin used to keep libLLVM's install name unversioned even when +# LLVM_VERSION_SUFFIX was set. That makes distinct LLVM builds look +# interchangeable to Mach-O consumers. Keep an opt-out for downstream users +# that still depend on the legacy install name. +option(LLVM_VERSIONED_DYLIB_NAME_ON_DARWIN "If set, use versioned dylib names and install names on Darwin like other Unix platforms" ON) +mark_as_advanced(LLVM_VERSIONED_DYLIB_NAME_ON_DARWIN) +# At the time of writing (2026-04-01), +# https://github.com/llvm/llvm-project/pull/189004#issuecomment-4165730721 +# claims that the macOS linker requires libLTO.dylib to keep that stable name +# for LTO builds. If this ever changes, audit Darwin LTO users first and +# verify that ld64 and downstream toolchains accept a versioned libLTO install +# name before changing this default. +option(LLVM_UNVERSIONED_LIBLTO_ON_DARWIN "If set, keep libLTO's Darwin dylib identity unversioned when Darwin versioned dylib names are enabled" ON) +mark_as_advanced(LLVM_UNVERSIONED_LIBLTO_ON_DARWIN) + include(${LLVM_COMMON_CMAKE_UTILS}/Modules/LLVMVersion.cmake) set_directory_properties(PROPERTIES LLVM_VERSION_MAJOR "${LLVM_VERSION_MAJOR}") diff --git a/llvm/cmake/modules/AddLLVM.cmake b/llvm/cmake/modules/AddLLVM.cmake index 7b2424bf67e7d..0730ba2f529ed 100644 --- a/llvm/cmake/modules/AddLLVM.cmake +++ b/llvm/cmake/modules/AddLLVM.cmake @@ -803,7 +803,7 @@ function(llvm_add_library name) ) endif() - if(NOT APPLE) + if(NOT APPLE OR LLVM_VERSIONED_DYLIB_NAME_ON_DARWIN) if(ARG_SONAME) get_target_property(output_name ${name} OUTPUT_NAME) if(${output_name} STREQUAL "output_name-NOTFOUND") diff --git a/llvm/cmake/modules/LLVMConfig.cmake.in b/llvm/cmake/modules/LLVMConfig.cmake.in index 0a7ae97bd7549..c7793005be258 100644 --- a/llvm/cmake/modules/LLVMConfig.cmake.in +++ b/llvm/cmake/modules/LLVMConfig.cmake.in @@ -17,6 +17,7 @@ set(LLVM_BUILD_TYPE @CMAKE_BUILD_TYPE@) set(CMAKE_MSVC_RUNTIME_LIBRARY @CMAKE_MSVC_RUNTIME_LIBRARY@) set(LLVM_USE_SPLIT_DWARF @LLVM_USE_SPLIT_DWARF@) +set(LLVM_VERSIONED_DYLIB_NAME_ON_DARWIN @LLVM_VERSIONED_DYLIB_NAME_ON_DARWIN@) set(LLVM_COMMON_DEPENDS @LLVM_COMMON_DEPENDS@) diff --git a/llvm/docs/CMake.rst b/llvm/docs/CMake.rst index 6a70a82a6e438..add3614a6017c 100644 --- a/llvm/docs/CMake.rst +++ b/llvm/docs/CMake.rst @@ -808,6 +808,19 @@ its enabled sub-projects. Nearly all of these variable names begin with library ID control variables (e.g., ``CMAKE_INSTALL_NAME_DIR``) are being set to non-standard values. +**LLVM_VERSIONED_DYLIB_NAME_ON_DARWIN**:BOOL + Defaults to ``ON``. If set to ``ON``, Darwin shared libraries built through + LLVM's CMake helpers use versioned dylib filenames and install names, matching + the behavior on other Unix platforms more closely. If set to ``OFF``, Darwin + keeps the legacy unversioned dylib install name, for compatibility with + existing consumers that expect ``@rpath/libLLVM.dylib``. + +**LLVM_UNVERSIONED_LIBLTO_ON_DARWIN**:BOOL + Defaults to ``ON``. When ``LLVM_VERSIONED_DYLIB_NAME_ON_DARWIN`` is ``ON``, + this keeps ``libLTO``'s Darwin dylib identity unversioned. Set it to + ``OFF`` to version ``libLTO`` using its Darwin ``LTO_VERSION`` policy + instead. + **LLVM_OPTIMIZED_TABLEGEN**:BOOL If enabled and building a debug or assert build, the CMake build system will generate a Release build tree to build a fully optimized tablegen for use diff --git a/llvm/tools/lto/CMakeLists.txt b/llvm/tools/lto/CMakeLists.txt index 6be458dca7aac..5d13bf5e1e80d 100644 --- a/llvm/tools/lto/CMakeLists.txt +++ b/llvm/tools/lto/CMakeLists.txt @@ -45,6 +45,15 @@ if(LLVM_ENABLE_PIC) if(LLVM_LTO_VERSION_OFFSET) math(EXPR LTO_VERSION "${LLVM_VERSION_MAJOR} + ${LLVM_LTO_VERSION_OFFSET}") endif() + if(LLVM_VERSIONED_DYLIB_NAME_ON_DARWIN) + set_target_properties(LTO PROPERTIES + SOVERSION ${LTO_VERSION}.${LLVM_VERSION_MINOR}${LLVM_VERSION_SUFFIX} + VERSION ${LTO_VERSION}.${LLVM_VERSION_MINOR}${LLVM_VERSION_SUFFIX}) + if(LLVM_UNVERSIONED_LIBLTO_ON_DARWIN) + set_property(TARGET LTO PROPERTY SOVERSION) + set_property(TARGET LTO PROPERTY VERSION) + endif() + endif() llvm_set_macho_current_version(LTO ${LTO_VERSION}) if(LLVM_USE_SANITIZER) execute_process(COMMAND ${CMAKE_CXX_COMPILER} -print-file-name=lib _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
