以前写Makefile很多,但是Makefile是类Linux系统的专属编译规则文件,涉及到跨平台(主要是Windows的VC)编译时,现阶段CMake是标配。CMake其实是在linux的makefile和windows的vcproj之上又做了一层,用于生成不同平台的编译规则(或者项目)文件,相当于编译规则的规则,其规则代码是写在CMakeLists.txt里的。
罗列一些常见问题于此:
通常test.c编译的中间文件test.o就会在同一目录,包括最终的可招行结果文件。以往在写Makefile时,还需要专门写个make clean来清理哪些中间文件。CMake一开始就考虑到了保持源代码的干净,这样也方便不同编译参数的结果文件能够并存。所以通常使用CMake时并不是直接make完事,而是在源码目录里先创建一个build目录,接着是:
cd build && cmake .. && make
这样清理中间文件就变得非常简单,直接删除掉build目录就行。
打开CMakeLists.txt,可能第一条对cmake的版本限制为
cmake_minimum_required(VERSION 3.16...3.28)
而系统安装的是3.10,不匹配怎么办呢?这种不匹配经常遇到,因为在编译五花八门的代码时,各家的版本要求都可能不一样。
幸运的是cmake只是一个规则生成程序,不涉及太多三方依赖,可以很容易地从官方网站下载编译好的软件版本,直接使用。具体为,访问 https://cmake.org/files/ ,找个目标版本,点击进去后下载即可,llinux环境时,可以下载.sh脚本,例如:cmake-3.20.6-linux-x86_64.sh。接着只需要覆盖终端的PATH,确保优先找到本地下载的cmake文件。
编译参数指定类型即可,比如编译Release:
cmake --build . --config Release
cmake通过-DXXX的方式来向编译代码设定宏定义。除不同软件有自己支持的宏外,cmake也有一些内置能用的宏,例如:
cmake . -DCMAKE_INSTALL_PREFIX=`pwd`/output
-DCMAKE_C_FLAGS_RELEASE="-Os -g0 -s" -DCMAKE_CXX_FLAGS_RELEASE="-Os -g0 -s"
-DDISABLE_SHARED=ON
在书写CMakeLists.txt时,指定c++版本比较特殊,如果只是针对linux的gcc,当然可以写成:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
但windows上并不支持-std参数的,所以需要写成:
set(CMAKE_CXX_STANDARD 11)
在写CMakeLists.txt时,有时候需要针对特定的编译器平台指定宏,最常见的例子就是写c++时用到std::min(),但在windows上,windows.h里定义了一个名为min的宏,为了避免冲突,就需要针对VC定义NOMINMAX宏,写法如下:
if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
add_compile_definitions(NOMINMAX)
endif()
要支持install命令,是需要在CMakefile.txt中指定安装路径的,如下即表示将project_name的结果安装到bin目录下:
install(TARGETS project_name DESTINATION bin)
安装命令即为:
cmake --install . --config Release
如果需要去除符号表,让结果二进制文件更小点,命令为:
cmake --install . --config Release --strip