当我用CMake和ninja构建时,clang++忽略了-MD标志

clang++ ignores -MD flag when I build with CMake and ninja

本文关键字:clang++ 标志 -MD CMake 构建 ninja      更新时间:2023-10-16

我创建了一个非常简单的C++/CMake项目:

CMakeLists.txt(注意-MD标志):

cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
add_executable(moop main.cc)
target_compile_options(moop PRIVATE -MD)

main.cc:

#include "moop.hh"
int main( int, char** ) { return 0; }

moop.hh:

#pragma once

从项目根目录,我运行以下内容:

mkdir build && cd build
cmake -G Ninja -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..
cat compile_commands.json

cat compile_commands.json输出(注意-MD标志):

{
"directory": "/home/zbardoo/moop/build",
"command": "/usr/bin/clang++      -MD -o CMakeFiles/moop.dir/main.cc.o -c /home/zbardoo/moop/main.cc",
"file": "/home/zbardoo/moop/main.cc"
}

如果我随后运行ninja,则可执行文件moop已成功构建。然而,moop.cc.d却不见踪影。但是,如果我从compile_commands.json复制并粘贴command值并运行它:

/usr/bin/clang++      -MD -o CMakeFiles/moop.dir/main.cc.o -c /home/zbardoo/moop/main.cc

出现文件/home/zbardoo/moop/build/CMakeFiles/moop.dir/main.cc.d

zbardoo@localhost:~/moop/build$ cat CMakeFiles/moop.dir/main.cc.d 
CMakeFiles/moop.dir/main.cc.o: /home/zbardoo/moop/main.cc 
/home/zbardoo/moop/moop.hh

为什么ninja不遵守compile_commands.json文件中的-MD标志?

Clang不是罪魁祸首,而是

可以找到丢失CMakeFiles/moop.dir/main.cc.d的原因如果您查看生成的build/rules.ninja并找到:

rule CXX_COMPILER__moop
depfile = $DEP_FILE
deps = gcc
command = /usr/bin/clang++  $DEFINES $INCLUDES $FLAGS -MD -MT $out -MF $DEP_FILE -o $out -c $in
description = Building CXX object $out

注:

deps = gcc

然后参阅Ninja手册:C/C++标头依赖项->deps:

deps(自Ninja 1.3起提供。)

事实证明,对于大型项目(尤其是在文件系统速度较慢的Windows上),启动时加载这些依赖文件的速度较慢。

相反,Ninja1.3可以在依赖关系生成后立即处理它们,并将相同信息的压缩形式保存在Ninja内部数据库中。

Ninja以两种形式支持这种处理。

deps=gcc指定该工具以Makefiles的形式输出gcc样式的依赖项。将其添加到上面的示例将导致Ninja在编译完成后立即处理depfile,然后删除.d文件(仅用作临时文件)

(我的重点)。

通过ninja -t deps:可以获得等效的标头依赖信息

zbardoo@localhost:~/moop/build$ ninja -t deps
CMakeFiles/moop.dir/main.cc.o: #deps 2, deps mtime 1547243911 (VALID)
../main.cc
../moop.hh

然而,无论我是否指定了-MDtarget_compile_options,这个依赖性信息似乎都是可用的。