我在与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
Run Code Online (Sandbox Code Playgroud)
我也有libnw,这取决于libn.libnw上的nm显示:
doug@ninja:~/projects/libnw/build$ nm libnw.a |grep Index
U nIndex
Run Code Online (Sandbox Code Playgroud)
但是,当我编译一个针对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
Run Code Online (Sandbox Code Playgroud)
原因很清楚.当Tests.c - > Tests.co时,它并没有选择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
Run Code Online (Sandbox Code Playgroud)
(注意测试对象文件中完全没有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
Run Code Online (Sandbox Code Playgroud)
我没有看到你链接线,所以我很难确定,但这似乎可能是一个订购问题
如果所需的所有符号libb都在liba,则应libb首先列出,以便将它们列为要解析的符号,并且在libb访问它们时将解析它们.这不是剥离本身,它只是不包括(即它是遗漏不是主动删除,我分裂头发?也许)
此外,有时如果存在循环依赖(liba需要一些符号libb并且libb需要一些符号liba),则必须多次列出库(这不是cmake我不使用的答案cmake,但是使用了多年的连接器,这里是一个常见的错误).
请注意,与库中的符号不同,目标文件中的所有符号都是链接的
最简单的尝试首先尝试只是交换两个库的顺序