gcc -u 符号编译器选项

Posted

技术标签:

【中文标题】gcc -u 符号编译器选项【英文标题】:gcc -u symbol compiler option 【发布时间】:2016-08-18 13:34:52 【问题描述】:

我们什么时候使用 gcc -u 编译器选项? 你也可以举个例子吗?

https://gcc.gnu.org/onlinedocs/gcc-2.95.2/gcc_2.html 说如下:

假装符号符号未定义,强制链接库 模块来定义它。你可以多次使用不同的`-u' 符号来强制加载额外的库模块。

【问题讨论】:

我们不使用它——几乎从不使用它。 (在过去的 30 年里,我不需要使用它,AFAICR。)当你需要它时,你就会知道该怎么做。在那之前,不要担心。 GCC 有很多其他类似的选项——如果你需要做一些神秘的事情,它们是非常宝贵的,但 99.99% 的时间是不相关的。 @JonathanLeffler,我目前确实需要它,但我终生无法弄清楚如何让它发挥作用。我正在尝试构建一个动态库,该动态库在头文件中具有一个函数,该函数需要静态库中的单个符号,但是由于它在头文件中,它不会自动为我链接静态库,因为从技术上讲,当我编译我的library 该符号尚未使用。这意味着我的库的客户必须知道链接静态库...您知道如何使“-u”选项起作用吗?或者更好的是,您对我的问题有更好的解决方案吗? @tjwrona1992:我想我可能会创建一个包含#include "header.h" 的文件libname.c,然后使用通常的规则在您的平台上构建一个共享库,可能使用列出的静态库创建共享库的命令行。我不相信这会奏效。让共享库从静态库中调用符号可能意味着必须将静态库链接到可执行文件中,共享库才能找到该符号。这就是共享库和静态库之间的区别;你不能只按需加载静态的。 您可能需要使用:gcc -u staticlibsymbol -o prog obj1.o … -ldynamic -lstatic …(其中libdynamic.so 或任何用于共享对象,libstatic.a 是静态库),这可能会导致符号 staticlibsymbol 来自要链接到可执行文件的静态库,以便在运行时对动态库可用。如果您已经尝试过,那么您可能需要使用 MCVE (minimal reproducible example) 就 SO 提出一个新问题。它可以合法地交叉引用这个问题——我几乎说 Q&A,但这里没有正式的 A。 问题中的链接是编译器的古老版本。但是,您可以从Linker Options 上的 GCC 8.2.0 手册中获得大致相同的信息。 【参考方案1】:

通常在链接对象期间,在提供的模块(即,来自编译的档案和其他对象文件)中搜索 undefined 符号,并且仅搜索最低满足整个集合所需的符号未定义的符号是从提供的模块中提取的。

这在实践中意味着如果你有例如目标文件中的函数 foo(),除非 foo() 在最终链接产品的其他地方使用,否则它不会被包含在内。这通常是所需的行为。

如果您有一个模块提供了一些功能,这些功能在最终链接产品的其他任何地方都没有引用,但您仍然希望包含这些功能,那该怎么办? (例如,也许这些函数被设计为直接从调试器调用)。这就是-u 选项派上用场的地方。它有效地告诉链接器存在对 foo() 的不满足引用,从而触发将其包含到最终链接的产品中,尽管代码中没有引用该符号。

示例:

让我们定义两个函数,foobar,并将每个函数放在一个单独的模块中,然后是一个仅引用 foo 的简短程序。尽管我们将libfoo.alibbar.a 都链接到程序中,但对程序(a.out)符号的检查显示bar 并未包括在内。

foo.h:

void foo(void);

foo.c:

void foo(void)  

bar.h:

void bar(void);

bar.c:

void bar(void)  

main.c:

#include "foo.h"
#include "bar.h"
int main(int argc, char** argv) 
    foo();
    return 0;

构建:

gcc -c foo.c bar.c main.c
ar -r libfoo.a foo.o
ar -r libbar.a bar.o
# For macOS, replace -shared with -dylib
ld -shared main.o -L . -lfoo -lbar
nm -g --defined-only a.out

> T _main
> T _foo

现在,如果我们只修改链接器阶段,并告诉它添加对bar 的未定义引用(使用其链接名称,前缀将带有下划线),这次我们将在最终产品,即使它没有在程序中引用:

# For macOS, replace -shared with -dylib
ld -shared -u _bar main.o -L . -lfoo -lbar
nm -g --defined-only a.out

> T _main
> T _foo
> T _bar

【讨论】:

以上是关于gcc -u 符号编译器选项的主要内容,如果未能解决你的问题,请参考以下文章

如何修改传递给 ld 的选项,而不重新编译 gcc

Linux(程序设计):05---gcc的基本用法

在gcc中定义符号常量

在编译时重命名符号而不以跨平台方式更改代码

GCC选项

gcc 编译器标志和符号表之间的不兼容函数地址