我正在做一个项目,它的依赖关系树如下:
main
|_ libB
|_ libA
由于libB
依赖于来自libA
的头文件,因此我将执行以下操作:
target_link_libraries(libB PRIVATE libA)
但如果我理解正确的话,这意味着在这些库之间创建一个硬依赖关系?
因此在这一行之后,CMake将理解到需要在构建libB
之前完全构建libA
,从而在不需要的地方增加编译时间。
如何使libB
依赖于libA
的include目录,而不同时依赖于libA
的完整编译?
PS:这个用例是我的实际问题的一个非常简化的版本,但它允许我简单地解释它。
4条答案
按热度按时间rpppsulh1#
我只想使用ninja来修复依赖项带来的编译顺序,但是对于没有为此进行优化的构建系统,也有一些变通方法。
解决方法是只添加另一个目标的include目录:
我仍然会添加一条评论,说这只是MSBuild缺乏的一个变通方法。
t2a7ltrp2#
因此在这一行之后,CMake将理解需要在构建libB之前完全构建libA,从而在不需要的地方增加编译时间。
你从哪里得到这个想法的?构建系统如何处理这样的依赖关系取决于构建系统-而不是CMake。CMake只是生成构建系统。CMake可能需要做一些事情来帮助构建系统理解它是什么类型的依赖关系。但一般来说,我认为这是不必要的。只是尝试各种发电机。你我可能会观察到聪明的程序同时为这样的目标编译源代码,只有在链接步骤,两个相互链接的二进制程序才需要准备好链接。
但是对于有很多源代码的目标,您可能不会注意到,即使使用更智能的构建系统,也只是因为您的机器只有这么多内核(您只能获得这么多并行性),并且根据您的机器所具有的内核数量,在某个点上,并行构建多个目标的源代码不会提高速度(当您的目标有足够数量的源文件时)。
如何使libB依赖于libA的include目录,而不同时依赖于libA的完整编译?
如前所述,对于一个智能构建系统,你不需要做任何特殊的事情,让CMake做它的工作,让生成的构建系统做它的工作。
但是,如果您想支持某些内容,可以直接指定target include目录(使用
target_include_directories()
)而不是让CMake使用target_link_libraries
来完成它的工作。但是这样你就不得不使用更多的拐杖来处理链接目标之类的事情...除非没有要链接的东西-在这种情况下,它是一个只包含头文件的库,没有要构建的东西,你所担心的根本不是问题。fdbelqdn3#
在Modern CMake(cmake〉3.0)中,你可以创建INTERFACE库,即“像”库一样工作但不是真实的库的抽象。
这使您可以做您所需要的事情-引用包含文件而不需要实际花费时间进行编译。
Godbolt链接:https://godbolt.org/z/7bea6178Y
bvk5enib4#
我终于找到了一个不需要使用另一台发电机的解决方案。
我一直在使用MSBuild生成Visual Studio解决方案(我并不同意这一点)。
我找到的解决方案是我写的这个函数:
我的项目的更准确布局是:
这里,我有两个INTERFACE库
module
和libs
,以及一个main
可执行文件。libs
中的每个库都依赖于module
,并且main
依赖于libs
。我找到的唯一解决方案是使用我的函数将include目录传播到另一个INTERFACE目标,例如
module_include
:这样,我就可以依靠
module_include
自动获取include目录,而不依赖于每个模块的编译。