在CMake项目下编译单个文件?
Compile a single file under CMake project?
我正在开发一个 C++ 项目,该项目将包含在一个更大的项目中。
我已经看到在更大的项目中(是一个 Qt 应用程序,它是从 qmake 生成的)我能够从 linux 命令行编译单个文件,只需输入相对路径特定文件作为 make 的参数。
另一方面,我正在为我自己的项目使用 CMake。当我修改一个编译单元的一些代码时,我必须修改它的头文件,我必须等待很长时间才能编译它的依赖项,然后再编译它自己的源文件。但是有些情况下我更愿意检查*.cc文件中的源代码是否可以无错编译。
有没有办法像 qmake 那样从 CMake 生成 Makefile?切换到 qmake 不再是一种选择。
不,CMake 不提供编译单个文件的内置支持。
您必须为每个目标文件添加一个目标,可能是通过一个遍历目录中所有文件的函数。
不是开箱即用的。 CMake 不会在主 makefile 中公开那些 "internal" makefile 规则。
只有考虑到CMake内部使用的是哪种文件结构,才能做到这一点。你可以例如使用 CMake 生成的 makefile 调用编译单个 .obj
文件
make -f CMakeFiles/myProg.dir/build.make CMakeFiles/myProg.dir/main.cc.obj
当你有类似的东西时
cmake_minimum_required(VERSION 3.1)
project(myProg CXX)
file(WRITE "main.cc" "int main()\n{\nreturn 0;\n}")
add_executable(myProg main.cc)
您不必向 CMake 脚本添加额外的自定义目标,因为 CMake 生成的 Makefile 已经包含每个 .cc 文件的 .o 目标。例如。如果你有一个名为 mySourceFile.cc
的源文件,你的构建目录中将有一个 Makefile 定义了一个名为 <Some Path>/mySourceFile.cc.o
的目标。如果你 cd
进入你的构建目录,你可以使用 grep
或 ack-grep
找到定义这个目标的 Makefile,然后 cd
进入那个 Makefile 的目录并构建它。
例如假设命令 ack-grep mySourceFile.cc.o
打印如下内容:
foo/bar/Makefile
119:x/y/z/mySourceFile.o: x/y/z/mySourceFile.cc.o
123:x/y/z/mySourceFile.cc.o:
124: # recipe for building target
然后您可以通过以下方式构建 mySourceFile.cc.o
:
cd foo/bar && make x/y/z/mySourceFile.cc.o
CMake 没有通用的内置方法来执行此操作(它是 open issue), but if you're using the Ninja generator, you can can use a special Ninja syntax 用于构建给定源文件的直接输出。例如,仅编译 foo.o
你会使用:
ninja /path/to/foo.cpp^
要单独构建 src/foo.cpp:
cmake --build . --target src/foo.cpp.o
其他人提出了从 .cpp
文件名中查找目标名称(以 .cpp.o
结尾)的方法,但是如果您已经知道将触发 [=] 编译的目标名称12=] 文件并且你正在使用忍者这个建议应该更容易。
首先构建目标:
ninja TriggersCppCompilationLib
假设您的文件已更改或尚未构建,ninja 将打印完整的目标名称。当您看到名称出现时,按回车键,这样它就不会被覆盖。然后只需从终端复制名称(例如使用 tmux 复制模式)。
我正在开发一个 C++ 项目,该项目将包含在一个更大的项目中。
我已经看到在更大的项目中(是一个 Qt 应用程序,它是从 qmake 生成的)我能够从 linux 命令行编译单个文件,只需输入相对路径特定文件作为 make 的参数。
另一方面,我正在为我自己的项目使用 CMake。当我修改一个编译单元的一些代码时,我必须修改它的头文件,我必须等待很长时间才能编译它的依赖项,然后再编译它自己的源文件。但是有些情况下我更愿意检查*.cc文件中的源代码是否可以无错编译。
有没有办法像 qmake 那样从 CMake 生成 Makefile?切换到 qmake 不再是一种选择。
不,CMake 不提供编译单个文件的内置支持。
您必须为每个目标文件添加一个目标,可能是通过一个遍历目录中所有文件的函数。
不是开箱即用的。 CMake 不会在主 makefile 中公开那些 "internal" makefile 规则。
只有考虑到CMake内部使用的是哪种文件结构,才能做到这一点。你可以例如使用 CMake 生成的 makefile 调用编译单个 .obj
文件
make -f CMakeFiles/myProg.dir/build.make CMakeFiles/myProg.dir/main.cc.obj
当你有类似的东西时
cmake_minimum_required(VERSION 3.1)
project(myProg CXX)
file(WRITE "main.cc" "int main()\n{\nreturn 0;\n}")
add_executable(myProg main.cc)
您不必向 CMake 脚本添加额外的自定义目标,因为 CMake 生成的 Makefile 已经包含每个 .cc 文件的 .o 目标。例如。如果你有一个名为 mySourceFile.cc
的源文件,你的构建目录中将有一个 Makefile 定义了一个名为 <Some Path>/mySourceFile.cc.o
的目标。如果你 cd
进入你的构建目录,你可以使用 grep
或 ack-grep
找到定义这个目标的 Makefile,然后 cd
进入那个 Makefile 的目录并构建它。
例如假设命令 ack-grep mySourceFile.cc.o
打印如下内容:
foo/bar/Makefile
119:x/y/z/mySourceFile.o: x/y/z/mySourceFile.cc.o
123:x/y/z/mySourceFile.cc.o:
124: # recipe for building target
然后您可以通过以下方式构建 mySourceFile.cc.o
:
cd foo/bar && make x/y/z/mySourceFile.cc.o
CMake 没有通用的内置方法来执行此操作(它是 open issue), but if you're using the Ninja generator, you can can use a special Ninja syntax 用于构建给定源文件的直接输出。例如,仅编译 foo.o
你会使用:
ninja /path/to/foo.cpp^
要单独构建 src/foo.cpp:
cmake --build . --target src/foo.cpp.o
其他人提出了从 .cpp
文件名中查找目标名称(以 .cpp.o
结尾)的方法,但是如果您已经知道将触发 [=] 编译的目标名称12=] 文件并且你正在使用忍者这个建议应该更容易。
首先构建目标:
ninja TriggersCppCompilationLib
假设您的文件已更改或尚未构建,ninja 将打印完整的目标名称。当您看到名称出现时,按回车键,这样它就不会被覆盖。然后只需从终端复制名称(例如使用 tmux 复制模式)。