我觉得很奇怪-Wl,-Bstatic,以便告诉gcc我想要静态链接哪些库.毕竟我gcc直接告诉所有关于链接库的信息(-Ldir,-llibname).
是否可以直接告诉gcc驱动程序哪些库应该静态链接?
澄清:我知道如果某个库只存在于静态版本中,它将在没有它的情况下使用它-Wl,-Bstatic,但我想暗示gcc更喜欢静态库.我也知道直接指定库文件会链接它,但我更喜欢保持包含静态和动态库的语义相同.
我需要分发一个可以在尽可能多的x86 Linux发行版上运行的二进制文件.这意味着我必须静态链接一些库,如glibc,因为用户可能没有我使用的版本.其他库必须动态链接,如fontconfig,因为它依赖于缓存文件格式和每个系统上可能不同的硬编码位置.
执行此操作的命令行选项有哪些?如果我指定-static,那么gcc将拒绝动态链接任何库.
以下问题是相关的,但不回答我的问题:
我之前提出了一个非常类似的问题,但是由于我开始的上一个问题在评论部分有些混乱而没有得到完全回答(但我将其标记为已回答,因为这是一项很好的努力并至少部分回答了它)我会问一个新问题.问题是具体如何将libc链接为静态,同时动态链接其他库(例如libm).有人提出在第一个问题中无法做到,是真的吗?如果是这样,知道为什么不是很有趣.
甚至可以这样做吗?有人发表了意见(这是出于某种原因删除,也许这是不正确的?),这是可能的,但那么一定还存在libc中的动态链接的版本,因为它会通过动态库需要(如动态的libm会需要动态libc(?)).
这对我来说很好,但对我来说如何告诉GCC这样做并不明显,即在libc中链接为静态和动态.我该怎么做(我做了几次尝试,有些会在后面的问题中展示)?或者还有其他方法可以做我想要的吗?
我们首先看到,通过简单地运行gcc test.c -lm,一切都是动态链接的,如下所示:
$ gcc test.c -lm
$ ldd a.out
linux-vdso.so.1 (0x00007fffb37d1000)
libm.so.6 => /lib64/libm.so.6 (0x00007f3b0eeb6000)
libc.so.6 => /lib64/libc.so.6 (0x00007f3b0eb10000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3b0f1b0000)
Run Code Online (Sandbox Code Playgroud)
要仅将libm链接为静态,同时允许libc保持动态,我们可以这样做(正如Z boson在前面提到的一个问题中指出的那样):
$ gcc test.c /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libm.a
$ ldd a.out
linux-vdso.so.1 (0x00007fff747ff000)
libc.so.6 => /lib64/libc.so.6 (0x00007f09aaa0c000)
/lib64/ld-linux-x86-64.so.2 (0x00007f09aadb2000)
Run Code Online (Sandbox Code Playgroud)
但是,尝试使用相同的过程来链接libc static和libm dynamic,似乎不起作用:
$ gcc test.c /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.a -lm
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: dynamic STT_GNU_IFUNC symbol `strcmp' with pointer equality in `/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.a(strcmp.o)' can not be used when making an executable; recompile with -fPIE and relink …Run Code Online (Sandbox Code Playgroud) 我需要创建一个共享库,必须将其自己的依赖项(包括libc / libstdc ++)静态链接到该共享库,以生成一个自包含的二进制文件。我试图做到这一点
g++ -c -fpic -o foo.o foo.cpp
g++ -static -shared -o foo.so foo.o
Run Code Online (Sandbox Code Playgroud)
失败与:
/usr/bin/ld.bfd.real: /usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.2.0/crtbeginT.o: relocation R_X86_64_32 against `__TMC_END__' can not be used when making a shared object; recompile with -fPIC
/usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.2.0/crtbeginT.o: could not read symbols: Bad value
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)
有人可以告诉我我做错了吗?
我有静态和安装在加速的动态版本/usr/local/lib,即两个libboost_system.dylib和libboost_system.a存在。
在我的qmake项目文件中,我将Boost库添加到了链接器中,如下所示: LIBS += -lboost_system
我可以告诉qmake在不显式说明文件名的情况下首选静态版本,以便减少qmake代码的数量以在所有平台上获得静态链接吗?
我正在尝试使用 GCC 的动态和静态链接来编译一个非常简单(就像 hello world 一样简单)的 C 程序。我想知道一般如何做到这一点,所以我的最小测试示例只是尝试将 libc 链接为静态,将 libm 动态链接。
我至少遇到过以下有关同一主题的其他问题:
其中的一些答案建议使用 -Wl,-Bstatic 和 -Wl,-Bdynamic 来指定哪些库分别是静态库和动态库。还建议简单地指定要链接的静态库的完整路径。
我已经尝试过其中的一些建议及其变体。我不明白它给我的错误消息。我知道 PIE 是什么,但我不明白它与我想做的事情有什么关系。
以下是一些失败的尝试:
$ gcc test.c /usr/lib64/libc.a
linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: dynamic STT_GNU_IFUNC symbol `strcmp' with pointer equality in `/usr/lib64/libc.a(strcmp.o)' can not be used when making an executable; recompile with -fPIE and relink with -pie
urned 1 exit status
$ gcc test.c -Wl,-Bdynamic -lm -Wl,-Bstatic -lc
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lgcc_s
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status
$ …Run Code Online (Sandbox Code Playgroud) 我的应用程序引入了许多共享库.有些是用C++编写的,它引入了libstdc ++.所以它引入了libgcc_s.so.还有一些是用简单的C编写的,并与-static-libgcc相关联.
所以现在我在多个共享库中静态链接了一些libgcc,并且libstdc ++在运行时动态加载libgcc的其他位.
Q1:这个设置会给我带来麻烦吗?libgcc是否具有会使这种混合链接出现问题的内部状态,还是只是内联函数?
Q2:为了让我的应用程序适用于较旧的Linux,我应该发布libstdc ++.so和libgcc_s.so并在主exe上使用rpath来加载它.这是正确的方法吗?
我正在尝试构建.so所有依赖项(主要是 boost)静态链接的库。目前,我可以构建静态链接的静态库和动态链接的共享库:

我想向.so库添加其他依赖项,使其具有 20MB 并且不需要用户安装任何内容。请注意,这只是我们在生产服务器上升级到新的 Boost 1.55 之前的临时解决方案。
我在 Makefile 中定义了这样的库($ARCH可以是 32 或 64):
## Multi-arch library locations
LIB32=/usr/lib/i386-linux-gnu/
LIB64=/usr/lib/x86_64-linux-gnu/
LIBDIR:=$(LIB$(ARCH))
##Library directory
LIB=-L $(LIBDIR)
## DYNAMIC
LIBS=-lboost_serialization -lboost_thread -lboost_date_time -lboost_signals -lboost_iostreams -lboost_system -llog4cplus -lcrypto -lssl -lm
## STATIC
SLIBS=$(LIBDIR)libboost_serialization.a $(LIBDIR)libboost_thread.a $(LIBDIR)libboost_date_time.a $(LIBDIR)libboost_signals.a $(LIBDIR)libboost_iostreams.a $(LIBDIR)libboost_system.a $(LIBDIR)liblog4cplus.a
Run Code Online (Sandbox Code Playgroud)
这是我的共享 lib GCC 命令:
生成文件:
$(CXX) $(CFLAGS) $(INCLUDE) $(LIB) $(LIBS) -shared -Wl,-soname,$(SHARED_LIB_VERSION) -o $(NEW_LIB_DIR)${SHARED_LIB_VERSION} $(OBJ_CPP_DYN) $(OBJ_C_DYN)
Run Code Online (Sandbox Code Playgroud)更改为:
g++ -m64 -Wl,--trace -D NDEBUG -I /usr/include/ -I /usr/local/include -L …Run Code Online (Sandbox Code Playgroud)所以我正在尝试编译并运行一个简单的升压计时器程序
#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
int main() {
using namespace boost::asio;
io_service io;
deadline_timer t(io, boost::posix_time::seconds(5));
t.wait();
std::cout << "Hello World!" << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我在编译这个程序时尝试的第一件事是做
g++ -I /home/vagrant/boost_1_60_0 main.cpp
Run Code Online (Sandbox Code Playgroud)
这给了我一个错误
/tmp/cc8Ytqko.o: In function `__static_initialization_and_destruction_0(int, int)':
main.cpp:(.text+0xfc): undefined reference to `boost::system::generic_category()'
main.cpp:(.text+0x108): undefined reference to `boost::system::generic_category()'
main.cpp:(.text+0x114): undefined reference to `boost::system::system_category()'
/tmp/cc8Ytqko.o: In function `boost::system::error_code::error_code()':
main.cpp:(.text._ZN5boost6system10error_codeC2Ev[_ZN5boost6system10error_codeC5Ev]+0x17): undefined reference to `boost::system::system_category()'
/tmp/cc8Ytqko.o: In function `boost::asio::error::get_system_category()':
main.cpp:(.text._ZN5boost4asio5error19get_system_categoryEv[_ZN5boost4asio5error19get_system_categoryEv]+0x5): undefined reference to `boost::system::system_category()'
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)
然后我做了一些研究,似乎我需要构建 …