如何指定头文件引入的库依赖项

时间:2012-10-28 09:55:51

标签: cmake build-automation

假设在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.cp​​p调用ch的类内联函数,它依次调用dh中的函数等,最后从库A中调用函数。如果批量文件包含bh,则手动查找所有这些依赖项是不可行的。大项目。

所以我的问题是,无论如何要指出,对于每个直接或间接包含标题的源文件,它需要链接某个库吗?

感谢。

1 个答案:

答案 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文件