我们正在开发包含数千个cmake文件的项目。代码是在Linux平台上开发的。现在我们正在为Windows CE平台移植这个项目。
在Linux平台上更改某些功能时,我们面临很多链接错误。
我们通过在cmake文件的target_link_library中添加相应的库来解决此链接错误。
我很惊讶它对Linux有用吗?它对Windows CE来说是失败的。
平台附加库之间的区别:
Linux平台
[A.Common]
[B]
[C]
[C]
[C]
[TLV]
[D]
[Boost.Filesystem]
[Boost.System]
[Boost.Thread]
[Boost.Atomic]
[Boost.DateTime]
[Boost.Chrono]
[Platform.Socket]
[D]
[C]
[C]
[Debug]
[SQLite]
[C]
[C]
[C]
[Meta]
[E]
WinCE的
[A.Common]
[B]
[E]
[E]
[E]
[TLV]
[D]
[Boost.Filesystem]
[Boost.System]
[Boost.Thread]
[Boost.Atomic]
[Boost.DateTime]
[Boost.Chrono]
[Platform.Socket]
[D]
[C]
[C]
[Debug]
[SQLite]
[ZLib]
[C]
[C]
[C]
[Meta]
[E]
任何帮助将不胜感激。
答案 0 :(得分:0)
根据我的经验,我可以确认,如果您正确设置了库依赖项,那么使用CMake项目移动到新平台也是一个检查。
如果我们在讨论SHARED
库,请先确认您已正确导出函数声明:
如果您正在使用STATIC
库,我会看到两种可能的方法(不考虑系统库中缺少符号的链接器错误):
您的CMake代码中可能有一些if
语句正在检查此平台或该平台。因此,首先通过激活GLOBAL_DEPENDS_DEBUG_MODE
来检查您的库依赖性是否真的相同:
set_property(GLOBAL PROPERTY GLOBAL_DEPENDS_DEBUG_MODE 1)
将其放在主CMakeList.txt
文件中,并比较两个平台上的输出。
链接顺序也很重要,不仅是库在链接器命令行的某处命名。我想引用Beginner's Guide to Linkers:
要注意的另一个重要细节是事件的顺序;只有在完成正常链接时才会查询库,并按顺序从左到右处理它们。这意味着如果从链接行后期的库中引入的对象需要链接行中较早的库中的符号,则链接器将不会自动找到它。
使用以下CMake测试程序查看链接器是否对打开的符号进行多路径扫描。我用GCC 4.8.1(不起作用)和Visual Studio 2013(确实有效)测试了它。所以我没有你的环境,所以请自己做测试。
该程序是故意设置为使用而不是使用正常的库依赖项(例如target_link_libraries(lib1 lib2)
)具有错误的库链接顺序(经验法则是将所有库直接添加为依赖项头文件来自),但是通过将全局列表中的顺序赋予main
:
cmake_minimum_required(VERSION 2.8)
project(WrongLinkOrderTest CXX)
set(_idx 1)
while (_idx LESS 10)
math(EXPR _next_idx "${_idx} + 1")
file(WRITE lib${_idx}.h "int lib${_idx}_func();")
file(WRITE lib${_idx}.cc "#include \"lib${_next_idx}.h\"\nint lib${_idx}_func() { return lib${_next_idx}_func(); }")
add_library(lib${_idx} lib${_idx}.cc)
# NOTE: This would fix it
#target_link_libraries(lib${_idx} lib${_next_idx})
set(_idx "${_next_idx}")
endwhile()
file(WRITE lib${_idx}.h "int lib${_idx}_func();")
file(WRITE lib${_idx}.cc "int lib${_idx}_func() { return 0; }")
add_library(lib${_idx} lib${_idx}.cc)
file(WRITE main.cc "#include \"lib1.h\"\nint main() { return lib1_func(); }")
add_executable(main main.cc)
if (CMAKE_COMPILER_IS_GNUCXX)
#target_link_libraries(main "-Wl,--start-group")
endif()
while (_idx GREATER 0)
math(EXPR _next_idx "${_idx} - 1")
# NOTE: Here it's done wrong
target_link_libraries(main lib${_idx})
set(_idx "${_next_idx}")
endwhile()
if (CMAKE_COMPILER_IS_GNUCXX)
#target_link_libraries(main "-Wl,--end-group")
endif()
默认情况下,它会在GCC
显示以下错误:
liblib1.a(lib1.cc.obj):lib1.cc:(.text+0x7): undefined reference to `lib2_func()'
取消注释target_link_libraries(lib${_idx} lib${_next_idx})
或--start-group
/ --end-group
行以解决此问题。
其他参考资料