gpt4 book ai didi

c++ - Cmake:在没有直接 target_link_libraries 的情况下使用来自另一个目标的函数

转载 作者:行者123 更新时间:2023-11-30 02:23:36 26 4
gpt4 key购买 nike

这是一个奇怪的问题。我有一个“渲染器前端”静态目标和几个“渲染器后端”静态目标。 “renderer frontend”包含后端需要实现的头文件,前端的代码会调用它们。后端通过调用底层相应的 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 下实现的函数时,我的程序就会出现“ undefined reference ”链接错误。尽管该程序在 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”中定义的“Renderer”库调用函数。

最佳答案

您的依赖项建模不正确。

如果 RendererRendererBackendGL 调用函数,您需要在 CMake 中为该关系建模:

target_link_libraries(Renderer PUBLIC RendererBackendGL)
target_link_libraries(Application PRIVATE Renderer)

是的,这意味着每个链接到 Renderer 的人也需要链接到后端,包括测试。但这是您的软件架构的问题,即。在 Renderer 中调用后端函数,这不是 CMake 的问题。

这在 gcc 中中断的原因是在链接器命令行上指定输入库的顺序很重要。这对 MSVC 来说并非如此(只要 lib 存在,它就会起作用,无论它出现在最前面还是最后)。由于此类顺序依赖性是特定于工具链的,因此实现这种可移植性的唯一方法是在 CMake 中正确地明确建模所有目标间依赖性。

那么您现在可以做什么来解决这个问题呢?我想到的一些选项:

  • 翻转依赖项。让后端依赖于前端,并且应用程序仅链接到它想要使用的后端。
  • 转向插件概念。前端不是静态链接,而是在运行时从共享库动态加载它想要使用的后端。
  • 在编译时选择一个特定的后端。这意味着,如果您仍想在同一个构建步骤中构建具有 GL 后端的应用程序和具有虚拟后端的测试,您将需要构建前端两次。这可能是最接近您当前尝试执行的方法。您可以使用 object libraries以尽量减少前端的重新编译量,但您最终仍会得到多个前端库目标。

请注意,所有这些都需要对您的代码进行一定程度的架构更改。因此,请务必在开始重构之前考虑所有影响。

关于c++ - Cmake:在没有直接 target_link_libraries 的情况下使用来自另一个目标的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46046443/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com