这是一个奇怪的问题。我有一个"渲染器前端"静态目标和几个"渲染器后端"静态目标。 "渲染器前端"包含后端需要实现的头文件,前端的代码将调用它们。后端通过调用底层相应的API(例如,OpenGL或DirectX)来实现这些功能。
到目前为止,这么好。我可以在编译时选择后端并将其链接到前端。但是,我决定在前端添加单元测试,这需要一个"虚拟后端"而不是为主程序配置的后端。
所以不要这样做:
if(${RendererBackend} STREQUAL "OpenGL")
target_link_libraries(Renderer RendererBackendGL)
elseif(...)
...
end
target_link_libraries(Application Renderer)
我想这样做:
target_link_libraries(Application Renderer)
target_link_libraries(RendererTest Renderer RendererBackendDummy)
if(${RendererBackend} STREQUAL "OPENGL")
target_link_libraries(Application RendererBackendGL)
elseif(...)
...
end
但是,我的程序有"未定义的引用"每当渲染器前端调用由GCC下的后端实现的函数时,链接错误。该程序在MSVC下运行良好。
编辑:
我检查了链接命令,它是这样的:
/usr/bin/g++ CMakeFiles/Demo.dir/src/main.cpp.o -o Demo -rdynamic -lm -ldl /usr/lib/x86_64-linux-gnu/libX11.so -lpthread ../Engine/OpenGL/libRendererBackendGL.a ../Engine/Graphics/libRenderer.a
问题是"渲染器"在" RendererBackendGL"。
中定义的库调用函数答案 0 :(得分:3)
您的依赖项建模不正确。
如果Renderer
调用RendererBackendGL
中的函数,则需要在CMake中建模该关系:
target_link_libraries(Renderer PUBLIC RendererBackendGL)
target_link_libraries(Application PRIVATE Renderer)
是的,这意味着每个链接到Renderer
的人都需要链接到后端,包括测试。但这是您的软件架构的问题,即。在Renderer
内调用了后端函数,而不是CMake的问题。
gcc中断的原因是链接器命令行上指定输入库的顺序很重要。对于MSVC来说情况并非如此(只要存在lib,它就会起作用,无论它是第一个还是最后一个)。由于此类顺序依赖性是特定于工具链的,因此实现此可移植性的唯一方法是通过在CMake中正确地建模所有目标间依赖关系。
那你现在可以做些什么来解决这个问题呢?我想到了一些选择:
请注意,所有这些都需要对代码进行一些架构更改。因此,在开始重构之前,请务必考虑所有影响。