我使用CMake构建共享库。该库包含一些C ++类,这些类应该由使用此库的程序引用。
但是,在生成的库上运行nm
会显示C ++类'函数不是外部可见的,而是内部链接。这意味着我无法使用它们并尝试引用它们会在链接阶段导致未定义的引用。
例如:
-- 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
答案 0 :(得分:2)
这是因为CMake默认添加了<span id="daily-price" style="display:none"><%= @vehicle.price %></span>
<div id="full-price"></div>
<script>
$( "#start-date, #end-date" ).change(function() {
var d1=document.getElementById("start-date").value;
var d2=document.getElementById("end-date").value;
var start = new Date(d1);
var end = new Date(d2);
var daily_price=document.getElementById("daily-price").innerHTML;
var full_price = daily_price * (end-start) / (24*3600*1000); // from milliseconds to days.
$("#full-price").innerHTML=full_price;
});
</script>
编译标志。
要恢复默认的可见性,只需将这两行添加到`SELECT COUNT(*) AS `__count`
FROM `album`
INNER JOIN `tracks`
ON (`album`.`id` = `tracks`.`album_id`)
WHERE `tracks`.`viewable` = 1`
:
-fvisibility hidden