如何处理CMake中的递归依赖项 [英] How do you handle recursive dependencies in CMake
问题描述
说我有软件包A,B和C.软件包B使用软件包A,软件包C使用软件包B.我创建共享库.
Say I have packages A, B, and C. Package B uses package A and package C uses package B. I create shared libraries.
所以在程序包B中,我做类似的事情
So in package B I do something like
find_package(A)
...
if(${A_FOUND})
target_link_libraries(B ${A_LIBRARIES})
endif()
我在C包中做
find_package(B)
...
if(${B_FOUND})
target_link_libraries(C ${B_LIBRARIES})
endif()
add_executable(main main.cpp)
target_link_libraries(main C)
其中$ {B_LIBRARIES}仅包含B.编译器现在会抱怨
where ${B_LIBRARIES} contains only B. The compiler will now complain
/usr/bin/ld: cannot find -lA
collect2: error: ld returned 1 exit status
只要将A安装在C的link_directories之外的地方,我想知道什么是正确的处理方法.对我来说,在C中使用 find_package(A)
(可能有效)似乎不太好.特别是对我来说,因为我事先不知道B是否依赖A.它还可能取决于其他程序包.
as long as A is installed in a place that is not in the link_directories of C. I was wondering what is the correct way of handling this. For me using find_package(A)
in C (which would work) doesn't seem to be the nice. For me especially, because I don't know in advance if B depends on A or not. It might also depend on a different package.
推荐答案
此处的问题是 $ {A_LIBRARIES}
应该包含绝对路径.诸如Trilinos之类的软件包提供了 $ {Trilinos_LIBRARY_DIRS}
之类的东西,您应该通过这样做将其包括在内
The problem here is that ${A_LIBRARIES}
should contain absolute paths. Packages like Trilinos provide something like ${Trilinos_LIBRARY_DIRS}
, which you should include in by doing
link_directories(${Trilinos_LIBRARY_DIRS})
但是,根据 https://cmake,这是错误的.org/cmake/help/v3.0/command/link_directories.html . find_package(Trilinos)
应该返回库的绝对路径,因此我不必这样做.我通过做类似的事情来解决了这个问题
This, however, is wrong according to https://cmake.org/cmake/help/v3.0/command/link_directories.html . find_package(Trilinos)
should return absolute paths to the libraries, so I should not have to do this. I fixed this by doing something like
set(library_directories ${Trilinos_LIBRARY_DIRS})
list(APPEND library_directories ${Trilinos_TPL_LIBRARY_DIRS})
set(library_dependencies ${Trilinos_LIBRARIES})
list(APPEND library_dependencies ${Trilinos_TPL_LIBRARIES})
set(found_library_dependencies)
foreach(lib ${library_dependencies})
set(found_${lib})
if(IS_ABSOLUTE ${lib})
set(found_${lib} ${lib})
else()
find_library(found_${lib} ${lib} ${library_directories})
endif()
list(APPEND found_library_dependencies ${found_${lib}})
message(STATUS "Using ${lib}")
message(STATUS "Found in ${found_${lib}}")
endforeach(lib)
我在这里列出了软件包的列表,因此我可以对所有从Trilinos复制了此错误行为的软件包进行此操作.
I made a list of the packages here so I can do this for all my packages which all copied this wrong behaviour from Trilinos.
回到原来的问题.我仍然必须在 $ {B_INCLUDE_DIRS}
中包含 $ {A_INCLUDE_DIRS}
,因此 C
可以找到 A的头文件
包含在 B
的头文件中,但是我可以接受.但是, $ {B_LIBRARIES}
现在不必包含 $ {A_LIBRARIES}
,因为它们是作为共享库构建的.而这正是我想要的.
Coming back on the original problem. I do still have to include the ${A_INCLUDE_DIRS}
in ${B_INCLUDE_DIRS}
, so C
can find the header files of A
that are included in header files of B
, but I can live with this. However, ${B_LIBRARIES}
now does not have to include ${A_LIBRARIES}
, since they were built as shared libraries. And that is exactly what I was looking for.
这篇关于如何处理CMake中的递归依赖项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!