[lld] [llvm] Add `NO_VERSIONING` feature in `add_llvm_library` (PR #124588)

Parth Arora via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 27 08:40:50 PST 2025


https://github.com/partaror created https://github.com/llvm/llvm-project/pull/124588

This commit adds `NO_VERSIONING` feature in `add_llvm_library`. With
`NO_VERSIONING`, symbols are exported without versioning when creating a
shared library using `add_llvm_library` with `LLVM_EXPORTED_SYMBOL_FILE`.
This makes `add_llvm_library` functionality more flexible.

We need this functionality to optimally maintain one of our downstream LLVM
tool.

>From 910509c9b787c3f96937e2b220b5aec9a062c5ec Mon Sep 17 00:00:00 2001
From: Parth Arora <quic_partaror at quicinc.com>
Date: Thu, 2 Jan 2025 09:32:23 -0800
Subject: [PATCH 1/2] [LLD] [ELF] Add support for linker script unary plus
 operator

This commit adds support for linker script unary plus ('+') operator.
It is helpful for improving compatibility between LLD and GNU LD.

Closes #118047
---
 lld/ELF/ScriptParser.cpp                 | 2 ++
 lld/test/ELF/linkerscript/diag.test      | 4 ++--
 lld/test/ELF/linkerscript/operators.test | 4 ++++
 3 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index f53515cc3f3c0d..06a22613ee93ac 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -1489,6 +1489,8 @@ Expr ScriptParser::readPrimary() {
     Expr e = readPrimary();
     return [=] { return -e().getValue(); };
   }
+  if (consume("+"))
+    return readPrimary();
 
   StringRef tok = next();
   std::string location = getCurrentLocation();
diff --git a/lld/test/ELF/linkerscript/diag.test b/lld/test/ELF/linkerscript/diag.test
index fbc24659a53114..114f5c2c0820b7 100644
--- a/lld/test/ELF/linkerscript/diag.test
+++ b/lld/test/ELF/linkerscript/diag.test
@@ -12,9 +12,9 @@ SECTIONS {
 }
 
 # RUN: not ld.lld -shared 0.o -T 1.lds 2>&1 | FileCheck %s --check-prefix=CHECK1 --match-full-lines --strict-whitespace
-#      CHECK1:{{.*}}:2: malformed number: +
+#      CHECK1:{{.*}}:2: malformed number: {
 # CHECK1-NEXT:>>>   .text + { *(.text) }
-# CHECK1-NEXT:>>>         ^
+# CHECK1-NEXT:>>>           ^
 
 #--- 2.lds
 
diff --git a/lld/test/ELF/linkerscript/operators.test b/lld/test/ELF/linkerscript/operators.test
index 27209a2e40f598..f84f23fd4d469d 100644
--- a/lld/test/ELF/linkerscript/operators.test
+++ b/lld/test/ELF/linkerscript/operators.test
@@ -73,6 +73,8 @@ SECTIONS {
   log2ceil100000000 = LOG2CEIL(0x100000000);
   log2ceil100000001 = LOG2CEIL(0x100000001);
   log2ceilmax = LOG2CEIL(0xffffffffffffffff);
+  unaryadd = +3 + ++5;
+  unaryadd_and_unaryminus = 15 + +-5 + -+7;
 }
 
 # CHECK:      0000000000000002 A unary
@@ -126,6 +128,8 @@ SECTIONS {
 # CHECK-NEXT: 0000000000000020 A log2ceil100000000
 # CHECK-NEXT: 0000000000000021 A log2ceil100000001
 # CHECK-NEXT: 0000000000000040 A log2ceilmax
+# CHECK-NEXT: 0000000000000008 A unaryadd
+# CHECK-NEXT: 0000000000000003 A unaryadd_and_unaryminus
 
 ## Mailformed number error.
 # RUN: echo "SECTIONS { . = 0x12Q41; }" > %t.script

>From 6daa3d78aefebecd9854fc6a211e42bced05ebb5 Mon Sep 17 00:00:00 2001
From: Parth Arora <quic_partaror at quicinc.com>
Date: Mon, 27 Jan 2025 08:33:21 -0800
Subject: [PATCH 2/2] Add NO_VERSIONING feature in add_llvm_library

This commit adds NO_VERSIONING feature in add_llvm_library. With
NO_VERSIONING, symbols are exported without versioning when creating a
shared library using add_llvm_library with LLVM_EXPORTED_SYMBOL_FILE.
This makes add_llvm_library functionality more flexible.

We need this functionality to optimally maintain one of our downstream LLVM
tool.
---
 llvm/cmake/modules/AddLLVM.cmake              | 19 ++++--
 .../modules/AddNoVersionSymbolExports.cmake   | 63 +++++++++++++++++++
 2 files changed, 76 insertions(+), 6 deletions(-)
 create mode 100644 llvm/cmake/modules/AddNoVersionSymbolExports.cmake

diff --git a/llvm/cmake/modules/AddLLVM.cmake b/llvm/cmake/modules/AddLLVM.cmake
index d3e9377c8d2f7e..a6be908dfa46ab 100644
--- a/llvm/cmake/modules/AddLLVM.cmake
+++ b/llvm/cmake/modules/AddLLVM.cmake
@@ -3,17 +3,18 @@ include(LLVMDistributionSupport)
 include(LLVMProcessSources)
 include(LLVM-Config)
 include(DetermineGCCCompatible)
+include(AddNoVersionSymbolExports)
 
 # get_subproject_title(titlevar)
 #   Set ${outvar} to the title of the current LLVM subproject (Clang, MLIR ...)
-# 
+#
 # The title is set in the subproject's top-level using the variable
 # LLVM_SUBPROJECT_TITLE. If it does not exist, it is assumed it is LLVM itself.
 # The title is not semantically significant, but use to create folders in
 # CMake-generated IDE projects (Visual Studio/XCode).
 function(get_subproject_title outvar)
   if (LLVM_SUBPROJECT_TITLE)
-    set(${outvar} "${LLVM_SUBPROJECT_TITLE}" PARENT_SCOPE) 
+    set(${outvar} "${LLVM_SUBPROJECT_TITLE}" PARENT_SCOPE)
   else ()
     set(${outvar} "LLVM" PARENT_SCOPE)
   endif ()
@@ -520,10 +521,12 @@ endfunction(set_windows_version_resource_properties)
 #      This is used to specify that this is a component library of
 #      LLVM which means that the source resides in llvm/lib/ and it is a
 #      candidate for inclusion into libLLVM.so.
+#   NO_VERSIONING
+#      This is used to remove symbol versioning info while exporting symbols for a shared object.
 #   )
 function(llvm_add_library name)
   cmake_parse_arguments(ARG
-    "MODULE;SHARED;STATIC;OBJECT;DISABLE_LLVM_LINK_LLVM_DYLIB;SONAME;NO_INSTALL_RPATH;COMPONENT_LIB"
+    "MODULE;SHARED;STATIC;OBJECT;DISABLE_LLVM_LINK_LLVM_DYLIB;NO_VERSIONING;SONAME;NO_INSTALL_RPATH;COMPONENT_LIB"
     "OUTPUT_NAME;PLUGIN_TOOL;ENTITLEMENTS;BUNDLE_PATH"
     "ADDITIONAL_HEADERS;DEPENDS;LINK_COMPONENTS;LINK_LIBS;OBJLIBS"
     ${ARGN})
@@ -645,11 +648,11 @@ function(llvm_add_library name)
   endif()
   set_target_properties(${name} PROPERTIES FOLDER "${subproject_title}/Libraries")
 
-  ## If were compiling with clang-cl use /Zc:dllexportInlines- to exclude inline 
+  ## If were compiling with clang-cl use /Zc:dllexportInlines- to exclude inline
   ## class members from being dllexport'ed to reduce compile time.
   ## This will also keep us below the 64k exported symbol limit
   ## https://blog.llvm.org/2018/11/30-faster-windows-builds-with-clang-cl_14.html
-  if(LLVM_BUILD_LLVM_DYLIB AND NOT LLVM_DYLIB_EXPORT_INLINES AND 
+  if(LLVM_BUILD_LLVM_DYLIB AND NOT LLVM_DYLIB_EXPORT_INLINES AND
      MSVC AND CMAKE_CXX_COMPILER_ID MATCHES Clang)
     target_compile_options(${name} PUBLIC /Zc:dllexportInlines-)
     if(TARGET ${obj_name})
@@ -737,7 +740,11 @@ function(llvm_add_library name)
     set_target_properties( ${name} PROPERTIES DEFINE_SYMBOL "" )
 
     if (LLVM_EXPORTED_SYMBOL_FILE)
-      add_llvm_symbol_exports( ${name} ${LLVM_EXPORTED_SYMBOL_FILE} )
+      if(ARG_NO_VERSIONING AND LLVM_ON_UNIX)
+        add_no_version_symbol_exports( ${name} ${LLVM_EXPORTED_SYMBOL_FILE} )
+      else(ARG_NO_VERSIONING AND LLVM_ON_UNIX)
+        add_llvm_symbol_exports( ${name} ${LLVM_EXPORTED_SYMBOL_FILE} )
+      endif(ARG_NO_VERSIONING AND LLVM_ON_UNIX)
     endif()
   endif()
 
diff --git a/llvm/cmake/modules/AddNoVersionSymbolExports.cmake b/llvm/cmake/modules/AddNoVersionSymbolExports.cmake
new file mode 100644
index 00000000000000..b0b1185e654bf6
--- /dev/null
+++ b/llvm/cmake/modules/AddNoVersionSymbolExports.cmake
@@ -0,0 +1,63 @@
+# Handy function to export symbols without versioning
+function(add_symbol_exports target_name export_file)
+  if(LLVM_HAVE_LINK_VERSION_SCRIPT)
+    # Gold and BFD ld require a version script rather than a plain list.
+    set(native_export_file "${target_name}.exports")
+    add_custom_command(
+      OUTPUT ${native_export_file}
+      COMMAND echo "{" > ${native_export_file}
+      COMMAND grep -q "[[:alnum:]]" ${export_file} && echo "  global:" >>
+              ${native_export_file} || :
+      COMMAND sed -e "s/$/;/" -e "s/^/    /" < ${export_file} >>
+              ${native_export_file}
+      COMMAND echo "  local: *;" >> ${native_export_file}
+      COMMAND echo "};" >> ${native_export_file}
+      DEPENDS ${export_file}
+      VERBATIM
+      COMMENT "Creating export file for ${target_name}")
+    set_property(
+    TARGET ${target_name}
+    APPEND_STRING
+    PROPERTY
+        LINK_FLAGS
+        "  -Wl,--version-script,\"${CMAKE_CURRENT_BINARY_DIR}/${native_export_file}\""
+    )
+  endif()
+
+  add_custom_target(${target_name}_exports DEPENDS ${native_export_file})
+  set_target_properties(${target_name}_exports PROPERTIES FOLDER "Misc")
+
+  get_property(
+    srcs
+    TARGET ${target_name}
+    PROPERTY SOURCES)
+  foreach(src ${srcs})
+    get_filename_component(extension ${src} EXT)
+    if(extension STREQUAL ".cpp")
+      set(first_source_file ${src})
+      break()
+    endif()
+  endforeach()
+
+  # Force re-linking when the exports file changes. Actually, it forces
+  # recompilation of the source file. The LINK_DEPENDS target property only
+  # works for makefile-based generators. FIXME: This is not safe because this
+  # will create the same target ${native_export_file} in several different file:
+  # - One where we emitted ${target_name}_exports - One where we emitted the
+  # build command for the following object. set_property(SOURCE
+  # ${first_source_file} APPEND PROPERTY OBJECT_DEPENDS
+  # ${CMAKE_CURRENT_BINARY_DIR}/${native_export_file})
+
+  set_property(
+    DIRECTORY
+    APPEND
+    PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${native_export_file})
+
+  add_dependencies(${target_name} ${target_name}_exports)
+
+  # Add dependency to *_exports later -- CMake issue 14747
+  list(APPEND LLVM_COMMON_DEPENDS ${target_name}_exports)
+  set(LLVM_COMMON_DEPENDS
+      ${LLVM_COMMON_DEPENDS}
+      PARENT_SCOPE)
+endfunction(add_symbol_exports)



More information about the llvm-commits mailing list