【发布时间】:2011-10-02 02:12:26
【问题描述】:
我在正确链接 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
【问题讨论】:
-
这应该用您正在使用的特定 c 编译器或链接器进行标记,因为这不是语言的特性,而是程序的特性。
-
(1) 你得到一个名为“Tests.c.o”的文件很奇怪。通常(例如使用 gcc),您会像这样编译:
gcc -c Tests.c,这将生成一个名为“Tests.o”的目标文件。 (2) 我在您的问题中没有看到 C99 特有的内容;据我所知,这同样适用于 C90。 (3) 你问题第一行的~字符有什么意义吗? -
我添加了 c99 作为标签,因为我正在使用 c99 std 进行编译,但我不确定这是否相关。 ~ 根本不相关(为了清楚起见,现在删除了),正如我提到的,我正在使用 cmake,它会生成详细的目标文件路径 (Tests.c.o),如所述。