删除“CMakeCache.txt”会导致不再构建“OPTIONAL”安装目标

Deleting `CMakeCache.txt` causes `OPTIONAL` install targets to no longer be built

我看到一个奇怪的构建问题,可能有点难以重现。我将 CMake 与 Ninja 结合使用来构建一个使用 Qt 5.5 的 C++ 项目。我 认为 这种混合物唯一相关的部分是 CMake 本身,但 Qt 肯定会给构建系统增加一些皱纹,所以这也是一个可能的罪魁祸首。

这是导致我出现问题的一系列事件:

  1. 我向基 class 添加了虚方法声明,但忘记将其设为纯虚方法 (=0)。我在派生的 classes 中实现了该方法,但由于缺少 base-class 实现而出现 undefined reference to vtable link 错误。
    1. 派生的 class 之一 继承自 QObject,因此受制于 automoc。我认为这与构建问题无关。
  2. 在我试图弄清楚为什么会出现 link 错误时,我删除了我的 CMakeCache.txt 文件。
    1. 我还删除了构建目录的整个父目录,其中包含有问题的虚拟和派生 classes。我不确定这是否是问题的一部分。
  3. 我意识到我需要使 base-class 方法成为纯虚拟的,并成功完成了我的构建。
  4. 问题: ninja install 不再安装 any 我的二进制目标(所有这些都声明为 OPTIONAL 以允许项目的部分 build/install 进行快速迭代),即使在重新 运行 宁 CMake 几次之后也是如此。

我重新删除了 CMakeCache.txt 并重新删除了 运行 CMake 和 ninja,但是在完全删除构建目录之前我无法重新安装目标.

我的一位同事也 运行 遇到了这个问题,虽然我不知道如何(他可能已经删除或以其他方式损坏了他的 CMakeCache.txt 文件,但他没有实际上还记得在看到问题之前他在做什么。

编辑: 我又遇到了这个问题,看起来当我将目标设置为非 OPTIONAL 时,CMake 希望在CMakeFiles 目录(在构建工件树中)称为 CMakeRelink.dir。这个目录显然从不存在。即使将 CMAKE_SKIP_INSTALL_ALL_DEPENDENCY 设置为 false 并重新 运行 CMake 似乎也无法解决问题,这对我来说毫无意义。

编辑 2: 认为 这是同一个错误,并且有一些解决方法:https://cmake.org/Bug/view.php?id=13934

这似乎是由于 CMake 如何处理其 post 二进制文件处理的错误。默认情况下,install 命令会在安装二进制文件之前从二进制文件中删除嵌入的库路径。对于 ELF 二进制文件,CMake 有某种内置的路径剥离器,它实际上读取 ELF 文件并创建一个没有嵌入路径的新文件;对于非 ELF 文件,使用不同的方案。值得注意的是,CMake 根据将使用哪种方案剥离它们,对未剥离的二进制文件使用不同的文件。我不知道这是为什么,但这是构建错误的根本原因。

没有 CMakeCache.txt,CMake 似乎 "forget" 使用(或应该使用)哪种方案来剥离文件。因此,它会在错误的工件目录中寻找未剥离的二进制文件。

这是一个known (though somewhat obscure) CMake bug;最简单的解决方法是通过设置 CMAKE_EXECUTABLE_FORMAT 变量明确指定(适当时)目标二进制文件为 ELF 格式。