我有大约50个不同的静态库链接到我的c ++项目,链接平均需要70s.
我发现这次移动了库的链接顺序.这是预期的,我想如果链接器不必在它构建到该点的整个符号表中继续搜索一组符号.
我想我可以用"nm"来获取静态库之间的依赖图.但是,这只会给我一个"正确"的链接顺序.获得最快链接顺序所涉及的因素是什么?
我觉得它会与上面提到的依赖图有关,通过尝试最小化一些数量的遍历,但我真的不确定哪个.
任何帮助,将不胜感激.
我主要使用intel编译器和gcc编译器.当我用top检查时,它们似乎都在使用GNU ld链接器.希望这可以帮助...
所以,为了更清楚地说明我想要问的内容,我已经知道如何从一组静态库中获得1遍顺序.我自己编写了这个脚本,但正如Olaf的回答所示,有一些众所周知的工具可以做到这一点.
我的问题是,我已经有两个1遍链接排序,其中一个在~85秒内运行,另一个在〜70秒内运行.很明显,我们可以在一次通过订单中进行更多优化.
我有一个安装在其中的动态libray libtest.dylib /PATH/lib,以及一个使用安装的dylib的执行二进制文件myapp /PATH/bin.
我可以myapp按如下方式运行以找到dylib(在Mac OS X上使用DYLD_LIBRARY_PATH是否可以?并且,使用它的动态库搜索算法是什么?):
DYLD_LIBRARY_PATH="/PATH/lib" myapp
Run Code Online (Sandbox Code Playgroud)
我想我可以install_name_tool用来更新库和可执行文件,以便可以使用rpath找到库.我在这篇文章中使用了提示 - 如何在dylib中指定rpath?.
在lib中,我执行了这个命令来添加rpath.
install_name_tool -id "@rpath/libtest.dylib" libtest.dylib
install_name_tool -add_rpath "@executable_path/../lib/" libtest.dylib
Run Code Online (Sandbox Code Playgroud)
在bin中,我执行了install_name_tool -add_rpath "@executable_path/../lib/" myapp.
但是,当我myapp在bin目录中执行时,我有错误消息.
dyld: Library not loaded: libtest.dylib
Referenced from: /PATH/bin/./myapp
Reason: image not found
Trace/BPT trap: 5
Run Code Online (Sandbox Code Playgroud)
otool -l myapp 显示rpath在myapp中正确更新.
Load command 16
cmd LC_RPATH
cmdsize 40
path @executable_path/../lib/ (offset 12)
Run Code Online (Sandbox Code Playgroud)
libtest.dylib也是如此
Load command 13
cmd LC_RPATH
cmdsize 40
path …Run Code Online (Sandbox Code Playgroud) 我只是好奇.我创建了一个共享对象:
gcc -o liba.so -fPIC -shared liba.c
Run Code Online (Sandbox Code Playgroud)
还有一个共享对象,它与前者相关联:
gcc -o libb.so -fPIC -shared libb.c liba.so
Run Code Online (Sandbox Code Playgroud)
现在,在创建链接的可执行文件时libb.so,我必须指定-rpath-link to ld,以便在发现liba.so时可以找到它libb.so依赖于它:
gcc -o test -Wl,-rpath-link,./ test.c libb.so
Run Code Online (Sandbox Code Playgroud)
否则ld会抱怨.
为什么,ld必须能够liba.so在链接时找到test?因为对我而言,似乎ld在确认liba.so存在方面做的事情并不多.例如,根据需要readelf --dynamic ./test只运行列表libb.so,所以我想动态链接器必须发现libb.so -> liba.so它自己的依赖关系,并使它自己搜索liba.so.
我在x86-64 GNU/Linux平台上,而main() - 例程在test调用函数libb.so时依次调用函数liba.so.
我有一个程序和一个静态库:
// main.cpp
int main() {}
// mylib.cpp
#include <iostream>
struct S {
S() { std::cout << "Hello World\n";}
};
S s;
Run Code Online (Sandbox Code Playgroud)
我想将静态库(libmylib.a)链接到程序对象(main.o),虽然后者不直接使用前者的任何符号.
以下命令似乎不适合g++ 4.7.它们将在没有任何错误或警告的情况下运行,但显然libmylib.a不会链接:
g++ -o program main.o -Wl,--no-as-needed /path/to/libmylib.a
Run Code Online (Sandbox Code Playgroud)
要么
g++ -o program main.o -L/path/to/ -Wl,--no-as-needed -lmylib
Run Code Online (Sandbox Code Playgroud)
你有更好的想法吗?
我们将代码库分解为静态库.不幸的是,这些库具有循环依赖性; 例如,libfoo.a取决于,libbar.a反之亦然.
我知道处理这个的"正确"方法是使用链接器--start-group和--end-group选项,如下所示:
g++ -o myApp -Wl,--start-group -lfoo -lbar -Wl,--end-group
Run Code Online (Sandbox Code Playgroud)
但在我们现有的Makefile中,问题通常是这样处理的:
g++ -o myApp -lfoo -lbar -lfoo
Run Code Online (Sandbox Code Playgroud)
(想象一下,这扩展到约20个具有复杂相互依赖性的库.)
我一直在通过我们的Makefiles将第二种形式更改为第一种形式,但现在我的同事们问我为什么......除了"因为它更清洁"以及另一种形式存在风险的模糊感,我不这样做有一个很好的答案.
因此,可以连接同一个库多次曾经创造出了问题?例如,如果同一个.o被拉入两次,链接是否会失败?或者是否有任何风险,我们可以结束相同的静态对象的两个副本,创建微妙的错误?
基本上,我想知道链接时间或运行时失败是否有可能多次链接同一个库; 如果是的话,如何触发它们.谢谢.
为了澄清,我的问题是当调用者和被调用者在与GCC编译器和链接器的同一编译单元中定义时,包装/拦截从一个函数/符号到另一个函数/符号的调用.
我的情况类似于以下情况:
/* foo.c */
void foo(void)
{
/* ... some stuff */
bar();
}
void bar(void)
{
/* ... some other stuff */
}
Run Code Online (Sandbox Code Playgroud)
我想包装对这些函数的调用,我可以用ld的--wrap选项(到某一点)用ld的选项(然后我实现__wrap_foo和__wrap_bar,然后按照ld --wrap选项的结果调用__real_foo和__real_bar ).
gcc -Wl,--wrap=foo -Wl,--wrap=bar ...
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是,这只对来自此编译单元外部的foo和bar的引用生效(并在链接时解析).也就是说,从foo.c中的其他函数调用foo和bar 不会被包装.

我尝试使用objcopy --redefine-sym,但只重命名符号及其引用.
我想将调用替换为foo和bar(在foo.o中)__wrap_foo以及__wrap_bar(就像它们通过链接器--wrap选项在其他目标文件中解析一样)之前我将*.o文件传递给链接器的--wrap选项,而不必修改foo .c的源代码.
这样,包装/拦截发生在所有调用foo和bar,而不仅仅是发生在foo.o之外的调用.
这可能吗?
我正在尝试使用ld而不是g ++链接C++的输出.我只是这样做是为了学习如何做,而不是为了实际目的,所以请不要建议只用g ++来做.
看看这个问题,这个人在运行ld命令时会得到同样的错误:
$ ld test.o -o test.out
ld: warning: cannot find entry symbol _start; defaulting to 00000000004000e8
test.o: In function `main':
test.cpp:(.text+0x1c): undefined reference to `strcasecmp'
test.cpp:(.text+0x23): undefined reference to `std::cout'
test.cpp:(.text+0x28): undefined reference to `std::ostream::operator<<(int)'
test.cpp:(.text+0x2d): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)'
test.cpp:(.text+0x35): undefined reference to `std::ostream::operator<<(std::ostream& (*)(std::ostream&))'
test.o: In function `__static_initialization_and_destruction_0(int, int)':
test.cpp:(.text+0x75): undefined reference to `std::ios_base::Init::Init()'
test.cpp:(.text+0x7a): undefined reference to `__dso_handle'
test.cpp:(.text+0x84): undefined reference to `std::ios_base::Init::~Init()'
test.cpp:(.text+0x89): undefined …Run Code Online (Sandbox Code Playgroud) 这是给出段错误的程序.
#include <iostream>
#include <vector>
#include <memory>
int main()
{
std::cout << "Hello World" << std::endl;
std::vector<std::shared_ptr<int>> y {};
std::cout << "Hello World" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
当然,程序本身绝对没有错.segfault的根本原因取决于其构建和运行的环境.
我们在亚马逊上使用构建系统,该系统以几乎与机器无关的方式构建和部署二进制文件(lib和bin).对于我们的情况下,基本上意味着它部署的可执行文件(从上面的程序内置)到和几乎所有的依赖(即共享库)进入.为什么我使用的短语"几乎"是因为共享库,比如,,和可能的其他几个人,从系统(即从可执行选秀权).请注意,这是应该挑选从不过.$project_dir/build/bin/$project_dir/build/lib/libc.solibm.sold-linux-x86-64.so.2/lib64libstdc++$project_dir/build/lib
现在我运行如下:
$ LD_LIBRARY_PATH=$project_dir/build/lib ./build/bin/run
segmentation fault
Run Code Online (Sandbox Code Playgroud)
但是,如果我运行它,而不设置LD_LIBRARY_PATH.它运行正常.
以下是ldd这两种情况的信息(请注意,我编辑了输出,以便在存在差异的地方提及库的完整版本)
$ LD_LIBRARY_PATH=$project_dir/build/lib ldd ./build/bin/run
linux-vdso.so.1 => (0x00007ffce19ca000)
libstdc++.so.6 => $project_dir/build/lib/libstdc++.so.6.0.20 …Run Code Online (Sandbox Code Playgroud) 我只是想分享一下我是如何找到错误的解决方案的
没有实现类程序的定义
运行X/Motif C应用程序时.我发布这个是因为我在网上搜索时只发现了一个对此问题的引用,并且它没有包含任何解决方案.
我设法解决了这个问题,如果你再次遇到这个问题,我想分享我的发现(注意:我不是说我的解决方案总能解决这类错误).
问题
我在运行使用Motif和X Intrinsics工具包的简单C程序时发现了这个问题.
$ gcc -Wall -c push.c
$ gcc -Wall -o push push.o -lXt -lXm
$ ./push
Error: No realize class procedure defined
Run Code Online (Sandbox Code Playgroud)
C源代码如下:
#include <stdio.h>
#include <Xm/Xm.h>
#include <Xm/PushB.h>
/* Prototype Callback function */
void pushed_fn(Widget, XtPointer, XmPushButtonCallbackStruct *);
int main(int argc, char **argv)
{
Widget top_wid, button;
XtAppContext app;
Display* display;
XtToolkitInitialize();
app = XtCreateApplicationContext();
display = XtOpenDisplay(app, "localhost:10.0","push","push", NULL,0, &argc,argv);
top_wid = XtAppCreateShell(NULL, "Form", applicationShellWidgetClass, display, NULL, …Run Code Online (Sandbox Code Playgroud)