CMake 学习
CMake 是一个开源、跨平台的工具系列,旨在构建、测试和打包软件。
📕CMake 基本语法
输出信息
message("hello cmake")
变量
set(name "pomin")
message("My name is ${name}!")
操作符
这些操作符一般使用大写
- 逻辑运算
# 逻辑真:ON , 1, YES, TRUE, Y
# 逻辑假:OFF, 0, NO, FALSE, N, NOTFOUND, IGNORER
# 直接判断,非空值,0,FALSE,OFF 或者 NOTFOUND即为 true
if (var)
# 逻辑非
if (NOT var)
# 逻辑与
if (var1 AND var2)
# 逻辑或
if (var1 OR var2)
- 前置运算符
# 当 cmd_name 是可调用的命令时为 true
if (COMMAND cmd_name)
# 当 var 已经被设置了值时为 true
if (DEFINED var)
# 当指定的文件或者目录存在时为 true
if (EXISTS file_or_dir_name)
# 当 name 是目录或者是绝对路径时为 true
if (IS_DIRECTORY name)
if (IS_ABSOLUTE name)
- 比较运算
# 大于
if (var1 GREATER var2)
# 等于
if (var1 EQUAL var2)
# 小于
if (var1 LESS var2)
# 字符串比较
# STRLESS, STREQUAL 和 STRGREATER
# 版本比较
# VERSION_LESS, VERSION_EQUAL 和 VERSION_GREATER
# 当 file_1 文件的修改时间比 file_2 文件的修改时间要新时为 true
if (file_1 IS_NEWER_THAN file_2)
# 正则表达式支持,当给定的内容与给定的正则表达式相匹配时为 true
if (str MATCHES regex)
次序: () > 前置运算符 > 比较运算 > NOT > AND / OR
if
set(str "x86")
if(str MATCHES "x86")
message("str is x86")
else()
message("str is arm")
endif()
while
set(num "1")
while(${num} LESS "5")
message("num : ${num}")
math(EXPR num "${num} + 1")
endwhile()
foreach
foreach(i RANGE 1 5)
message("i : ${i}")
endforeach()
宏
宏,其中声明的变量为全局变量,宏外可以使用
macro(print str)
message(${str})
endmacro()
print("hello macro")
函数
函数,其中声明的变量为局部变量,函数外不可使用
function(printf str)
message(${str})
endfunction()
printf("hello function")
🧨CMake 环境配置命令
文件类型
CMakeLists.txt 文件有两种:工程文件和脚本文件
工程文件:放在工程根目录的 CMakeLists.txt,使用 project() 指定工程信息的
脚本文件:放在工程的子目录,编译工程所需的链接库等,可以使用
-P
命令使用直译模式。
cmake版本
cmake_minimum_required(VERSION 3.0.0)
工程配置
- 工程名
project(hello)
- 添加工程子目录
子目录中也含有 CMakeLists.txt 脚本
add_subdirectory(lib)
添加文件
- 添加头文件路径
include_directories(inc)
- 添加源文件路径
# 查找当前目录下的所有源文件并将名称保存到 CUR_DIR_SRCS 变量中
aux_source_directory(. ROOT_DIR_SRCS)
# 查找src目录下的所有源文件并将名称保存到 SRC_DIR_SRCS 变量中
aux_source_directory(src SRC_DIR_SRCS)
可以用 CMAKE_MODULE_PATH 来指定外部的包含目录
set (CMAKE_MODULE_PATH /usr/include)
find_path (MODULE_INCLUDE_DIR header.h path1 path2)
find_library (MODULE_LIBRARY library path1 path2)
find_package (MODULE_PACKAGE ....)
编译配置
- 库文件输出
# 从一组源文件中编译出一个库文件并命名
# 静态库
add_library(out_name ${DIR_SRCS})
# 动态库
add_library(out_name SHARED ${DIR_SRCS})
- 可执行文件输出
# 从 SRC_DIR_SRCS 与 ROOT_DIR_SRCS 中编译出可执行文件 hello
add_executable(hello
${SRC_DIR_SRCS}
${ROOT_DIR_SRCS}
)
- 添加链接库
# 放在 add_executable(...) 之后
target_link_libraries(hello hello_lib)
组合变量
- PROJECT_SOURCE_DIR 工程根目录
- CMAKE_BUILD_TYPE
- None: 编译器默认值
- Debug: 产生除错信息
- Release: 进行最佳化
- RelWithDebInfo: 进行最佳化,但仍然会启用 DEBUG flag
- MinSizeRel: 进行程式码最小化
- CMAKE_C_FLAGS C 编译器的编译选项
- CMAKE_CXX_FLAGS C++ 编译器的编译选项
🔅常用命令行
cmake -P CMakeLists.txt
# 直译模式
cmake -Da=99 -Db=99
# 指定变量值
cmake -DCMAKE_BUILD_TYPE=Debug
# 设置开发模式为 Debug 模式
cmake --help-command-list
# 查看所有cmake命令
cmake --help-command message
# 查看具体某个命令说明
💨示例工程
目录结构
.
├── CMakeLists.txt
├── inc
│ └── hello.h
├── lib
│ ├── CMakeLists.txt
│ ├── hello_lib.c
│ └── hello_lib.h
├── main.c
└── src
└── hello.c
- 工程根目录 CMakeLists.txt
# cmake版本要求
cmake_minimum_required(VERSION 3.0.0)
# 工程名字
project(hello)
# 添加头文件路径
include_directories(inc)
# 查找当前目录下的所有源文件并将名称保存到 CUR_DIR_SRCS 变量中
aux_source_directory(. ROOT_DIR_SRCS)
# 查找src目录下的所有源文件并将名称保存到 SRC_DIR_SRCS 变量中
aux_source_directory(src SRC_DIR_SRCS)
# 添加库路径
add_subdirectory(lib)
# 从 SRC_DIR_SRCS 与 ROOT_DIR_SRCS 中编译出可执行文件 hello
add_executable(hello
${SRC_DIR_SRCS}
${ROOT_DIR_SRCS}
)
# 添加链接库
target_link_libraries(hello hello_lib)
- 工程根目录 main.c
#include "./inc/hello.h"
#include "./lib/hello_lib.h"
int main(int argc, char const* argv[]) {
hello();
hello_lib();
return 0;
}
- inc 目录 hello.h 与 src 目录 hello.c
#ifndef _HELLO_H
#define _HELLO_H
#include <stdio.h>
int hello(void);
#endif // _HELLO_H
#include "hello.h"
int hello(void) {
printf("Hello\n");
return 0;
}
- lib 目录 CMakeLists.txt
# 查找lib目录下的所有源文件并将名称保存到 LIB_DIR_SRCS 变量中
aux_source_directory(. LIB_DIR_SRCS)
# 编译lib目录为静态库
# add_library(hello_lib ${LIB_DIR_SRCS})
# 动态库
add_library(hello_lib SHARED ${LIB_DIR_SRCS})
- lib 目录 hello_lib.h 与 hello_lib.c
#ifndef _HELLO_LIB_H
#define _HELLO_LIB_H
#include <stdio.h>
int hello_lib(void);
#endif // _HELLO_H
#include "hello_lib.h"
int hello_lib(void) {
printf("Hello lib\n");
return 0;
}
编译结果
⚡⚡⚡ OVER ⚡⚡⚡