c++ - CMake:包含外部 makefile 时的编译速度

标签 c++ makefile build cmake

我有一个 C++ cmake 项目。在这个项目中,我构建(除其他外)一个示例,我需要在其中使用另一个项目,将其称为 Foo。此 Foo 项目不提供 cmake 构建系统。相反,它有一个预制的 Makefile.custom.in。为了构建一个使用 Foo 特性的可执行文件,需要在他的项目中复制这个 makefile,并修改它(通常设置 SOURCES 变量和一些编译器标志)。基本上,这个 Makefile 最终包含您的可执行文件的源代码以及 Foo 项目的所有源文件。您最终不会将 Foo 用作库。

现在,这是一个我不喜欢的设计,但为了这个问题,假设我们坚持使用它。

为了在我的 cmake 构建中创建我的示例,我添加了一个自定义目标:

CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/Makefile.custom.in Makefile.custom)

ADD_CUSTOM_TARGET(my_target COMMAND $(MAKE) -f Makefile.custom
                  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})

这行得通。我可以为 cmake 指定一些变量,这些变量在对 CONFIGURE_FILE 的调用中得到解析,我最终得到一个有效的 Makefile.custom。然后,从构建目录调用 make my_target,我可以构建可执行文件。我什至可以将它添加到 all 目标(以节省我键入​​ make my_target 的精力)

SET_TARGET_PROPERTIES(my_target PROPERTIES EXCLUDE_FROM_ALL FALSE)

甜甜的。但是,cmake 似乎将单个作业分配给自定义目标,从而减慢了我的编译时间(Foo 源文件夹包含几十个 cpp 文件)。最重要的是,make clean 目标不会转发到自定义 makefile。我最终不得不添加另一个目标:

ADD_CUSTOM_TARGET(really-clean COMMAND "$(MAKE)" clean
                  COMMAND "$(MAKE)" -f Makefile.custom clean
                  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})

my_targetall 不同,我不能将其包含在 clean 目标中(可以吗?)。

现在,我知道一个更简洁的解决方案是将 Foo 项目构建为外部项目,然后链接到它。然而,我被“推荐”使用他们的 Makefile.custom.in makefile,修改我需要的几行(添加我的源代码,指定编译器标志,以及其他一些小的修改)。因此,无论这种设计模式多么整洁干净,我的问题是:

  • 有没有办法告诉 cmake make 在制作目标 my_target 时应该使用超过 1 个作业?
  • 是否有更简洁的方法将预先存在的 makefile 包含在 cmake 项目中?请注意,我不想(不能?)将 Foo 用作库(并链接到它)。我想(需要?)使用不是由 cmake 生成的 makefile 将它与我的可执行文件一起编译(好吧,cmake 可以通过 CONFIGURE_FILE 解决一些变量,但仅此而已)。

注意:我知道 ExternalProject(同样在 this 回答中建议),但我认为这并不是我在这里需要的(因为它会构建 Foo 然后将其用作图书馆)。此外,我的项目和 Foo 都是专门用 C++ 编写的(完全不确定这个问题)。

我希望这个问题是有道理的(不管最终的设计有多丑陋/烦人/不令人满意)。

编辑:我使用的是 cmake 版本 3.5.2

最佳答案

首先,由于您定义了自己的目标,您可以直接在 CMakeLists.txt 中为目标 my_target 的构建过程分配更多核心。
您可以包含 Cmake 模块 ProcessCount 以确定机器中的内核数量,然后将其用于并行构建。

include(ProcessorCount)
ProcessorCount(N)
if(NOT N EQUAL 0)
  # given that cores != 0 you could modify
  # math(EXPR N "${N}+1")  # modify (increment/decrement) N at your will, in this case, just incrementing N by one
  set(JOBS_IN_PARALLEL -j${N})
endif(NOT N EQUAL 0)

当你定义你的自定义目标时有如下内容:

ADD_CUSTOM_TARGET(my_target 
                  COMMAND ${CMAKE_MAKE_PROGRAM} ${JOBS_IN_PARALLEL} -f Makefile.custom
                  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})

顺便说一下,我认为您没有必要在目标的 COMMAND 中也包含 CMAKE_BUILD_TOOL
我相信您可以调用

而不是像上面那样修改行
make -j8 my_target  

它可能会在不修改 CMakeLists.txt 的情况下启动 8 个作业(只是一个例子),但我不能保证这个工作已经按照你的方式定义了 COMMAND,如果足够的话就试试吧。< br/> 对于第二点,我现在想不出“更清洁”的方法。

关于c++ - CMake:包含外部 makefile 时的编译速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41816836/

相关文章:

c++ - Make 无法识别正在修改的文件

jenkins - 路径中的符号和百分号

build - Erlang 的标准构建工具是什么?

c++ - 并发可变优先级队列

c++ - 线程调用函数模板时的编译错误(对于默认参数)

c++ - 为什么类的默认构造函数和析构函数是内联的?

postgresql - Makefile:运行命令“go test./…”后终止

c# - .Net Core 为不同的构建配置启动

c# - 大型客户端/服务器项目布局和 Ivy 设置的建议

c++ - 线程取消 (pthread) & C++