如何在C中正确链接以阻止符号被剥离?

时间:2011-10-02 02:12:26

标签: c gcc

我在与C中的库正确链接时遇到了一些问题。

我确信这是我不完全理解的那些神秘的C链接规则之一,但我无法理解。

我有libn,我编译成静态库libn.a

nm libn显示:

doug@ninja:~/projects/libnw/build$ nm ../../libn/build/libn.a |grep nIndex
00000034 T nIndex
00000000 D nIndex_
00000026 T nIndex_finalize
00000013 T nIndex_init
00000000 T nIndex_map

我也有libnw,这取决于libn。 libnw上的nm显示:

doug@ninja:~/projects/libnw/build$ nm libnw.a |grep Index
         U nIndex

然而,当我编译一个针对libnw和libn的编程链接时,我得到:

doug@ninja:~/projects/libnw/build$ make
[ 70%] Built target nw
[ 80%] Built target test-template
Scanning dependencies of target test-Core
[ 85%] Building C object tests/nw/mvc/Core/CMakeFiles/test-Core.dir/Tests.c.o
[ 90%] Building C object tests/nw/mvc/Core/CMakeFiles/test-Core.dir/test.c.o
Linking C executable test-Core
../../../../libnw.a(Impl.c.o): In function `nwCore__Impl_init':
/home/doug/projects/libnw/src/nw/mvc/Core/Impl.c:76: undefined reference to `nIndex'
collect2: ld returned 1 exit status
make[2]: *** [tests/nw/mvc/Core/test-Core] Error 1
make[1]: *** [tests/nw/mvc/Core/CMakeFiles/test-Core.dir/all] Error 2
make: *** [all] Error 2

原因很清楚。当Tests.c - > Tests.c.o,它没有选择nIndex作为它需要保留的符号:

doug@ninja:~/projects/libnw/build$ nm tests/nw/mvc/Core/CMakeFiles/test-Core.dir/Tests.c.o 
         U MyController
000005a4 T Tests
00000000 D Tests_
00000125 T Tests_can_attach_controller
00000080 T Tests_can_create_core
000003d3 T Tests_can_handle_native_event
000001c8 T Tests_can_set_controller
00000322 T Tests_can_update
00000000 t Tests_core_factory
0000056c T Tests_finalize
000005c0 T Tests_getType
0000048c T Tests_init
         U nFactory
         U nTest
         U nType_nalloc
         U nType_nfree
         U nwCore
         U nwDummyContext_getType
         U nwDummyEvents_getType
         U nwDummyRender_getType
         U nwIContext_getType
         U nwIEvents_getType
         U nwIRender_getType

(注意测试对象文件中完全没有U nIndex)。

所以,我可以通过在我的测试脚本中添加对nIndex()的调用来轻松解决这个问题,但这并不能解决基本问题:

程序依赖于liba依赖于libb,liba缺少需要解析的libb符号,但是程序没有对这些符号的引用,所以它们似乎被剥离了。

我做错了什么?

(是的,我正在使用cmake并依赖于静态构建的libn和libnw版本)。

编辑:

现在使用链接器行:

/usr/bin/gcc  -std=c99 -g   CMakeFiles/test-Core.dir/Tests.c.o \
      CMakeFiles/test-Core.dir/test.c.o \
      CMakeFiles/test-Core.dir/helpers/MyController.c.o \
      CMakeFiles/test-Core.dir/helpers/MyModel.c.o \
      -o test-Core -rdynamic \
      /home/doug/projects/tapspin-android/source/deps/libn/build/libn.a \
      ../../../../libnw.a 

3 个答案:

答案 0 :(得分:5)

我没有看到你链接线,所以我很难确定,但这似乎可能是一个订购问题

如果libb所需的所有符号都在liba中,那么您应首先列出libb,以便将它们列为要解析的符号,当访问libb时,他们将得到解决。这不是剥离本身,它只是不包括(即它是一个遗漏不是主动删除,我分裂头发?也许)

此外,有时如果存在周期性依赖(liba需要libb中的某些符号而libb需要来自liba的某些符号),则必须列出多个库时 (这不是cmake答案,因为我不使用cmake,但使用了连接器多年,这是一个常见的错误。)

请注意,与库中的符号不​​同,目标文件中的所有符号都是链接的

最简单的尝试首先尝试只是交换两个库的顺序

答案 1 :(得分:1)

由于这是链接顺序的问题,您也可以使用

解决它

- 启动组

- 端基

GCC: what are the --start-group and --end-group command line options?

只要我们谈论静态库/存档文件,它就可以工作。

答案 2 :(得分:1)

要查找依赖库的正确顺序,可以使用以下* nix命令管道:

lorder libA.a libB.a ... | tsort

如果有一个关于循环引用的错误,那么虽然使用--start-group和--end-group的上述GCC kludge可以工作,或者只是第二次列出有问题的库,但是真的应该修复库,因此它们没有周期性依赖。