为方便起见,我在下面添加了相关联机帮助页.
首先我的(错误)理解:如果我需要将选项分开,
,这意味着第二个-Wl
选项不是另一个选项,因为它在,
此之前就意味着它是-rpath
选项的参数.
我不明白怎么-rpath
会有-Wl,.
争论!
在我看来有意义的是:
-Wl,-rpath .
Run Code Online (Sandbox Code Playgroud)
这应该使用当前目录参数调用-rpath链接器选项.
男人gcc:
轮候册,选项
传递选项作为链接器的选项.如果选项包含逗号,则会在逗号中将其拆分为多个选项.您可以使用此语法将参数传递给该选项.例如,
-Wl,-Map,output.map
传递-Map output.map
给链接器.使用GNU链接器时,您也可以使用`-Wl,-Map = output.map'获得相同的效果.
男子ld:
-rpath = DIR
将目录添加到运行时库搜索路径.将ELF可执行文件与共享对象链接时使用此方法.所有-rpath参数都连接在一起并传递给运行时链接程序,后者使用它们在运行时查找共享对象.在定位链接中明确包含的共享对象所需的共享对象时,也会使用-rpath选项;
我知道.so
文件是一种动态库(许多线程可以共享这些库,因此不需要在内存中有多个副本).但是.a
和之间有什么区别.la
?这些都是静态库吗?
如果动态库比静态库有很大的优势,为什么还有很多静态库呢?
我还想知道加载库(两种类型)的基本机制,以及在某个地方使用它时如何调用lib中的一段代码.我应该学习哪一部分内核?我应该知道哪些相关的Linux命令/实用程序才能知道进程是如何运行的?(我现在才知道ld
命令)
我什么时候应该尝试构建代码.so
或.a
?哪一个更好?
[mirror@home ins_openvpn]$ ls lib/openvpn/plugins/ -l
total 96
-rw-r--r-- 1 mirror mirror 22892 Sep 2 23:25 openvpn-plugin-auth-pam.a
-rwxr-xr-x 1 mirror mirror 931 Sep 2 23:25 openvpn-plugin-auth-pam.la
-rwxr-xr-x 1 mirror mirror 23621 Sep 2 23:25 openvpn-plugin-auth-pam.so
-rw-r--r-- 1 mirror mirror 17228 Sep 2 23:25 openvpn-plugin-down-root.a
-rwxr-xr-x 1 mirror mirror 932 Sep 2 23:25 openvpn-plugin-down-root.la
-rwxr-xr-x 1 mirror mirror 18805 Sep 2 23:25 openvpn-plugin-down-root.so
Run Code Online (Sandbox Code Playgroud) linux memory-management shared-libraries ld static-libraries
我正在构建一个简单的C++程序,我想暂时用一个系统提供的共享库替换它的更新版本,以进行开发和测试.
我尝试设置LD_LIBRARY_PATH变量,但链接器(ld)失败了:
/ usr/bin/ld:找不到-lyaml-cpp
我希望这可以工作,因为根据ld手册页:
链接器使用以下搜索路径来查找所需的共享库:...对于本机链接器,环境变量"LD_LIBRARY_PATH"的内容...
然后我尝试设置LIBRARY_PATH,这很有效.
根据GCC手册:
LIBRARY_PATH的值是以冒号分隔的目录列表,与PATH非常相似.当配置为本机编译器时,GCC会在搜索特殊链接器文件时尝试这样指定的目录,如果它无法使用GCC_EXEC_PREFIX找到它们.在使用-l选项搜索普通库时,使用GCC链接也会使用这些目录(但首先使用-L指定的目录).
正如(GCC)手册所示,LIBRARY_PATH可行,因为我与GCC链接.
但..
我需要严格优化可执行文件的大小(ARM
开发),我注意到在我当前的构建方案(gcc
+ ld
)中,未使用的符号不会被剥离.
的用法arm-strip --strip-unneeded
为生成的可执行文件/库不改变可执行文件的输出大小(我不知道为什么,也许它根本不能).
修改我的构建管道的方式是什么(如果存在),以便从结果文件中删除未使用的符号?
我甚至都不会想到这一点,但我当前的嵌入式环境并不是非常"强大",甚至500K
可以节省2M
非常好的加载性能.
更新:
不幸的是,gcc
我使用的当前版本没有-dead-strip
选项,并且-ffunction-sections... + --gc-sections
for ld
不会对结果输出产生任何显着差异.
我很震惊,这甚至成了问题,因为我确信gcc + ld
应该自动删除未使用的符号(为什么他们甚至要保留它们?).
我有一个虚拟的Debian系统,我用它来开发.
今天我想试试llvm/clang.
安装clang后,我无法编译我的旧c项目(使用gcc).这是错误:
...
/usr/bin/ld: cannot find crt1.o: No such file or directory
/usr/bin/ld: cannot find crti.o: No such file or directory
collect2: ld returned 1 exit status
...
Run Code Online (Sandbox Code Playgroud)
我卸载了clang,它仍然无法正常工作.
有谁知道如何解决这个问题?
gcc
并ld
提供了许多方法来指定库的搜索路径 - 其中包括-rpath
和-L
标志.这些联机帮助页显示这两个标志之间没有差异,有效地说每个标志都会向库搜索路径添加一个库.但两个旗帜完全相同的事情似乎很奇怪.这两个选项之间有什么区别?
如何将两个GCC编译的.o对象文件合并到第三个.o文件中?
$ gcc -c a.c -o a.o
$ gcc -c b.c -o b.o
$ ??? a.o b.o -o c.o
$ gcc c.o other.o -o executable
Run Code Online (Sandbox Code Playgroud)
如果您有权访问源文件,-combine
GCC标志将在编译之前合并源文件:
$ gcc -c -combine a.c b.c -o c.o
Run Code Online (Sandbox Code Playgroud)
但是,这仅适用于源文件,并且GCC不接受.o
文件作为此命令的输入.
通常,链接.o
文件无法正常工作,因为您无法使用链接器的输出作为输入.结果是共享库,并且不会静态链接到生成的可执行文件中.
$ gcc -shared a.o b.o -o c.o
$ gcc c.o other.o -o executable
$ ./executable
./executable: error while loading shared libraries: c.o: cannot open shared object file: No such file or directory
$ file c.o
c.o: ELF 32-bit …
Run Code Online (Sandbox Code Playgroud) 这些命令行选项的目的是什么?请帮助破译以下命令行的含义:
-Wl,--start-group -lmy_lib -lyour_lib -lhis_lib -Wl,--end-group -ltheir_lib
Run Code Online (Sandbox Code Playgroud)
显然它与链接有关,但GNU手册很安静,究竟是分组的意思.
我正在尝试编译一个使用udis86库的程序.实际上我正在使用库的用户手册中给出的示例程序.但是在编译时,它会给出错误.我得到的错误是:
example.c:(.text+0x7): undefined reference to 'ud_init'
example.c:(.text+0x7): undefined reference to 'ud_set_input_file'
.
.
example.c:(.text+0x7): undefined reference to 'ud_insn_asm'
Run Code Online (Sandbox Code Playgroud)
我使用的命令是:
$ gcc -ludis86 example.c -o example
Run Code Online (Sandbox Code Playgroud)
按照用户手册中的说明进行操作.
显然,链接器无法链接libudis库.但如果我改变命令:
$ gcc example.c -ludis86 -o example
Run Code Online (Sandbox Code Playgroud)
它开始工作.那么可以请某人解释第一个命令的问题是什么?