https://github.com/tamird updated https://github.com/llvm/llvm-project/pull/189004
>From 7e0be8d6d09635766f917408f8a9720132c13aef 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 an 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 and libLTO keep dedicated Darwin escape hatches so they 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 relevant options 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 | 3 +++ clang/tools/libclang/CMakeLists.txt | 9 +++++++++ llvm/CMakeLists.txt | 24 ++++++++++++++++++++++++ llvm/cmake/modules/AddLLVM.cmake | 2 +- llvm/cmake/modules/LLVMConfig.cmake.in | 3 +++ llvm/docs/CMake.rst | 15 +++++++++++++++ llvm/tools/lto/CMakeLists.txt | 9 +++++++++ 7 files changed, 64 insertions(+), 1 deletion(-) diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt index b3bc56209fc9e..40506fc8a1546 100644 --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -724,6 +724,9 @@ if (CLANG_ENABLE_BOOTSTRAP) LLVM_VERSION_MAJOR LLVM_VERSION_MINOR LLVM_VERSION_PATCH + LLVM_VERSIONED_DYLIB_NAME_ON_DARWIN + LLVM_UNVERSIONED_LIBCLANG_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..5fdfc474332f7 100644 --- a/clang/tools/libclang/CMakeLists.txt +++ b/clang/tools/libclang/CMakeLists.txt @@ -170,6 +170,15 @@ 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}) + if(LLVM_UNVERSIONED_LIBCLANG_ON_DARWIN) + set_property(TARGET libclang PROPERTY SOVERSION) + set_property(TARGET libclang PROPERTY VERSION) + endif() + 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 359d1591925b1..da012596cca93 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -16,6 +16,30 @@ 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-4171272082 +# claims that Xcode uses libclang for indexing and can load additional +# toolchains, so keeping libclang.dylib unversioned avoids breaking that +# compatibility by default. If this ever changes, audit Darwin libclang users +# first and verify that Xcode and downstream toolchains accept a versioned +# libclang install name before changing this default. +option(LLVM_UNVERSIONED_LIBCLANG_ON_DARWIN "If set, keep libclang's Darwin dylib identity unversioned when Darwin versioned dylib names are enabled" ON) +mark_as_advanced(LLVM_UNVERSIONED_LIBCLANG_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..23933e882ecec 100644 --- a/llvm/cmake/modules/LLVMConfig.cmake.in +++ b/llvm/cmake/modules/LLVMConfig.cmake.in @@ -17,6 +17,9 @@ 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_UNVERSIONED_LIBCLANG_ON_DARWIN @LLVM_UNVERSIONED_LIBCLANG_ON_DARWIN@) +set(LLVM_UNVERSIONED_LIBLTO_ON_DARWIN @LLVM_UNVERSIONED_LIBLTO_ON_DARWIN@) set(LLVM_COMMON_DEPENDS @LLVM_COMMON_DEPENDS@) diff --git a/llvm/docs/CMake.rst b/llvm/docs/CMake.rst index 6a70a82a6e438..7a73dd7f1e0f4 100644 --- a/llvm/docs/CMake.rst +++ b/llvm/docs/CMake.rst @@ -808,6 +808,21 @@ 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,LIBCLANG}_ON_DARWIN**:BOOL + Default to ``ON``. When ``LLVM_VERSIONED_DYLIB_NAME_ON_DARWIN`` is ``ON``, + these keep ``libLTO`` and ``libclang``'s Darwin dylib identities + unversioned. Set ``LLVM_UNVERSIONED_LIBLTO_ON_DARWIN`` to ``OFF`` to + version ``libLTO`` using its Darwin ``LTO_VERSION`` policy instead. Set + ``LLVM_UNVERSIONED_LIBCLANG_ON_DARWIN`` to ``OFF`` to version + ``libclang`` using its existing ABI 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
