如何指定头文件引入的库依赖关系 [英] How to specify library dependency introduced by header file

查看:70
本文介绍了如何指定头文件引入的库依赖关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设在CMake项目中,我有一个内置在库中的源

Suppose in a CMake project, I have a source that is built into a library

// 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包含:

The CMakeLists.txt contains:

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中调用函数。如果lot文件包含bh,则手动找出所有此类依赖项对于大型项目。

Now look at the last line of the CMakeLists.txt: I need to specify A as the dependencies of main explicitly. Basically, I need to specify such dependencies for every source that includes b.h. Since the includes can be indirect and go all the way down through a chain of includes. For example, a.cpp calls a class inline function of c.h, which in turns calls function in d.h, etc, and finally calls function from library A. If b.h is included by lots files, manually finding out all such dependencies is not feasible for large projects.

所以我的问题是,是否有必要指定每个直接或间接包含标头的源文件都需要链接到某些库?

So my question is, is there anyway to specify that, for every source file that directly or indirectly includes a header, it needs to link against certain library?

谢谢。

推荐答案

要弄清楚一件事:您a.cpp得到编译成lib A。这意味着A的任何用户都需要为A指定 target_link_libraries 。没有办法。如果您有10个使用A的小应用程序,则需要指定 target_link_libraries 十次。

To make one thing clear: You a.cpp gets compiled into a lib "A". That means that any user of A, will need to specify target_link_libraries with A. No way around it. If you have 10 little applications using A, you will need to specify target_link_libraries ten times.

我的答案与您的问题的第二期,我相信它是更重要的:

My answer deals with the second issue of your question and I believe it is the more important one:

如何摆脱包含链?

通过在bh中包含ah并在bh中使用其方法,您将添加隐式依赖项。如您所见,b.h的任何用户也需要a.h。广义上讲,有两种方法。

By including a.h in b.h and using its method in b.h you are adding a "implicit" dependency. As you noticed, any user of b.h needs a.h as well. Broadly speaking, there are two approaches.

这与CMake无关,但与封装有关。您的库用户(包括您自己)无需担心其内部实现。这意味着:请勿在a.h中包含b.h。

This has nothing to do with CMake, but is about encapsulation. The users of your library (incl. you yourselves) should not need to worry about its internal implementation. That means: Don't include b.h in a.h.

相反,将include移至.cpp文件。这样,您就可以打破链条。例如。像

Instead, move the include to a .cpp file. This way, you break the chain. E.g. something like

// b.h
void f();
struct X
{ 
    void g();
};

// b.cpp
#include b.h
#include a.h
void X::g( )
{
    f();
}

这样,在cpp文件中包含了ah的使用,使用您的库的任何人都只需包含bh并链接到b.lib。

This way, the use of a.h is "contained" in the cpp file and anyone using you library need only include b.h and link to b.lib.

现在,在某些情况下,您必须接受这种依赖,或者这是一个有意识的选择。例如。当您无法控制A或有意识地决定创建一个根据A内部的类/结构定义的库时。

Now, there are situations where you have to accept such a "dependency" or where it is a conscious choice. E.g. when you have no control over A or when you conciously decided to create a library defined in terms of classes/structs internal to A.

在这种情况下,我建议您编写一段CMake代码,它准备了链下所有必要的包含目录。例如。在 YourLibConfig.cmake中定义变量 YOURLIB_INCLUDES和 YOURLIB_LIBRARIES,并记录库的任何用户都应导入 YourLibConfig.cmake。这是一些基于cmake的项目采用的方法。例如。 OpenCV安装 OpenCVConfig.cmake 文件,VTK安装 VTKConfig.cmake 并准备 UseVTK .cmake 文件

In that case, I suggest you write a piece of CMake code, which prepares all the necessary include-dirs down the chain. E.g. define a variable "YOURLIB_INCLUDES" and "YOURLIB_LIBRARIES" in "YourLibConfig.cmake" and document that any user of your library should import "YourLibConfig.cmake". This is the approach several cmake-based projects take. E.g. OpenCV installs a OpenCVConfig.cmake file, VTK installs a VTKConfig.cmake and prepares a UseVTK.cmake file

这篇关于如何指定头文件引入的库依赖关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆