假设在CMake项目中,我有一个内置于库中的源
// a.cpp
void f() { /* some code*/ }
我有一个标题
// b.h
void f();
struct X { void g() { f(); } };
我有另一个档案:
// main.cpp
#include "b.h"
int main() { X x; x.g(); }
CMakeLists.txt包含:
add_library(A a.cpp)
add_executable(main main.cpp)
target_link_libraries(main A)
现在看一下CMakeLists.txt的最后一行:我需要明确指定A作为main的依赖项。基本上,我需要为包含b.h的每个源指定这样的依赖项。由于包含可以是间接的,并且通过一系列包含一直向下。例如,a.cpp调用ch的类内联函数,它依次调用dh中的函数等,最后从库A中调用函数。如果批量文件包含bh,则手动查找所有这些依赖项是不可行的。大项目。
所以我的问题是,无论如何要指出,对于每个直接或间接包含标题的源文件,它需要链接某个库吗?
感谢。
答案 0 :(得分:2)
要明确一点:你将a.cpp编译成lib“A”。这意味着A的任何用户都需要用A指定target_link_libraries
。没办法解决它。如果您有10个使用A的小应用程序,则需要指定target_link_libraries
十次。
我的回答是关于你问题的第二个问题,我认为这是更重要的问题:
如何摆脱包含链?
通过在b.h中包含a.h并在b.h中使用它的方法,你将添加一个“隐式”依赖项。正如您所注意到的,b.h的任何用户也需要a.h.从广义上讲,有两种方法。
这与CMake无关,而是与封装有关。您图书馆的用户(包括您自己)不应该担心其内部实施。这意味着:不要在a.h中包含b.h.
相反,将include移动到.cpp文件。这样,你打破了链条。例如。
之类的东西// b.h
void f();
struct X
{
void g();
};
// b.cpp
#include b.h
#include a.h
void X::g( )
{
f();
}
这样,a.h的使用被“包含”在cpp文件中,任何使用你库的人只需要包含b.h并链接到b.lib。
现在,有些情况下你必须接受这种“依赖”或者是有意识的选择。例如。当你无法控制A或者你有意识地决定创建一个根据A内部的类/结构定义的库时。
在这种情况下,我建议你写一段CMake代码,准备所有必要的包括dirs链。例如。在“YourLibConfig.cmake”中定义变量“YOURLIB_INCLUDES”和“YOURLIB_LIBRARIES”,并记录您的库的任何用户应导入“YourLibConfig.cmake”。这是几个基于cmake的项目所采用的方法。例如。 OpenCV安装OpenCVConfig.cmake
文件,VTK安装VTKConfig.cmake
并准备UseVTK.cmake
文件