我正在Linux上构建共享库,并且已配置项目以使用-fvisibility=hidden
进行编译,并使用__attribute__ (( __visibility__ ("default")))
手动添加到要导出的符号中。以下虚拟文件足以说明:
#include <experimental/filesystem>
#include <iostream>
namespace fs = std::experimental::filesystem;
__attribute__((__visibility__("default"))) void foo() { std::cout << "foo\n"; }
void bar() { std::cout << "bar\n"; }
// void baz() { std::cout << fs::current_path().string() << std::endl; }
然后使用:
g++ -shared -o dummy.so -fPIC dummy.cpp -lstdc++fs -fvisibility=hidden
并运行nm -CD dummy.so | grep " T "
来检查导出的符号(在手册页的文本部分中定义的符号)。
foo
被导出:这就是我所期望的。-fvisibility=hidden
,将看到同时导出的foo
和bar
。还可以。baz
(使用std :: filesystem的函数),则无论是否有-fvisibility=hidden
,您都会看到导出的大量文件系统符号。像这样:000000000003b110 T std::filesystem::__cxx11::directory_iterator::operator*() const
000000000003a930 T std::filesystem::__cxx11::recursive_directory_iterator::depth() const
000000000003a980 T std::filesystem::__cxx11::recursive_directory_iterator::operator*() const
0000000000034bb0 T std::filesystem::__cxx11::path::parent_path() const
0000000000032870 T std::filesystem::__cxx11::path::has_filename() const
依此类推-仅显示std :: filesystem或std :: experimental :: filesystem中的符号。
看看libstdc ++ fs_path.h
标头,我假设这种可见性是由namespace std _GLIBCXX_VISIBILITY(default)
行触发的。但是,文件系统并不是库中使用的唯一标准库工具(真正的库工具或该虚拟库工具):也使用了许多其他工具,并且在此视图中都没有出现。
我了解为什么在编译实际的标准库SO时这些符号应该可见,但是为什么从仅使用标准库的库中“导出”这些符号呢?而且,为什么只导出文件系统符号?我可以在不删除std :: filesystem使用的情况下解决此问题吗?
(我的环境是Debian Buster x64。无论我使用Clang还是GCC,这似乎都发生了,并且系统编译器是GCC 8.3.0及其相关的libstdc ++。)