Skip to content

Commit 1fe030b

Browse files
AaronStGeorgeclaudebangtianliu
authored
Add --exclude-libs=ALL to libIREECompiler.so shared library (#23574)
When building `libIREECompiler.so` in `TheRock` I hit the following error when trying to load the library: ``` LLVM ERROR: Option 'pbqp' already exists! ``` I'll put the full claude generated description of what happened below but the long and the short of it is `libIREECompiler.so` seems to be exporting quite a few symbols when linking LLVM's static `.a`'s. In my case, `TheRock` has another library that loads `libLLVM.so`, and when loaded it [interposes](https://maskray.me/blog/2021-05-16-elf-interposition-and-bsymbolic) some of the global command line registration machinery. Because of the interposition, `libIREECompiler.so`'s command line registration got routed to `libLLVM.so`'s; luckily, rather than some incredibly hard to diagnose error, the double command line registration crashes on startup. `--exclude-libs,ALL` hides symbols from static libraries when linking the final `libIREECompiler.so`, preventing LLVM's symbols from being exported and therefore being interposable. --- Claude generated description ``` Add --exclude-libs=ALL to libIREECompiler.so shared library libIREECompiler.so statically links LLVM/MLIR but exports ~175K internal symbols via its version script (api_version.ld uses `global: *`). The visibility design assumes LLVM is compiled with -fvisibility=hidden, but LLVM's own CMake build only applies -fvisibility-inlines-hidden — not -fvisibility=hidden — to the vast majority of its compilation units (2250/2720 LLVM files, 1049/1145 MLIR files lack the flag). This means all non-inline LLVM symbols default to visibility("default") and leak through the version script. When libIREECompiler.so is loaded via dlopen(RTLD_LOCAL) into a process that already has libLLVM.so in the global scope (e.g. via HIP runtime's libamd_comgr.so → libLLVM.so.22.0git), the ELF dynamic linker searches the global scope first when resolving relocations. LLVM function calls in libIREECompiler.so that go through the PLT/GOT resolve to libLLVM.so's copies rather than the compiler's own static LLVM. This causes LLVM cl::Option static initializers to register duplicate options into libLLVM.so's global registry, crashing with: LLVM ERROR: Option 'pbqp' already exists! The fix adds --exclude-libs=ALL to the SharedImpl linker options, which forces all symbols from static archives (.a files) to hidden visibility at link time. Only symbols from object files (.o) compiled with explicit __attribute__((visibility("default"))) annotations — i.e. the IREE and MLIR C API functions marked with IREE_EMBED_EXPORTED / MLIR_CAPI_EXPORTED — remain visible. This reduces exported dynamic symbols from ~274K to ~2.9K. This matches the pattern already used by MLIR's own MLIR-C shared library (mlir/lib/CAPI/CMakeLists.txt): target_link_options(MLIR-C PRIVATE "-Wl,-exclude-libs,ALL") ``` ci-extra: all --------- Signed-off-by: Bangtian Liu <liubangtian@gmail.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Bangtian Liu <liubangtian@gmail.com>
1 parent b082090 commit 1fe030b

File tree

5 files changed

+9
-0
lines changed

5 files changed

+9
-0
lines changed

build_tools/cmake/iree_check_test.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
function(iree_is_bytecode_module_test_excluded_by_labels _DST_IS_EXCLUDED_VAR _SRC_LABELS)
88
string(TOLOWER "${CMAKE_BUILD_TYPE}" _LOWERCASE_BUILD_TYPE)
99
if(((IREE_ARCH MATCHES "^riscv_") AND ("noriscv" IN_LIST _SRC_LABELS)) OR
10+
((IREE_ARCH STREQUAL "arm_64") AND ("noaarch64" IN_LIST _SRC_LABELS)) OR
1011
(EMSCRIPTEN AND ("nowasm" IN_LIST _SRC_LABELS)) OR
1112
(IREE_ENABLE_ASAN AND ("noasan" IN_LIST _SRC_LABELS)) OR
1213
(IREE_ENABLE_TSAN AND ("notsan" IN_LIST _SRC_LABELS)) OR

compiler/bindings/python/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ declare_mlir_python_extension(IREECompilerPythonExtensions.CompilerDialects
214214
iree_compiler_API_SharedImpl
215215
PRIVATE_LINK_LIBS
216216
LLVMSupport
217+
MLIRIR
218+
MLIRSupport
217219
)
218220

219221
################################################################################

compiler/src/iree/compiler/API/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,10 @@ iree_cc_library(
168168
LINKOPTS
169169
# Linux uses a linker script to version symbols.
170170
$<$<PLATFORM_ID:Linux>:-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/api_version.ld>
171+
# Hide all symbols from static archives (.a) linked into the shared library.
172+
# Without this, LLVM/MLIR internal symbols leak through the `global: *`
173+
# version script since LLVM is not compiled with -fvisibility=hidden.
174+
$<$<PLATFORM_ID:Linux>:LINKER:--exclude-libs,ALL>
171175
DEPS
172176
iree::compiler::bindings::c::headers
173177
)

tests/e2e/regression/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ iree_check_single_backend_test_suite(
8686
compiler_flags = ["--iree-llvmcpu-target-cpu=generic"],
8787
driver = "local-task",
8888
tags = [
89+
"noaarch64",
8990
"noriscv",
9091
],
9192
target_backend = "llvm-cpu",

tests/e2e/regression/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ iree_check_single_backend_test_suite(
8181
COMPILER_FLAGS
8282
"--iree-llvmcpu-target-cpu=generic"
8383
LABELS
84+
"noaarch64"
8485
"noriscv"
8586
)
8687

0 commit comments

Comments
 (0)