c++ - Clang 不导出 C++ 符号

标签 c++ linker clang dynamic-library

我正在使用 CMake 构建共享库。该库包含一些 C++ 类,使用该库的程序应该引用这些类。

但是,在生成的库上运行 nm 显示 C++ 类的函数不是外部可见的,而是具有内部链接。这意味着我无法使用它们,并且尝试引用它们会导致链接阶段出现 undefined reference 。

例如:

-- test.h --
#pragma once
class Test {
public:
    Test();
};

-- test.cpp --
#include "test.h"
#include <iostream>
Test::Test() { std::cout << "Hey!\n"; }

在此示例中 Test::Test() 在外部不可见!

我使用的是 clang 6.0。检查命令调用确认该库是使用 -shared 选项构建的。

什么可能导致此行为?

编辑: 编译命令(我把一些长目录改成了DIR)

clang -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -discard-value-names -main-file-name test.cpp -mrelocation-model pic -pic-level 2 -mthread-model posix -mdisable-fp-elim -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -v -ffunction-sections -fdata-sections -coverage-notes-file DIR/example/CMakeFiles/examplelib.dir/test.cpp.gcno -resource-dir LLVM_DIR/build/lib/clang/6.0.0 -D HAVE_CONFIG_H -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -D examplelib_EXPORTS -I LLVM_DIR/llvm/include -I LLVM_DIR/build/include -I LLVM_DIR/llvm/tools/clang/include -I LLVM_DIR/build/tools/clang/include -D GOOGLE_PROTOBUF_NO_RTTI -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/x86_64-linux-gnu/c++/7.3.0 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/7.3.0/../../../../include/c++/7.3.0/backward -internal-isystem /usr/local/include -internal-isystem LLVM_DIR/build/lib/clang/6.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wall -w -std=c++14 -fdeprecated-macro -fdebug-compilation-dir DIR/example -ferror-limit 19 -fmessage-length 101 -fvisibility hidden -fvisibility-inlines-hidden -pthread -fobjc-runtime=gcc -fcxx-exceptions -fexceptions -fdiagnostics-show-option -fcolor-diagnostics -o CMakeFiles/examplelib.dir/test.cpp.o -x c++ DIR/example/test.cpp

(检查 test.ccp.o 显示该符号是外部的,因此一定是链接器搞砸了)。

链接器命令(/usr/bin/ld 是 LLVM 链接器 LLD 的链接):

 "/usr/bin/ld" -z relro --hash-style=gnu --eh-frame-hdr -m elf_x86_64 -shared -o libexamplelib.so /usr/bin/../lib/gcc/x86_64-linux-gnu/7.3.0/../../../x86_64-linux-gnu/crti.o /usr/bin/../lib/gcc/x86_64-linux-gnu/7.3.0/crtbeginS.o -L/usr/bin/../lib/gcc/x86_64-linux-gnu/7.3.0 -L/usr/bin/../lib/gcc/x86_64-linux-gnu/7.3.0/../../../x86_64-linux-gnu -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/bin/../lib/gcc/x86_64-linux-gnu/7.3.0/../../.. -LDIR/build/bin/../lib -L/lib -L/usr/lib -ltinfo -z defs -z nodelete -soname libexamplelib.so CMakeFiles/examplelib.dir/test.cpp.o -lpthread -lstdc++ -lm -lgcc_s -lpthread -lc -lgcc_s /usr/bin/../lib/gcc/x86_64-linux-gnu/7.3.0/crtendS.o /usr/bin/../lib/gcc/x86_64-linux-gnu/7.3.0/../../../x86_64-linux-gnu/crtn.o

使用nm检查:

$ nm -gC libexamplelib.so 
0000000000201038 B __bss_start
                 U __cxa_atexit@@GLIBC_2.2.5
                 w __cxa_finalize@@GLIBC_2.2.5
0000000000201038 D _edata
0000000000201040 B _end
00000000000007fc T _fini
                 w __gmon_start__
0000000000000638 T _init
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 U std::ios_base::Init::Init()@@GLIBCXX_3.4
                 U std::ios_base::Init::~Init()@@GLIBCXX_3.4
                 U std::cout@@GLIBCXX_3.4
                 U std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)@@GLIBCXX_3.4

最佳答案

这是因为 CMake 似乎默认添加了 -fvisibility hide 编译标志。

要将可见性恢复为默认值,只需将这两行添加到 CMakeLists.txt 中即可:

set(CMAKE_CXX_VISIBILITY_PRESET default)
set(CMAKE_VISIBILITY_INLINES_HIDDEN 0)

关于c++ - Clang 不导出 C++ 符号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49311634/

相关文章:

c++ - 在保留原始顺序的同时删除/删除多个 std::vector 元素的最有效方法?

c++ - 我不断收到错误 : clang: error: linker command failed with exit code 1 (use -v to see invocation). 请帮助,谢谢

objective-c - 添加一个大的静态库作为 cocoapod 或直接将所有目标文件添加到生成的二进制文件中,因为 -ObjC 链接器标志

c++ - 相同的 C++ 代码,不同的链接选项会导致不同的行为?

c++ - 将 `nullptr` 分配给 `bool` 类型。哪个编译器是正确的?

c++ - 错误编译opencv示例

c++ - 如何在 borland c++ 5.02 中使用 ROM BIOS 中断?

c++ - Linux 64 中带有 JsonCPP 库的 undefined symbol 。我缺少什么?

c++ - 不能在 Qt 中使用 libclang

ios - 哪个是抑制 "unused variable"警告的最佳方法