https://github.com/tamird created https://github.com/llvm/llvm-project/pull/189004
Please see details in the commit message. This diff is easier to review with whitespace suppressed (append `?w=1` to the URL). cc @vadorovsky >From 9fbc3ba69fe0c0ccc6ca8e6f39536e95eb914735 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein <[email protected]> Date: Thu, 26 Mar 2026 19:43:05 -0700 Subject: [PATCH] [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. 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 | 1 + clang/tools/libclang/CMakeLists.txt | 7 +------ llvm/CMakeLists.txt | 7 +++++++ llvm/cmake/modules/AddLLVM.cmake | 14 +++++++++++--- llvm/cmake/modules/LLVMConfig.cmake.in | 1 + llvm/docs/CMake.rst | 7 +++++++ llvm/tools/llvm-shlib/CMakeLists.txt | 7 +++---- llvm/tools/lto/CMakeLists.txt | 4 +--- llvm/tools/remarks-shlib/CMakeLists.txt | 5 +---- 9 files changed, 33 insertions(+), 20 deletions(-) diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt index b3bc56209fc9e..d9ee5e05d995c 100644 --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -724,6 +724,7 @@ if (CLANG_ENABLE_BOOTSTRAP) LLVM_VERSION_MAJOR LLVM_VERSION_MINOR LLVM_VERSION_PATCH + LLVM_VERSIONED_DYLIB_NAME_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 09322a424f488..b43111c654013 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 @@ -253,4 +249,3 @@ if(NOT LLVM_ENABLE_IDE) COMPONENT libclang-python-bindings) endif() - diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index 6dbe47600cb2f..6a351cd1ab166 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -16,6 +16,13 @@ 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) + 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 e2d0f74f26058..98fb8f311027c 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) @@ -797,8 +804,9 @@ 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) + # specifier. + if(UNIX AND (NOT APPLE OR LLVM_VERSIONED_DYLIB_NAME_ON_DARWIN) AND + NOT ARG_SONAME) set_target_properties(${name} PROPERTIES # Since 18.1.0, the ABI version is indicated by the major and minor version. @@ -820,7 +828,7 @@ function(llvm_add_library name) endif() if(ARG_SHARED) - if(NOT APPLE AND ARG_SONAME) + if((NOT APPLE OR LLVM_VERSIONED_DYLIB_NAME_ON_DARWIN) AND ARG_SONAME) get_target_property(output_name ${name} OUTPUT_NAME) if(${output_name} STREQUAL "output_name-NOTFOUND") set(output_name ${name}) 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..8a666b6afc0e2 100644 --- a/llvm/docs/CMake.rst +++ b/llvm/docs/CMake.rst @@ -808,6 +808,13 @@ 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_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/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() _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
