Mac OS X上的弱符号链接

Rob*_*bin 10 macos linker linker-errors weak

目前我在使用Xcode 4.0.2的Mac OS X 10.6.7上遇到了弱链接问题.

robin@chameleon:/tmp/o$ gcc --version
i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5666) (dot 3)
Run Code Online (Sandbox Code Playgroud)

正如文档http://developer.apple.com/library/mac/#technotes/tn2064/_index.html所说,我们可以使用gcc 属性((weak_import))作为弱链接符号.但是,以下示例代码始终抛出编译错误.如下:

weak.c:

#include <stdlib.h>
#include <stdio.h>

extern int SayHello() __attribute__((weak));

int main()
{
    int result;

    if (SayHello!=NULL)
    {
        printf("SayHello is present!\n");
        result=SayHello();
    }
    else
        printf("SayHello is not present!\n");
}
Run Code Online (Sandbox Code Playgroud)

错误消息如下:

robin@chameleon:/tmp/o$ gcc weak.c 
Undefined symbols for architecture x86_64:
  "_f", referenced from:
      _main in cceOf2wN.o
     (maybe you meant: __dyld_func_lookup)
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)

即使使用选项-undefined dynamic_lookup,它仍会在运行时抛出错误:

robin@chameleon:/tmp/o$ gcc -undefined dynamic_lookup weak.c 
robin@chameleon:/tmp/o$ ./a.out 
dyld: Symbol not found: _SayHello
  Referenced from: /private/tmp/o/./a.out
  Expected in: dynamic lookup

Trace/BPT trap
Run Code Online (Sandbox Code Playgroud)

nm -m"a.out" 的消息如下:

robin@chameleon:/tmp/o$ nm -m a.out  | grep Hello

(undefined) external _SayHello (dynamically looked up)
Run Code Online (Sandbox Code Playgroud)

预计如下:

(undefined) weak external _SayHello (dynamically looked up)
Run Code Online (Sandbox Code Playgroud)

但是,当我使用gcc(Ubuntu/Linaro 4.4.4-14ubuntu5)4.4.5在Ubuntu上编译时,它按预期工作:

weak.c:

#include <stdlib.h>
#include <stdio.h>

extern int SayHello() __attribute__((weak));

int main()
{
    int result;

    if (SayHello!=NULL)
    {
        printf("SayHello is present!\n");
        result=SayHello();
    }
    else
        printf("SayHello is not present!\n");
}
Run Code Online (Sandbox Code Playgroud)

  robin @ robinz:/ tmp/o $ gcc weak.c robin @ robinz:/ tmp/o $ ./a.out SayHello不存在!

SayHello二进制符号是:

robin@robinz:/tmp/o$ nm a.out | grep Hello
w SayHello
Run Code Online (Sandbox Code Playgroud)

"w"符号是一个弱符号,未被特别标记为弱对象符号.

我测试旧的xcode 3.2,它按预期工作.

有人可以帮我吗?这是ld的错误吗?

我发现了更多感兴趣的东西.当我创建一个虚拟的lib来导出动态库中的SayHello符号时,它按预期工作.

dummy.c:

int SayHello() {
    return;
}
Run Code Online (Sandbox Code Playgroud)

 

robin@chameleon:/tmp/o$ gcc -dynamiclib -o libdummy.dylib dummy.c 
robin@chameleon:/tmp/o$ gcc weak.c libdummy.dylib 
robin@chameleon:/tmp/o$ ./a.out 
SayHello is present!
Run Code Online (Sandbox Code Playgroud)

如果"libdummy.dylib"不存在:

robin@chameleon:/tmp/o$ rm libdummy.dylib 
robin@chameleon:/tmp/o$ ./a.out 
SayHello is not present!
Run Code Online (Sandbox Code Playgroud)

按预期工作!现在在nm消息中的弱符号,如预期的那样:

robin@chameleon:/tmp/o$ nm -m a.out | grep Hello

                 (undefined) weak external _SayHello (from libdummy)
Run Code Online (Sandbox Code Playgroud)

Jam*_*ner 0

今天,在没有该选项的 GCC 12 和 Clang 14 上仍然会出现错误-undefined dynamic_lookup

Undefined symbols for architecture arm64:
  "_SayHello", referenced from:
      _main in weak-518bb6.o
ld: symbol(s) not found for architecture arm64
Run Code Online (Sandbox Code Playgroud)

但它与选项集一起正常工作:

% gcc-12 -undefined dynamic_lookup  -o weak weak.c && ./weak
ld: warning: -undefined dynamic_lookup may not work with chained fixups
SayHello is not present!
% cc -undefined dynamic_lookup  -o weak weak.c && ./weak
ld: warning: -undefined dynamic_lookup may not work with chained fixups
SayHello is not present!

gcc-12 (Homebrew GCC 12.2.0) 12.2.0
Apple clang version 14.0.0 (clang-1400.0.29.102)
Run Code Online (Sandbox Code Playgroud)

C0deH4cker 在评论中指出了这个链接。它详细介绍了该问题,包括一些解决方法。