https://github.com/ceph/ceph/pull/69711

From e55244161992640e2e4a487b1cbaa702f2cebf43 Mon Sep 17 00:00:00 2001
From: Ronen Friedman <rfriedma@redhat.com>
Date: Sun, 28 Jun 2026 14:42:07 +0000
Subject: [PATCH] build: add Mold linker compatibility

Mold handles several linker features differently from ld.bfd:

- --exclude-libs,ALL hides .symver-aliased symbols (e.g. rados_*)
  even when the version script lists them as global. Detect Mold
  (via USING_MOLD_LINKER) and disable --exclude-libs; version
  scripts already control symbol visibility.

- Duplicate symbols across static archives are treated as errors.
  Merge crimson-alien-common into crimson-alienstore as a single
  archive. For crimson-osd, link crimson-alienstore before
  crimson-common with --allow-multiple-definition so the alien
  thread's non-crimson definitions win (Mold picks first definition).

- Python/Cython extension builds (via Distutils.cmake) invoked the
  system default linker. Pass -fuse-ld= via MOLD_FUSE_LD_FLAG so
  extensions link with the configured linker.

- Add rados_* and _rados_* to librados.map global section for Mold
  compatibility with .symver aliases.

Co-authored-by: Mark Kogan <mkogan@redhat.com>
Signed-off-by: Ronen Friedman <rfriedma@redhat.com>

#diff --git a/cmake/modules/CephChecks.cmake b/cmake/modules/CephChecks.cmake
#index 4da4dfad5bf..9506a4db220 100644
#--- a/cmake/modules/CephChecks.cmake
#+++ b/cmake/modules/CephChecks.cmake
#@@ -202,3 +202,12 @@ try_compile(HAVE_LINK_EXCLUDE_LIBS
#   ${CMAKE_CURRENT_BINARY_DIR}
#   SOURCES ${CMAKE_CURRENT_LIST_DIR}/CephCheck_link.c
#   LINK_LIBRARIES "-Wl,--exclude-libs,ALL")
#+
#+# Mold linker applies --exclude-libs after version script processing,
#+# which hides .symver-aliased symbols (e.g. rados_*) even when the
#+# version script lists them as global.  Disable --exclude-libs for Mold;
#+# version scripts already control symbol visibility.
#+if(HAVE_LINK_EXCLUDE_LIBS AND USING_MOLD_LINKER)
#+  message(STATUS "Mold linker -- disabling --exclude-libs (incompatible with .symver)")
#+  set(HAVE_LINK_EXCLUDE_LIBS FALSE CACHE INTERNAL "" FORCE)
#+endif()
#diff --git a/cmake/modules/Distutils.cmake b/cmake/modules/Distutils.cmake
#index 37b2efa7457..9d5dd33fcef 100644
#--- a/cmake/modules/Distutils.cmake
#+++ b/cmake/modules/Distutils.cmake
#@@ -72,7 +72,11 @@ function(distutils_add_cython_module target name src)
#   list(APPEND PY_CPPFLAGS -D'__Pyx_check_single_interpreter\(ARG\)=ARG\#\#0')
#   set(PY_CC ${compiler_launcher} ${CMAKE_C_COMPILER} ${c_compiler_arg1})
#   set(PY_CXX ${compiler_launcher} ${CMAKE_CXX_COMPILER} ${cxx_compiler_arg1})
#-  set(PY_LDSHARED ${link_launcher} ${CMAKE_C_COMPILER} ${c_compiler_arg1} "-shared")
#+  if(USING_MOLD_LINKER)
#+    set(PY_LDSHARED ${link_launcher} ${CMAKE_C_COMPILER} ${c_compiler_arg1} "-shared" "${MOLD_FUSE_LD_FLAG}")
#+  else()
#+    set(PY_LDSHARED ${link_launcher} ${CMAKE_C_COMPILER} ${c_compiler_arg1} "-shared")
#+  endif()
#   string(REPLACE " " ";" PY_LDFLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
#   list(APPEND PY_LDFLAGS -L${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
# 
#@@ -117,7 +121,11 @@ function(distutils_install_cython_module name)
#   get_property(compiler_launcher GLOBAL PROPERTY RULE_LAUNCH_COMPILE)
#   get_property(link_launcher GLOBAL PROPERTY RULE_LAUNCH_LINK)
#   set(PY_CC "${compiler_launcher} ${CMAKE_C_COMPILER}")
#-  set(PY_LDSHARED "${link_launcher} ${CMAKE_C_COMPILER} -shared")
#+  if(USING_MOLD_LINKER)
#+    set(PY_LDSHARED "${link_launcher} ${CMAKE_C_COMPILER} -shared ${MOLD_FUSE_LD_FLAG}")
#+  else()
#+    set(PY_LDSHARED "${link_launcher} ${CMAKE_C_COMPILER} -shared")
#+  endif()
#   set(PY_LDFLAGS "${CMAKE_SHARED_LINKER_FLAGS} -L${CMAKE_LIBRARY_OUTPUT_DIRECTORY}")
#   cmake_parse_arguments(DU "DISABLE_VTA" "" "" ${ARGN})
#   if(DU_DISABLE_VTA AND HAS_VTA)
#diff --git a/src/crimson/os/alienstore/CMakeLists.txt b/src/crimson/os/alienstore/CMakeLists.txt
#index 6a227cfdb87..0c87e1505e5 100644
#--- a/src/crimson/os/alienstore/CMakeLists.txt
#+++ b/src/crimson/os/alienstore/CMakeLists.txt
#@@ -30,11 +30,6 @@ if(WITH_CEPH_DEBUG_MUTEX)
#     ${PROJECT_SOURCE_DIR}/src/common/condition_variable_debug.cc
#     ${PROJECT_SOURCE_DIR}/src/common/shared_mutex_debug.cc)
# endif()
#-add_library(crimson-alien-common STATIC
#-  ${crimson_alien_common_srcs})
#-if(WITH_BREAKPAD)
#-  target_link_libraries(crimson-alien-common Breakpad::client)
#-endif()
# 
# set(alien_store_srcs
#   alien_store.cc
#@@ -65,20 +60,32 @@ set(alien_store_srcs
#   ${PROJECT_SOURCE_DIR}/src/os/bluestore/OnodeScan.cc
#   ${PROJECT_SOURCE_DIR}/src/os/memstore/MemStore.cc)
# 
#+# Merge alienstore + alien-common into a single archive.  The common sources
#+# are compiled without WITH_CRIMSON and duplicate symbols in crimson-common.
#+# ld.bfd resolves these by archive order; Mold treats them as errors.
#+# After building, localize the duplicate symbols so they resolve internally
#+# within this archive (for the alien/bluestore thread) while crimson-osd's
#+# own references resolve from crimson-common (for seastar threads).
# add_library(crimson-alienstore STATIC
#-  ${alien_store_srcs})
#+  ${alien_store_srcs}
#+  ${crimson_alien_common_srcs})
# if(WITH_LTTNG)
#   add_dependencies(crimson-alienstore bluestore-tp)
# endif()
#+if(WITH_BREAKPAD)
#+  target_link_libraries(crimson-alienstore PRIVATE Breakpad::client)
#+endif()
# 
#-# For crimson-alienstore WITH_CRIMSON is not defined
# target_link_libraries(crimson-alienstore
#   PRIVATE
#     seastar
#     ${FMT_LIB}
#     kv
#     heap_profiler
#-    crimson-alien-common
#     ${BLKID_LIBRARIES}
#     ${UDEV_LIBRARIES}
#     blk)
#+
#+# Mold duplicate-symbol handling is done at the crimson-osd link step
#+# (see src/crimson/osd/CMakeLists.txt) by ordering crimson-alienstore
#+# before crimson-common with --allow-multiple-definition.
#diff --git a/src/crimson/osd/CMakeLists.txt b/src/crimson/osd/CMakeLists.txt
#index 7e06215a6eb..a15adf049cc 100644
#--- a/src/crimson/osd/CMakeLists.txt
#+++ b/src/crimson/osd/CMakeLists.txt
#@@ -70,16 +70,36 @@ if(HAS_VTA)
#   set_source_files_properties(main.cc
#     PROPERTIES COMPILE_FLAGS -fno-var-tracking-assignments)
# endif()
#-target_link_libraries(crimson-osd
#-  legacy-option-headers
#-  crimson-admin
#-  crimson-common
#-  crimson-os
#-  crimson
#-  erasure_code
#-  ${FMT_LIB}
#-  Boost::MPL
#-  dmclock::dmclock)
#+if(USING_MOLD_LINKER AND WITH_BLUESTORE)
#+  # With Mold, duplicate symbols between crimson-alienstore and crimson-common
#+  # must be resolved in favor of crimson-alienstore (compiled without
#+  # WITH_CRIMSON) so the alien thread uses the classic code paths.
#+  # Link crimson-alienstore BEFORE crimson-common so its definitions win
#+  # with --allow-multiple-definition (Mold picks first definition).
#+  target_link_libraries(crimson-osd
#+    legacy-option-headers
#+    crimson-admin
#+    crimson-alienstore
#+    crimson-common
#+    crimson-os
#+    crimson
#+    erasure_code
#+    ${FMT_LIB}
#+    Boost::MPL
#+    dmclock::dmclock)
#+  target_link_options(crimson-osd PRIVATE -Wl,--allow-multiple-definition)
#+else()
#+  target_link_libraries(crimson-osd
#+    legacy-option-headers
#+    crimson-admin
#+    crimson-common
#+    crimson-os
#+    crimson
#+    erasure_code
#+    ${FMT_LIB}
#+    Boost::MPL
#+    dmclock::dmclock)
#+endif()
# set_target_properties(crimson-osd PROPERTIES
#   POSITION_INDEPENDENT_CODE ${EXE_LINKER_USE_PIE})
# install(TARGETS crimson-osd DESTINATION bin)
diff --git a/src/librados/librados.map b/src/librados/librados.map
index 279a0ba0691..96dd5072d94 100644
--- a/src/librados/librados.map
+++ b/src/librados/librados.map
@@ -1,5 +1,7 @@
 LIBRADOS_PRIVATE {
 	global:
+		rados_*;
+		_rados_*;
 		extern "C++" {
 			"guard variable for boost::asio::detail::call_stack<boost::asio::detail::strand_executor_service::strand_impl, unsigned char>::top_";
 			"guard variable for boost::asio::detail::call_stack<boost::asio::detail::strand_service::strand_impl, unsigned char>::top_";
-- 
2.49.1

