cmake语法学习笔记
一、背景概述
cmake是用于生成编译用的Makefile的脚本语言,极大的降低了编译脚本的编写难度,vpp、x86平台诸多工程都开始使用cmake脚本进行编译,有必要对cmake语法进行学习掌握。
二、语法介绍和实战
2.1 单文件编译
1)基础.c编译,生成可执行文件,编写CMakeLists.txt
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)# 项目信息
project (Demo1)# 指定生成目标main
add_executable(main main.c)
tips:
- 使用括号的方式调用函数,和make\shell不同
- 分隔符没有逗号和分号,使用空格分割。
- project属性是否每个CMakeLists.txt文件都需要添加?
不需要,顶层添加即可
2.2 编译执行
- 生成makefile
cmake .
- 使用生成的makefile进行编译
make
上述文件,生成的makefile如下
zfj@ubuntu22:~/test/cmake$ cat Makefile
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 3.22# Default target executed when no arguments are given to make.
default_target: all
.PHONY : default_target# Allow only one "make -f Makefile2" at a time, but pass parallelism.
.NOTPARALLEL:#=============================================================================
# Special targets provided by cmake.# Disable implicit rules so canonical targets will work.
.SUFFIXES:# Disable VCS-based implicit rules.
% : %,v# Disable VCS-based implicit rules.
% : RCS/%# Disable VCS-based implicit rules.
% : RCS/%,v# Disable VCS-based implicit rules.
% : SCCS/s.%# Disable VCS-based implicit rules.
% : s.%.SUFFIXES: .hpux_make_needs_suffix_list# Command-line flag to silence nested $(MAKE).
$(VERBOSE)MAKESILENT = -s#Suppress display of executed commands.
$(VERBOSE).SILENT:# A target that is always out of date.
cmake_force:
.PHONY : cmake_force#=============================================================================
# Set environment variables for the build.# The shell in which to execute make rules.
SHELL = /bin/sh# The CMake executable.
CMAKE_COMMAND = /usr/bin/cmake# The command to remove a file.
RM = /usr/bin/cmake -E rm -f# Escaping for special characters.
EQUALS = =# The top-level source directory on which CMake was run.
CMAKE_SOURCE_DIR = /home/zfj/test/cmake# The top-level build directory on which CMake was run.
CMAKE_BINARY_DIR = /home/zfj/test/cmake#=============================================================================
# Targets provided globally by CMake.# Special rule for the target edit_cache
edit_cache:@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "No interactive CMake dialog available..."/usr/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available.
.PHONY : edit_cache# Special rule for the target edit_cache
edit_cache/fast: edit_cache
.PHONY : edit_cache/fast# Special rule for the target rebuild_cache
rebuild_cache:@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."/usr/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
.PHONY : rebuild_cache# Special rule for the target rebuild_cache
rebuild_cache/fast: rebuild_cache
.PHONY : rebuild_cache/fast# The main all target
all: cmake_check_build_system$(CMAKE_COMMAND) -E cmake_progress_start /home/zfj/test/cmake/CMakeFiles /home/zfj/test/cmake//CMakeFiles/progress.marks$(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 all$(CMAKE_COMMAND) -E cmake_progress_start /home/zfj/test/cmake/CMakeFiles 0
.PHONY : all# The main clean target
clean:$(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 clean
.PHONY : clean# The main clean target
clean/fast: clean
.PHONY : clean/fast# Prepare targets for installation.
preinstall: all$(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall
.PHONY : preinstall# Prepare targets for installation.
preinstall/fast:$(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 preinstall
.PHONY : preinstall/fast# clear depends
depend:$(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1
.PHONY : depend#=============================================================================
# Target rules for targets named main# Build rule for target.
main: cmake_check_build_system$(MAKE) $(MAKESILENT) -f CMakeFiles/Makefile2 main
.PHONY : main# fast build rule for target.
main/fast:$(MAKE) $(MAKESILENT) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/build
.PHONY : main/fastmain.o: main.c.o
.PHONY : main.o# target to build an object file
main.c.o:$(MAKE) $(MAKESILENT) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/main.c.o
.PHONY : main.c.omain.i: main.c.i
.PHONY : main.i# target to preprocess a source file
main.c.i:$(MAKE) $(MAKESILENT) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/main.c.i
.PHONY : main.c.imain.s: main.c.s
.PHONY : main.s# target to generate assembly for a file
main.c.s:$(MAKE) $(MAKESILENT) -f CMakeFiles/main.dir/build.make CMakeFiles/main.dir/main.c.s
.PHONY : main.c.s# Help Target
help:@echo "The following are some of the valid targets for this Makefile:"@echo "... all (the default if no target is provided)"@echo "... clean"@echo "... depend"@echo "... edit_cache"@echo "... rebuild_cache"@echo "... main"@echo "... main.o"@echo "... main.i"@echo "... main.s"
.PHONY : help#=============================================================================
# Special targets to cleanup operation of make.# Special rule to run CMake to check the build system integrity.
# No rule that depends on this can have commands that come from listfiles
# because they might be regenerated.
cmake_check_build_system:$(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0
.PHONY : cmake_check_build_system
tips: CMakeFiles是中间目录,保存cmake的中间文件。
2.3 多文件编译
直接在add_executable 列表中添加需要编译的c文件即可。
add_executable(main main.c test.c)
2.4 添加目录编译
将目录下所有文件保存到变量中,然后添加的可执行程序的源码文件中。
# 并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)# 指定生成目标
add_executable(Demo ${DIR_SRCS})
文件格式是如何定义?
c和cpp都会添加
2.5 cmake如何调试?
使用message函数添加打印,多个参数依次排列即可。
message( [STATUS|WARNING|AUTHOR_WARNING|FATAL_ERROR|SEND_ERROR] "message to display" ...)
message(STATUS "hello zfj " ${DIR_SRCS})
2.6 编译成lib库
1)可执行文件的工程:根目录CMakelists.txt中添加子目录,如子目录math目录编译成动态库,并添加链接。
# 添加 math 子目录
add_subdirectory(math)# 添加链接库
target_link_libraries(main MathFunctions)
2)动态库math目录CMakelists.txt中
# 并将名称保存到 DIR_LIB_SRCS 变量
aux_source_directory(. DIR_LIB_SRCS)# 生成链接库
add_library (MathFunctions ${DIR_LIB_SRCS})
指定生成动态库和静态库:
add_library(lib_name STATIC/SHARED src)
# 函数作用:生成库。
# 参数lib_name:是要生成的库名称,
# 参数STATIC/SHARED:指定生成静态库或动态库,
# 参数src:指明库的生成所需要的源文件
编译so的输出目录,分别生成静态库和动态库:
add_library(MathFunctions_static STATIC ${DIR_LIB_SRCS})
add_library(MathFunctions_dyn SHARED ${DIR_LIB_SRCS})# 库名统一修改
set_target_properties(MathFunctions_static PROPERTIES OUTPUT_NAME "MathFunctions")
set_target_properties(MathFunctions_dyn PROPERTIES OUTPUT_NAME "MathFunctions")# 设置库的输出目录
set(LIBRARY_OUTPUT_PATH ../lib)
tips:
- PROJECT_BINARY_DIR是cmake系统变量,意思是执行cmake命令的目录
-
使用find_library的好处是在执行cmake …时就会去查找库是否存在,这样可以提前发现错误,不用等到链接时。
-
二进制输出目录
set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
2.7 添加include路径
include_directories ( dir )
2.8 源码和产物分离
将源码和产物使用两个目录进行编译,防止.o文件在源码目录,不利于源码维护。常规操作是创建build目录,然后在build目录下执行cmake …,这个一般是在CMake文件中进行copy的。
2.9 添加编译选项
add_compile_options(-std=c++11 -Wall)
2.10 宏配置
1)option定义cmake选项
2)add_definitions 传递给c文件
option(WWW1 "print one message" OFF)
option(WWW2 "print another message" OFF)if (WWW1)add_definitions(-DWWW1)
endif()if (WWW2)add_definitions(-DWWW2)
endif()
传递宏:
cmake … -DMYDEBUG=ON
3)C文件中使用宏
三、参考资料
https://getiot.tech/zh/cmake/cmake-message/#google_vignette
https://blog.csdn.net/weixin_43717839/article/details/128032486
cmake使用详细教程(日常使用这一篇就足够了)_cmake教程-CSDN博客
https://www.cnblogs.com/ybqjymy/p/13409050.html