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

相关文章

新特性抢先看! Ubuntu 25.04 Beta 发布:Linux 6.14 内核

《新特性抢先看!Ubuntu25.04Beta发布:Linux6.14内核》Canonical公司近日发布了Ubuntu25.04Beta版,这一版本被赋予了一个活泼的代号——“Plu... Canonical 昨日(3 月 27 日)放出了 Beta 版 Ubuntu 25.04 系统镜像,代号“Pluc

C++ 中的 if-constexpr语法和作用

《C++中的if-constexpr语法和作用》if-constexpr语法是C++17引入的新语法特性,也被称为常量if表达式或静态if(staticif),:本文主要介绍C++中的if-c... 目录1 if-constexpr 语法1.1 基本语法1.2 扩展说明1.2.1 条件表达式1.2.2 fa

Linux安装MySQL的教程

《Linux安装MySQL的教程》:本文主要介绍Linux安装MySQL的教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux安装mysql1.Mysql官网2.我的存放路径3.解压mysql文件到当前目录4.重命名一下5.创建mysql用户组和用户并修

Linux上设置Ollama服务配置(常用环境变量)

《Linux上设置Ollama服务配置(常用环境变量)》本文主要介绍了Linux上设置Ollama服务配置(常用环境变量),Ollama提供了多种环境变量供配置,如调试模式、模型目录等,下面就来介绍一... 目录在 linux 上设置环境变量配置 OllamPOgxSRJfa手动安装安装特定版本查看日志在

Linux系统之主机网络配置方式

《Linux系统之主机网络配置方式》:本文主要介绍Linux系统之主机网络配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、查看主机的网络参数1、查看主机名2、查看IP地址3、查看网关4、查看DNS二、配置网卡1、修改网卡配置文件2、nmcli工具【通用

Linux系统之dns域名解析全过程

《Linux系统之dns域名解析全过程》:本文主要介绍Linux系统之dns域名解析全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、dns域名解析介绍1、DNS核心概念1.1 区域 zone1.2 记录 record二、DNS服务的配置1、正向解析的配置

C++中::SHCreateDirectoryEx函数使用方法

《C++中::SHCreateDirectoryEx函数使用方法》::SHCreateDirectoryEx用于创建多级目录,类似于mkdir-p命令,本文主要介绍了C++中::SHCreateDir... 目录1. 函数原型与依赖项2. 基本使用示例示例 1:创建单层目录示例 2:创建多级目录3. 关键注

Linux修改pip和conda缓存路径的几种方法

《Linux修改pip和conda缓存路径的几种方法》在Python生态中,pip和conda是两种常见的软件包管理工具,它们在安装、更新和卸载软件包时都会使用缓存来提高效率,适当地修改它们的缓存路径... 目录一、pip 和 conda 的缓存机制1. pip 的缓存机制默认缓存路径2. conda 的缓

C++从序列容器中删除元素的四种方法

《C++从序列容器中删除元素的四种方法》删除元素的方法在序列容器和关联容器之间是非常不同的,在序列容器中,vector和string是最常用的,但这里也会介绍deque和list以供全面了解,尽管在一... 目录一、简介二、移除给定位置的元素三、移除与某个值相等的元素3.1、序列容器vector、deque

C++常见容器获取头元素的方法大全

《C++常见容器获取头元素的方法大全》在C++编程中,容器是存储和管理数据集合的重要工具,不同的容器提供了不同的接口来访问和操作其中的元素,获取容器的头元素(即第一个元素)是常见的操作之一,本文将详细... 目录一、std::vector二、std::list三、std::deque四、std::forwa