删除“CMakeCache.txt”会导致不再构建“OPTIONAL”安装目标
Deleting `CMakeCache.txt` causes `OPTIONAL` install targets to no longer be built
我看到一个奇怪的构建问题,可能有点难以重现。我将 CMake 与 Ninja 结合使用来构建一个使用 Qt 5.5 的 C++ 项目。我 认为 这种混合物唯一相关的部分是 CMake 本身,但 Qt 肯定会给构建系统增加一些皱纹,所以这也是一个可能的罪魁祸首。
这是导致我出现问题的一系列事件:
- 我向基 class 添加了虚方法声明,但忘记将其设为纯虚方法 (
=0
)。我在派生的 classes 中实现了该方法,但由于缺少 base-class 实现而出现 undefined reference to vtable
link 错误。
- 派生的 class 之一 也 继承自
QObject
,因此受制于 automoc
。我认为这与构建问题无关。
- 在我试图弄清楚为什么会出现 link 错误时,我删除了我的
CMakeCache.txt
文件。
- 我还删除了构建目录的整个父目录,其中包含有问题的虚拟和派生 classes。我不确定这是否是问题的一部分。
- 我意识到我需要使 base-class 方法成为纯虚拟的,并成功完成了我的构建。
- 问题:
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 格式。
我看到一个奇怪的构建问题,可能有点难以重现。我将 CMake 与 Ninja 结合使用来构建一个使用 Qt 5.5 的 C++ 项目。我 认为 这种混合物唯一相关的部分是 CMake 本身,但 Qt 肯定会给构建系统增加一些皱纹,所以这也是一个可能的罪魁祸首。
这是导致我出现问题的一系列事件:
- 我向基 class 添加了虚方法声明,但忘记将其设为纯虚方法 (
=0
)。我在派生的 classes 中实现了该方法,但由于缺少 base-class 实现而出现undefined reference to vtable
link 错误。- 派生的 class 之一 也 继承自
QObject
,因此受制于automoc
。我认为这与构建问题无关。
- 派生的 class 之一 也 继承自
- 在我试图弄清楚为什么会出现 link 错误时,我删除了我的
CMakeCache.txt
文件。- 我还删除了构建目录的整个父目录,其中包含有问题的虚拟和派生 classes。我不确定这是否是问题的一部分。
- 我意识到我需要使 base-class 方法成为纯虚拟的,并成功完成了我的构建。
- 问题:
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 格式。