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

Posted

技术标签:

【中文标题】当我使用 CMake 和 ninja 构建时,clang++ 会忽略 -MD 标志【英文标题】:clang++ ignores -MD flag when I build with CMake and ninja 【发布时间】:2019-01-11 21:51:42 【问题描述】:

我创建了一个非常简单的 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 标志?

【问题讨论】:

【参考方案1】:

Clang 不是罪魁祸首,是 ninga

可以找到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

那就看the Ninja manual: C/C++ header dependencies -> deps:

部门 (自 Ninja 1.3 起可用。)

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

Ninja 1.3 可以在生成依赖项后立即处理依赖项,并将相同信息的压缩形式保存在 Ninja 内部数据库中。

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

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

(我的重点)。

【讨论】:

【参考方案2】:

看起来等效的头依赖信息可以通过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,此依赖信息似乎都是可用的。

【讨论】:

以上是关于当我使用 CMake 和 ninja 构建时,clang++ 会忽略 -MD 标志的主要内容,如果未能解决你的问题,请参考以下文章

CMake/Ninja 试图编译已删除的“.cpp”文件

使用 Ninja 构建系统,我可以清理中间构建产品吗?

CMake / Ninja:当内容未知时递归“清理”输出目录......?

使用 CMake、Clang 和 Ninja 在 Windows 上构建 c++ 项目

如何使用 qtcreator 通过 ninja 构建系统远程部署应用程序

Ninja 构建中的 CMake 命令行参数