Ninja 作为构建工具比 Make 更先进且更有助于调试。
但是,由于右-右-右-右-左的模式,输入
ninja
的速度要慢得多,而 make
的右-左-右-左的模式则非常快。我想在使用 make
构建时打字
ninja
。
我有几个项目,由于历史原因,我必须使用 make 或 ninja,我想将所有项目标准化为
make
。
我考虑过使用一些 shell 技巧,比如
alias make='/bin/make || ninja'
但有一些缺点:
它们始终依赖于手动或 .bashrc 设置环境变量。我不想那样做。
别名取决于了解
make
和 ninja
二进制文件的位置
所以我正在考虑将 something 添加到我的 CMakeLists.txt 文件中的最简单方法,这样它就会删除
Makefile
,例如 drop_makefile()
。即使成本是将该行添加到项目中的每个行中。
很容易丢弃类似的东西
all:
ninja
如果您所做的只是
make
,那么效果很好。
但是,如果我想制作忍者中存在的特定目标,它就不会像
make tests
那样工作,它应该翻译成ninja tests
。
如果你想要生成一个包含所有已知目标的
Makefile
对于 CMake,您可以使用 BUILDSYSTEM_TARGETS
属性。由于这是一个
Directory 属性,您将需要遍历项目的所有目录。
幸运的是,答案
以编程方式获取 CMake 项目中的所有目标
已经展示了如何做到这一点。我用用户ilya1725的功能get_all_targets
进行了测试。
剩下的就是迭代列表并创建像这样调用
ninja
的 Makefile 语法:
function(drop_makefile)
# Bail if CMake is already generating Makefiles
if(CMAKE_GENERATOR STREQUAL "Unix Makefiles")
return()
endif()
# Function get_all_targets taken from
https://stackoverflow.com/questions/60211516/programmatically-get-all-targets-in-a-cmake-project
get_all_targets(_all_targets .)
# Make magic "all" target the first one
list(PREPEND _all_targets "all")
foreach(_target IN LISTS _all_targets)
string(APPEND _makefile ".PHONY: ${_target}\n${_target}:\n\tninja ${_target}\n")
endforeach()
file(WRITE ${CMAKE_BINARY_DIR}/Makefile ${_makefile})
endfunction(drop_makefile)
在项目的根目录中调用该函数,结果将是一个包含项目已知的所有(非导入)目标的
Makefile
。我无法摆脱这种违背 CMake 目的的感觉。
顺便说一句,
make
将评估其选项,但不会将其转发给
ninja
。
像 make -j32
这样的东西会产生 32 个工作,但不会在后台调用 ninja -j32
。
cmake --build
。这将调用正确的工具并消化一些常见选项,例如--jobs
。在这个问题中,击键是一个因素,对于它们来说,这是不可能的。
一个更简单的解决方案是为每个项目提供自己的配置文件
alias_make.sh
,其中包含以下行之一:
alias make=make # for a native Makefile project
alias make=ninja # for a native ninja project
alias make='cmake --build' # for all CMake projects
当开始处理一个项目时,您需要做的就是
source alias_make.sh
并且您可以在幸福无知的情况下使用 make
实际调用 ninja
(好吧,除非它因为它们不一样而崩溃,当然).
顺便说一句,我经常使用
mak
来表示此类 alias
或 shell function
,因为它可以节省 又一个 击键。如果您认为自己可以克服肌肉记忆,请考虑删除最后一个字母。
最后,我要说的是
make
和 ninja
并不相同,因此每次尝试将其中一个伪装成另一个都会导致泄漏抽象。