链接对象ST 的CubeIDE 发出如下命令:
arm-none-eabi-g++ -mcpu=cortex-m33 --specs=nosys.specs -Wl,-Map=mymap.map -Wl,--gc-sections -static --specs=nano.specs -mfpu=fpv5-sp-d16 -mfloat-abi=hard -mthumb -Wl,--start-group -lc -lm -lstdc++ -lsupc++ -Wl,--end-group -Tmyldscript.ld @myobjects.txt -o myelf.elf
我试图理解为什么他们使用-Wl
多次和--start-group
/ --end-group
。这样做有什么正当理由吗?这个命令可以简化吗?
—Wl
-Wl
被多次使用是因为每次需要告诉 GCC 将一个或多个链接器选项直接传递给链接器时都需要它,ld
而不是尝试遵循选项本身(并且可能给出未知选项错误)。是 GCC 选项,表示传递
<linker-option> [<linker-option>...]
给链接器。请参阅GCC 手册:3.15 链接选项。--启动组/--结束组
用法如下:
是成对的链接器选项。默认情况下,链接器仅在首次输入静态库时将静态库视为解析链接迄今为止累积的未定义符号引用的候选,并且永远不会再次输入(除非再次输入该库)。这些选项
--start-group/--end-group
告诉链接器暂停其对封闭的静态库序列的默认策略-liba [-libb...]
,而是循环考虑和重新考虑它们,解析未定义的引用并累积新的引用,直到没有新的引用累积。请参阅GNU ld 手册:2.1 命令行选项--start-group/--end-group
当所包含的静态库之间存在循环依赖关系时-liba [-libb...]
,这些依赖关系是必需的,这意味着,如果每个库在第一次看到时只被考虑一次,则链接器不可能解析由它们的链接引起的所有未定义引用。这种循环依赖关系是不常见的,并且表明库设计考虑不周。--start-group/--end-group
虽然不是必需的,但当其中不存在任何循环依赖关系时,它们很有用-liba [-libb...]
,但组成链接命令行的人员或构建系统不知道这一点,也不知道在默认策略下输入库的成功顺序。如果
--start-group/--end-group
用于“强制”成功链接无序库,而这些库本来可以按照链接器的默认策略的依赖顺序输入,那么就会产生一些效率低下的问题:链接器必须重新访问那些如果按照正确的顺序输入就不需要重新访问的库。通常,仅通过查看链接命令行无法判断是否需要使用
--start-group/--end-group
,因为仅通过查看封闭是否包含循环依赖项无法判断-liba [-libb...]
。“高级”构建系统(例如 CMake、Meson 等)可能会对--start-group/--end-group
链接中的库序列施加自己的默认策略,以强制成功链接构建系统不想坚持由用户按依赖顺序排列的静态库。--start-group -liba [-libb...] --end-group
对共享的封闭库(不是静态库)没有影响,但构建系统可能会将它们封闭,因为即使所有库都是共享库,这也是无害的。 在您的例子中,所有库选项:必须解析为静态库,因为该选项
-static
已经预先指定。这个命令可以简化吗?
片段:
可以重写为:
少用一个
-Wl
。这是因为该选项-l lib
既是 GCC 的选项,也是链接器的选项,对两者的含义相同。(事实上,它是一种非常常用的链接器选项,GCC 会将其传递给链接器而不需要-Wl
。其他此类链接器选项是-L dir
和-static
)。然而,通常-Wl
只应用于 GCC自身无法识别的链接器选项。在链接中使用
--start-group/--end-group
是一种强制使用。如果没有它,库可以按照依赖顺序进行链接: