Code :: Blocks和boost 1.55:当存在动态库时,不使用静态库

时间:2014-01-17 11:03:10

标签: c++ gcc boost linker codeblocks

我使用以下命令构建了boost 1.55序列化库:

b2 --build-dir=build toolset=gcc --with-serialization --layout=tagged link=static threading=multi stage

并在libboost_serialization-mt.a目录中获得libboost_wserialization-mt.astage/lib - 很好。然后我将boost_serialization添加到我的C :: B项目的链接器库列表中并编译了boost serialization example,它从命令行运行良好。然后,我使用

另外构建了动态和单线程变体
b2 --build-dir=build toolset=gcc --with-serialization --layout=tagged link=static,shared threading=multi,single stage

并按预期在我的stage/lib目录中获得了更多库。让我感到困惑的是,每个库都有一个.so文件,即使是那些应该是静态的文件。为什么会这样?需要什么?

当我现在编译项目时,可执行文件抱怨:

error while loading shared libraries: libboost_serialization.so.1.55.0: cannot open shared object file: No such file or directory

库绝对存在,我可能只需要将它的路径添加到LD_LIBRARY_PATH,但我想暂时静态链接。我怎么能这样做?

我也不太了解库命名:我的libboost_wserialization...文件夹中有一些lib库,而w中的serialization前缀未在当前boost getting started page的库命名部分。


您的回答让我更好地了解了发生的事情 - 现在我知道了boost_wserialization图书馆的来源。我发现在完成第二次构建后,所有存在的库被共享,并且静态库被覆盖。这就是为什么我对那些以前确实是静态的库的“额外”.so文件感到困惑。

2 个答案:

答案 0 :(得分:2)

好的,第一个问题:

  

为什么有boost_serializationboost_wserialization库?

wserialization库是面向wchar_t的。放入一个单独的库,因为实际上可能不需要它。

  

为什么有多个共享/静态库?

您看到所有这些额外共享库的原因是因为您使用b2调用link=static,shared,它指示boost构建共享库以及静态库。此外,添加thread=multi会导致构建mt库,这些库是链接到多线程应用程序时应使用的库。

  

为什么我收到有关libboost_serialization.so.1.55.0的运行时链接错误?

默认情况下,大多数unix / linux系统在链接时更喜欢使用共享库而不是静态库,所以当你尝试链接时,它更喜欢使用共享库而不是静态库。如果要强制使用静态库而不是共享库的链接,可以使用以下命令告诉编译时链接器执行此操作:

-Wl,-Bstatic -lboost_serialization -Wl,-Bdynamic

这将导致链接器查找boost_serialization库的静态变体,而不是动态变体。

现在,因为你正在使用code::blocks,我必须查找如何根据具体情况指定这些标志,但最明智的做法是清理boost构建使用./b2 clean然后重建,仅指定link=static,那么您最终只能使用.a个文件,这将再次生成独立的可执行文件。

如果您要为code::blocks指定此选项,则需要将它们放入Build Settings - > Linker settings - >项目的Other Linker Options字段。只需在库字段中指定库就不适用于这种情况。此外,忘记传入-Wl,-Bdynamic选项将导致它尝试链接某些平台库的静态版本,如果相关库不存在,这可能导致构建失败。

如果要避免必须设置LD_LIBRARY_PATH来运行二进制文件,可以将选项-Wl,-rpath,/path/to/boost/libraries添加到链接器标志,这将导致编译程序在尝试解析时搜索该目录图书馆的位置。

答案 1 :(得分:1)

  

让我感到困惑的是,每个图书馆都有一个.so文件,甚至   那些应该是静态的。为什么会这样?需要什么?

你显然正在使用别人的make文件。我写了自己的。我的构建命令不会创建“.so”(共享对象库)。它只创建“.a”(存档库)。链接器知道如何使用它们。

见男人ar。实用程序ar建立档案 见男士ld。实用程序ld可以构建共享对象。

您可能会在构建序列中查找这些实用程序调用,或者询问某人他们在哪里并注释掉ld的使用,因为您很可能不需要两者(并且构建两者都会不必要地延长构建时间)。或者,您可以暂时重命名ld命令,然后尝试构建。当找不到ld命令时,您可能会获得有关调用ld的位置的有用提示。

在我的make文件中,命令如下所示。注释char是#行的开头。 (字符串扩展$(AR)和$(LD)允许使用非标准实用程序。)

$(TARGET_ARCHIVE): $(OBJ)
    @echo R10: $(TARGET_ARCHIVE) :from: $(OBJ)
    $(AR) crs  $(TARGET_ARCHIVE)  $(OBJ)

#    $(TARGET_OLB) : $(OBJ)
#        @echo R00: $(TARGET_OLB) :from: $(OBJ)  
#        $(LD)   -o $(TARGET_OLB) -r  $(OBJ)

存档(.a)在使用时直接链接到您的可执行文件并包含在您的可执行文件中。加载可执行文件时,.a的所有引用符号都已包含在其中。 (未引用的符号和代码未链接)

共享对象(.so)没有直接链接,而是您的可执行文件获取.so的句柄(或可能是文件名)。我相信,当您的可执行文件加载时,.so不会立即加载。直到您的可执行文件第一次引用.so中的符号时才会加载.so。在该加载时,您的应用程序将遇到延迟,但对于大多数应用程序来说,这种延迟加载可能是合理的。

在激活过程之前,.so也可能已加载到系统内存中。在这种情况下,当你的可执行文件首先引用.so中的一个符号时,一些系统代码会将现有的内存.so映射到你的应用程序 - 可能比加载它更快,但我认为最大的好处是.so由许多进程使用/引用只需要加载一次,从而节省了内存空间。加载的.so具有所有符号,即使您的应用程序不需要所有符号。

在任何一种情况下,你的可执行文件都会更小,但是.so更大,但是.so的每个.so都有一些小的性能损失,需要加载或映射。我的桌面有4 GB,桌面从未感到“拥挤”。它的交换从未使用过(afaik)。所以我一般都使用.a's。

注意:当链接器可以访问存档(.a)和共享对象(.so)文件时,链接器将使用.so(并忽略.a)。可能你可以覆盖这个偏好,但我还没试过。我发现将归档文件(.a)简单地移动到一个单独的(从.so的)目录中更容易,并通过-L build选项通知链接器。