Linux C/C++ 库链接选项 --whole-archive,--no-whole-archive和--start-group, --end-group

2024-08-28 06:28

本文主要是介绍Linux C/C++ 库链接选项 --whole-archive,--no-whole-archive和--start-group, --end-group,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

库链接选项

  • 一、介绍
    • whole-archive编译选项
    • Bstatic编译选项
    • start-group 编译选项
  • 示例
  • 参考链接

一、介绍

  这四个都是链接器的选项,所以在编译的时候要用-Wl,[options]来传递给链接器,不然编译器会不认得这个选项。
  在大型工程开发中,工程目录会分的非常细,在modules下会创建很多模块,每个modules都会编译成.a静态库文件供主路径/app/src/下使用,这样就会产生链接库问题,比如在app下的函数要调用静态库里的函数,会出现未定义的错误,需要通过:

-Wl,--whole-archive -lXXX
-Wl,--no-whole-archive -lXXX

  在脚本里修改下链接库的选项,这里XXX代表静态库的名称。

whole-archive编译选项

  默认情况下,对于未使用到的符号(函数是一种符号),链接器不会将它们链接进共享库和可执行程序。这个时候,可以启用链接参数 "--whole-archive"来告诉链接器,将后面库中所有符号都链接进来,参数 "-no-whole-archive" 则是重置,以避免后面库的所有符号被链接进来。

Bstatic编译选项

"-Wl,-Bstatic"指定链接静态库,使用"-Wl,-Bdynamic"指定链接共享库,使用示例:

-Wl,-Bstatic -lmysqlclient_r -lssl -lcrypto -Wl,-Bdynamic -lrt -Wl,-Bdynamic -pthread -Wl,-Bstatic -lgtest

start-group 编译选项

  假设程序x依赖三个静态库:libX1.a、libX2.a和libX3.a,而libX2.a又依赖libX1.a,libX3.a依赖libX2.a和libX1.a,正常情况下的CMakeLists.txt格式如下

target_link_libraries(xlibX1.alibX2.alibX3.a
)

  但也不关心静态库的顺序问题,ld为此提供了start-group和end-group两个选项,让包含在这两者间的静态库顺序可以随意。

target_link_libraries(x-Wl,--start-grouplibX3.alibX2.alibX1.a-Wl,--end-group
)

  这里有一个链接顺序的问题,在command line上前面的库会依赖之后的库,如果碰到循环链接,-lliba -llibb -lliba,这样就需要使用–start-group和–end-group反复在.a中进行搜索直到所有的未定义字符都被找到为止,而不是默认的只搜索一次。MKL库有这样的问题。

示例

// a.h   
extern void foo();// a.cpp 
#include  
void foo() 
{ printf("foo\n"); 
} // x.cpp 
#include "a.h" 
int main() 
{ foo(); return 0; 
}// Makefile 
all: x 
x: x.cpp liba.so g++ -g -o $@ $^ 
liba.so: liba.a g++ -g -fPIC -shared -o $@ $^ #g++ -g -fPIC -shared -o $@ -Wl,--whole-archive $^ -Wl,-no-whole-archive 
liba.a: a.o ar cru $@ $^ 
a.o: a.cpp g++ -g -c $^ 
clean: rm -f x a.o liba.a liba.so 

运行测试:

$ make g++ -g -c a.cpp ar cru liba.a a.o g++ -g -fPIC -shared -o liba.so liba.a #g++ -g -fPIC -shared -o liba.so -Wl,--whole-archive liba.a -Wl,-no-whole-archive g++ -g -o x x.cpp liba.so /tmp/cc6UYIAF.o: In function `main': /data/jayyi/ld/x.cpp:5: undefined reference to `foo()' collect2: ld returned 1 exit status make: *** [x] Error 1 

  默认情况下,对于未使用到的符号(函数是一种符号),链接器不会将它们链接进共享库和可执行程序。
  这个时候,可以启用链接参数“--whole-archive”来告诉链接器,将后面库中所有符号都链接进来,参数“-no-whole-archive”则是重置,以避免后面库的所有符号被链接进来。
  主要作用就是解决主目录函数与模块间函数相互调用问题。
修改一下makefile:

// Makefile 
all: x 
x: x.cpp liba.so g++ -g -o $@ $^ 
liba.so: liba.a g++ -g -fPIC -shared -o $@ -Wl,--whole-archive $^ -Wl,-no-whole-archive 
liba.a: a.o ar cru $@ $^ 
a.o: a.cpp g++ -g -c $^ 
clean: rm -f x a.o liba.a liba.so 

参考链接

https://www.cnblogs.com/vaughnhuang/p/16474361.html
https://blog.csdn.net/lanhuazui10/article/details/107895036
https://www.cnblogs.com/JimmyTY/p/5856217.html

这篇关于Linux C/C++ 库链接选项 --whole-archive,--no-whole-archive和--start-group, --end-group的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1113984

相关文章

Linux如何查看文件权限的命令

《Linux如何查看文件权限的命令》Linux中使用ls-R命令递归查看指定目录及子目录下所有文件和文件夹的权限信息,以列表形式展示权限位、所有者、组等详细内容... 目录linux China编程查看文件权限命令输出结果示例这里是查看tomcat文件夹总结Linux 查看文件权限命令ls -l 文件或文件夹

idea的终端(Terminal)cmd的命令换成linux的命令详解

《idea的终端(Terminal)cmd的命令换成linux的命令详解》本文介绍IDEA配置Git的步骤:安装Git、修改终端设置并重启IDEA,强调顺序,作为个人经验分享,希望提供参考并支持脚本之... 目录一编程、设置前二、前置条件三、android设置四、设置后总结一、php设置前二、前置条件

C++11范围for初始化列表auto decltype详解

《C++11范围for初始化列表autodecltype详解》C++11引入auto类型推导、decltype类型推断、统一列表初始化、范围for循环及智能指针,提升代码简洁性、类型安全与资源管理效... 目录C++11新特性1. 自动类型推导auto1.1 基本语法2. decltype3. 列表初始化3

C++11右值引用与Lambda表达式的使用

《C++11右值引用与Lambda表达式的使用》C++11引入右值引用,实现移动语义提升性能,支持资源转移与完美转发;同时引入Lambda表达式,简化匿名函数定义,通过捕获列表和参数列表灵活处理变量... 目录C++11新特性右值引用和移动语义左值 / 右值常见的左值和右值移动语义移动构造函数移动复制运算符

Linux系统中查询JDK安装目录的几种常用方法

《Linux系统中查询JDK安装目录的几种常用方法》:本文主要介绍Linux系统中查询JDK安装目录的几种常用方法,方法分别是通过update-alternatives、Java命令、环境变量及目... 目录方法 1:通过update-alternatives查询(推荐)方法 2:检查所有已安装的 JDK方

SQL Server安装时候没有中文选项的解决方法

《SQLServer安装时候没有中文选项的解决方法》用户安装SQLServer时界面全英文,无中文选项,通过修改安装设置中的国家或地区为中文中国,重启安装程序后界面恢复中文,解决了问题,对SQLSe... 你是不是在安装SQL Server时候发现安装界面和别人不同,并且无论如何都没有中文选项?这个问题也

Linux系统之lvcreate命令使用解读

《Linux系统之lvcreate命令使用解读》lvcreate是LVM中创建逻辑卷的核心命令,支持线性、条带化、RAID、镜像、快照、瘦池和缓存池等多种类型,实现灵活存储资源管理,需注意空间分配、R... 目录lvcreate命令详解一、命令概述二、语法格式三、核心功能四、选项详解五、使用示例1. 创建逻

Linux下在线安装启动VNC教程

《Linux下在线安装启动VNC教程》本文指导在CentOS7上在线安装VNC,包含安装、配置密码、启动/停止、清理重启步骤及注意事项,强调需安装VNC桌面以避免黑屏,并解决端口冲突和目录权限问题... 目录描述安装VNC安装 VNC 桌面可能遇到的问题总结描js述linux中的VNC就类似于Window

linux下shell脚本启动jar包实现过程

《linux下shell脚本启动jar包实现过程》确保APP_NAME和LOG_FILE位于目录内,首次启动前需手动创建log文件夹,否则报错,此为个人经验,供参考,欢迎支持脚本之家... 目录linux下shell脚本启动jar包样例1样例2总结linux下shell脚本启动jar包样例1#!/bin

C++中detach的作用、使用场景及注意事项

《C++中detach的作用、使用场景及注意事项》关于C++中的detach,它主要涉及多线程编程中的线程管理,理解detach的作用、使用场景以及注意事项,对于写出高效、安全的多线程程序至关重要,下... 目录一、什么是join()?它的作用是什么?类比一下:二、join()的作用总结三、join()怎么