CMAKE常用命令详解

NDK

List基本用法

Get--获取列表中指定索引的元素

cmake 复制代码
list(Get list_name index output_var)
解释
  • list_name: 要操作集合的名称
  • index: 要取得的元素下标
  • output_var: 保存从集合中取得元素的结果
栗子
cmake 复制代码
list(GET mylist 0 first_element)  # 获取第一个元素

APPEND--在列表末尾添加元素

cmake 复制代码
list(APPEND list_name element1 element2 ...)
解释
  • list_name: 集合名称
  • element1: 添加集合元素的名称
栗子
cmake 复制代码
list(APPEND mylist "new_item")

INSERT--在指定位置插入元素

cmake 复制代码
list(INSERT list_name index element1 element2 ...)
解释
  • list_name: 集合名称
  • index: 要插入的索引位置
  • element1: 添加集合元素的名称
栗子
cmake 复制代码
list(INSERT mylist 0 "first_item") # 在开头插入

REMOVE_ITEM--移除指定元素

cmake 复制代码
list(REMOVE_ITEM list_name value1 value2 ...)
解释
  • list_name: 集合名称
  • value1: 要移除元素的名称
栗子
cmake 复制代码
list(REMOVE_ITEM mylist "item_to_remove")

LENGTH--获取列表长度

cmake 复制代码
list(LENGTH list_name output_var)
解释
  • list_name: 集合名称
  • output_var: 集合长度
栗子
cmake 复制代码
list(LENGTH mylist list_size)

SORT--列表排序

cmake 复制代码
list(SORT list_name)
解释
  • list_name: 集合名称
栗子
cmake 复制代码
list(SORT mylist) # 按字母顺序排序

string基本用法

REPLACE--替换

cmake 复制代码
string(REPLACE <match_string> <replace_string> <output_variable> <input>)
解释
  • match_string: 要匹配的字符串
  • replace_string: 要替换的字符串
  • output_variable: 存储结果的变量
  • input: 输入的字符串
栗子
cmake 复制代码
string(REPLACE "." ";" VERSION_LIST "1.2.3")  # 结果: "1;2;3"

SUBSTRING--截取

cmake 复制代码
string(SUBSTRING <input> <begin> <length> <output_variable>)
解释
  • input: 输入的字符串

  • begin: 开始截取的起始位置

  • length: 要截取的长度

  • output_variable: 存储结果的变量

栗子
cmake 复制代码
string(SUBSTRING "Hello World" 0 5 RESULT)  # 结果: "Hello"

LENGTH--长度

cmake 复制代码
string(LENGTH <input> <output_variable>)
解释
  • input: 输入的字符串
  • output_variable: 存储结果的变量
栗子
cmake 复制代码
string(LENGTH "Hello" LEN)  # 结果: 5

TOUPPER--转大写

cmake 复制代码
string(TOUPPER <input> <output_variable>)
解释
  • input: 输入的字符串
  • output_variable: 存储结果的变量
栗子
cmake 复制代码
string(TOUPPER "hello" RESULT)  # 结果: "HELLO"

TOLOWER--转小写

cmake 复制代码
string(TOUPPER <input> <output_variable>)
解释
  • input: 输入的字符串
  • output_variable: 存储结果的变量
栗子
cmake 复制代码
string(TOLOWER "HELLO" RESULT)  # 结果: "hello"

FIND--查找

cmake 复制代码
string(FIND <input> <substring> <output_variable>)
解释
  • input: 输入的字符串
  • substring: 查找的字符串
  • output_variable: 存储结果的变量
栗子
cmake 复制代码
string(FIND "Hello World" "World" POSITION)  # 结果: 6

COMPARE--比较

cmake 复制代码
string(COMPARE EQUAL <input1> <input2> <output_variable>)
解释
  • input1: 输入的字符串1
  • input2: 输入的字符串2
  • output_variable: 存储结果的变量
栗子
cmake 复制代码
string(COMPARE EQUAL "hello" "hello" RESULT)  # 结果: TRUE

function--函数基本用法

cmake 复制代码
# 定义函数
function(函数名 [参数1] [参数2] ...)
	# 函数体
endfunction()

# 调用函数
函数名(参数1 参数2 ...)
参数访问

通过参数名字节访问

cmake 复制代码
# 通过参数名直接访问
message("First argument: ${arg1}")
message("Second argument: ${arg2}")

通过ARGV访问所有参数

(argc,argv[])是不是很眼熟,和C语言的访问方式一样

cmake 复制代码
# 通过ARGV访问所有参数
message("All args: ${ARGV}")             # 所有参数的列表
message("Arg count: ${ARGC}")            # 参数个数
message("Arg 0: ${ARGV0}")               # 第一个参数
message("Arg 1: ${ARGV1}")               # 第二个参数
返回值处理
cmake 复制代码
function(my_function result_var)
    # 使用PARENT_SCOPE设置父作用域变量
    set(${result_var} "some value" PARENT_SCOPE)
endfunction()

# 调用并获取结果
my_function(RESULT)
message("Result: ${RESULT}")

macro--函数的另一版

由于marco和``function的用法非常相似,所以这里与function做一个对比,突出macro`的功能

变量作用域

cmake 复制代码
# Macro示例 - 变量会影响外部作用域
macro(test_macro)
    set(var "macro value")    # 会改变外部var的值
endmacro()

# Function示例 - 变量仅在函数内有效
function(test_function)
    set(var "function value") # 不会改变外部var的值
endfunction()

# 使用示例
set(var "original value")
test_macro()
message("After macro: ${var}")    # 输出: "macro value"

set(var "original value")
test_function()
message("After function: ${var}") # 输出: "original value"

参数处理

cmake 复制代码
# Macro中的参数是文本替换
macro(test_macro arg)
    message("arg = ${arg}")       # 直接使用参数名
    set(${arg} "new value")       # 可以修改外部变量
endmacro()

# Function中的参数是值传递
function(test_function arg)
    message("arg = ${arg}")       # 使用参数值
    set(${arg} "new value")       # 需要PARENT_SCOPE才能修改外部变量
endfunction()

返回值处理

cmake 复制代码
# Macro没有真正的返回值机制
macro(test_macro result)
    set(${result} "macro result")  # 直接修改外部变量
endmacro()

# Function需要使用PARENT_SCOPE来返回值
function(test_function result)
    set(${result} "function result" PARENT_SCOPE)  # 使用PARENT_SCOPE修改父作用域
endfunction()

变量引用

cmake 复制代码
# Macro中的变量引用
macro(test_macro var)
    message("${${var}}")  # 需要两层${}来获取变量值
endmacro()

# Function中的变量引用
function(test_function var)
    message("${var}")     # 直接使用参数值
endfunction()

特殊变量的行为

cmake 复制代码
# Macro中的ARGN
macro(test_macro arg)
    message("ARGN = ${ARGN}")  # ARGN包含所有额外参数
endmacro()

# Function中的ARGN
function(test_function arg)
    message("ARGN = ${ARGN}")  # ARGN是一个新的局部变量
endfunction()

递归调用

cmake 复制代码
# Macro的递归可能导致无限展开
macro(recursive_macro count)
    if(count GREATER 0)
        math(EXPR new_count "${count} - 1")
        recursive_macro(${new_count})  # 可能导致问题
    endif()
endmacro()

# Function的递归更安全
function(recursive_function count)
    if(count GREATER 0)
        math(EXPR new_count "${count} - 1")
        recursive_function(${new_count})  # 正常工作
    endif()
endfunction()

if基本用法

由于if比较简单,所以直接在这里写栗子了

基本比较
cmake 复制代码
# 基础语法
if(条件)
    # 条件为真时执行
elseif(条件2)
    # 条件2为真时执行
else()
    # 所有条件为假时执行
endif()

# 常量比较
if(TRUE)  # 也可以用1, ON, YES, Y
    message("True")
endif()

if(FALSE) # 也可以用0, OFF, NO, N, IGNORE, NOTFOUND, ""
    message("False")
endif()
数值比较
cmake 复制代码
# 数值比较运算符
if(1 EQUAL 1)        # 等于
if(1 LESS 2)         # 小于
if(2 GREATER 1)      # 大于
if(1 LESS_EQUAL 1)   # 小于等于
if(1 GREATER_EQUAL 1)# 大于等于

# 版本号比较
if(1.2.3 VERSION_LESS 1.2.4)
if(1.2.3 VERSION_GREATER 1.2.2)
if(1.2.3 VERSION_EQUAL 1.2.3)
if(1.2.3 VERSION_LESS_EQUAL 1.2.3)
if(1.2.3 VERSION_GREATER_EQUAL 1.2.3)
字符串比较
cmake 复制代码
# 字符串比较
if("string" STREQUAL "string")  # 字符串相等
if("string" MATCHES "str.*")    # 正则匹配

# 字符串比较(不区分大小写)
if("String" STREQUAL "string")          # 为假
if("String" STREQUAL "string" CASE INSENSITIVE) # 为真
路径比较
cmake 复制代码
# 路径比较
if(path1 PATH_EQUAL path2)  # 判断两个路径是否相同

# 检查路径是否存在
if(EXISTS "/path/to/file")
if(IS_DIRECTORY "/path/to/dir")
if(IS_SYMLINK "/path/to/symlink")
变量检查
cmake 复制代码
# 变量定义检查
if(DEFINED VARIABLE)         # 检查变量是否被定义
if(NOT DEFINED VARIABLE)     # 检查变量是否未定义

# 变量值检查
if(VARIABLE)                # 检查变量值是否为真
if(NOT VARIABLE)            # 检查变量值是否为假

# 环境变量检查
if(DEFINED ENV{PATH})       # 检查环境变量是否定义
if($ENV{PATH})             # 检查环境变量的值
逻辑运算
cmake 复制代码
# 与运算
if(condition1 AND condition2)
if(condition1 AND condition2 AND condition3)

# 或运算
if(condition1 OR condition2)
if(condition1 OR condition2 OR condition3)

# 非运算
if(NOT condition)

# 复杂逻辑组合
if((A OR B) AND (C OR D))
文件操作相关
cmake 复制代码
# 文件检查
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/file.txt")
if(IS_NEWER_THAN file1 file2)
if(IS_ABSOLUTE path)

# 权限检查
if(IS_DIRECTORY dir AND EXISTS "${dir}/file")
策略和特性检查
cmake 复制代码
# 检查CMake策略
if(POLICY CMP0048)
    cmake_policy(SET CMP0048 NEW)
endif()

# 检查编译器特性
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if(MSVC)
if(APPLE)
if(UNIX)
if(WIN32)
目标库检查
cmake 复制代码
# 检查目标是否存在
if(TARGET target_name)

# 检查库是否找到
find_package(OpenGL)
if(OpenGL_FOUND)
    # 使用OpenGL
endif()

get_property--获取属性值

基本语法

cmake 复制代码
get_property(<variable>
             <GLOBAL | DIRECTORY | TARGET | SOURCE | INSTALL | TEST | CACHE | VARIABLE>
             PROPERTY <property_name>
             [DEFINED | SET | BRIEF_DOCS | FULL_DOCS])

解释

  • variable: 用于存储获取到的属性值的变量名
  • 作用域参数(必选其一):
    • GLOBAL - 全局属性
    • DIRECTORY - 目录属性
    • TARGET - 目标属性
    • **SOURCE **- 源文件属性
    • INSTALL - 安装属性
    • **TEST **- 测试属性
    • **CACHE **- 缓存属性
    • VARIABLE - 变量属性
  • PROPERTY <property_name> - 要获取的属性名称

math--数学计算

基本用法

cmake 复制代码
math(EXPR <output_variable> "<expression>")

解释

  • EXPR: 固定格式
  • output_variable: 保存计算后的结果的变量
  • "": 计算的表达式

栗子

cmake 复制代码
# 多个运算符组合
math(EXPR result "(10 + 5) * 2")  # result = 30

# 使用变量
set(a 10)
set(b 20)
math(EXPR result "${a} + ${b}")  # result = 30

message--输出消息日志

基本用法

cmake 复制代码
message([<mode>] "message text")

解释

  • mode: 类型
  • "message text": 输出的消息

栗子

cmake 复制代码
# 状态信息(默认)
message(STATUS "This is a status message")

# 错误信息(会终止CMake运行)
message(FATAL_ERROR "This is a fatal error message")

# 警告信息(不会终止)
message(WARNING "This is a warning message")

# 作者警告
message(AUTHOR_WARNING "This is an author warning message")

# 调试信息
message(DEBUG "This is a debug message")

# 普通信息(无前缀)
message("This is a normal message")

# 发送到stderr的信息
message(SEND_ERROR "This is an error message")

# 弃用警告
message(DEPRECATION "This feature is deprecated")

option--布尔类型变量

option命令用于定义布尔类型的选项变量

基本语法

cmake 复制代码
option(<variable> "<help_text>" [value])

参数解释

  • variable: 变量名称
  • "<help_text>": 帮助文本
  • value: 变量的初始值

栗子

cmake 复制代码
# 构建选项
option(ENABLE_SHARED "Build shared libraries" TRUE)
option(ENABLE_STATIC "Build static libraries" TRUE)

file--文件操作

模板的用法

读取文件

cmake 复制代码
# 读取整个文件到变量
file(READ "filename.txt" file_contents)

# 读取文件的前N个字节
file(READ "filename.txt" file_contents LIMIT 1024)

# 按行读取文件到列表
file(STRINGS "filename.txt" file_lines)

# 读取并去除注释和空行
file(STRINGS "filename.txt" file_lines REGEX "^[^#]")

写入文件

cmake 复制代码
# 写入内容到文件(覆盖)
file(WRITE "output.txt" "Some content")

# 追加内容到文件
file(APPEND "output.txt" "More content")

# 生成文件
file(GENERATE OUTPUT "config.h" CONTENT "
#define VERSION \"${VERSION}\"
#define BUILD_TYPE \"${CMAKE_BUILD_TYPE}\"
")

文件操作

cmake 复制代码
# 复制文件
file(COPY "source.txt" DESTINATION "dest/")

# 复制并重命名
file(COPY_FILE "source.txt" "dest/new.txt")

# 删除文件
file(REMOVE "filename.txt")

# 删除多个文件
file(REMOVE_RECURSE "dir1" "dir2")

# 创建目录
file(MAKE_DIRECTORY "new_dir")

文件查找

cmake 复制代码
# 查找文件
file(GLOB source_files "src/*.cpp")

# 递归查找文件
file(GLOB_RECURSE all_sources 
    "src/*.cpp"
    "src/*.h"
)

# 相对路径查找
file(GLOB_RECURSE relative_paths
    RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
    "*.cpp"
)

路径操作

cmake 复制代码
# 获取真实路径
file(REAL_PATH "relative/path" absolute_path)

# 获取相对路径
file(RELATIVE_PATH rel_path 
    "${CMAKE_CURRENT_SOURCE_DIR}" 
    "${CMAKE_CURRENT_BINARY_DIR}"
)

# 规范化路径
file(TO_CMAKE_PATH "path/with\\mixed/separators" cmake_path)
file(TO_NATIVE_PATH "${cmake_path}" native_path)

文件下载

cmake 复制代码
# 下载文件
file(DOWNLOAD 
    "https://example.com/file.zip"
    "${CMAKE_BINARY_DIR}/file.zip"
    SHOW_PROGRESS
)

# 下载并验证
file(DOWNLOAD 
    "https://example.com/file.zip"
    "${CMAKE_BINARY_DIR}/file.zip"
    EXPECTED_HASH SHA256=abcdef...
    TLS_VERIFY ON
)

文件权限

cmake 复制代码
# 设置权限
file(CHMOD "script.sh" PERMISSIONS
    OWNER_READ OWNER_WRITE OWNER_EXECUTE
    GROUP_READ GROUP_EXECUTE
    WORLD_READ WORLD_EXECUTE
)

# 获取权限
file(GET_RUNTIME_DEPENDENCIES
    EXECUTABLES my_exe
    LIBRARIES my_lib
    DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}"
)

Configure_file--从模板生成输出文件

基本用法

cmake 复制代码
configure_file(<model_file> <output_file>)

解释

  • model_file: 模板文件
  • output_file: 输出文件

栗子

  1. 变量替换

    cmake 复制代码
    # config.h.in 文件内容:
    #define VERSION_MAJOR @VERSION_MAJOR@     // 使用 @变量名@ 语法
    #define VERSION_MINOR @VERSION_MINOR@     // 使用 @变量名@ 语法
    #define PROJECT_NAME "${PROJECT_NAME}"    // 使用 ${变量名} 语法
    
    # CMakeLists.txt
    set(VERSION_MAJOR 1)
    set(VERSION_MINOR 0)
    configure_file(
        "config.h.in"
        "${PROJECT_BINARY_DIR}/config.h"
    )
    
    # 生成的 config.h 文件内容会是:
    #define VERSION_MAJOR 1
    #define VERSION_MINOR 0
    #define PROJECT_NAME "YourProjectName"
  2. 条件替换

    cmake 复制代码
    # config.h.in
    #cmakedefine USE_FEATURE      // 条件定义宏
    #cmakedefine01 HAVE_LIBRARY   // 条件定义为0或1
    
    # CMakeLists.txt
    option(USE_FEATURE "Enable feature" ON)    # 设置为ON
    set(HAVE_LIBRARY TRUE)                     # 设置为TRUE
    configure_file(
        "config.h.in"
        "${PROJECT_BINARY_DIR}/config.h"
    )
    
    # 生成的 config.h 文件内容会是:
    #define USE_FEATURE           // 因为 USE_FEATURE 是 ON
    #define HAVE_LIBRARY 1        // 因为 HAVE_LIBRARY 是 TRUE

    add_subdirectory--构建添加子目录

    基本用法

    cmake 复制代码
    add_subdirectory(source_dir)

    解释

    • source_dir : 子目录中CMakeLists.txt路径

    栗子

    项目结构

    project/

    ├── CMakeLists.txt

    ├── src/

    │ ├── CMakeLists.txt

    │ └── main.cpp

    ├── lib/

    │ ├── CMakeLists.txt

    │ └── library.cpp

    └── tests/

    ├── CMakeLists.txt

    └── test.cpp

CMakeLists.txt
cmake 复制代码
cmake_minimum_required(VERSION 3.10)
project(MyProject)

# 添加各个子目录
add_subdirectory(src)
add_subdirectory(lib)
add_subdirectory(tests)

add_library--创建一个库

基本用法

与下面set_target_properties搭配使用

cmake 复制代码
add_library(<name> [STATIC | SHARED] [SOURCE1 | SOURCE2])

解释

  • name: 库的名称
  • [STATIC | SHARED]: 库的类型
  • [SOURCE1 | SOURCE2]: 源文件的地址

栗子

创建普通库

cmake 复制代码
# 1. 创建静态库 (.a / .lib)
add_library(mylib STATIC source1.cpp source2.cpp)

# 2. 创建动态库 (.so / .dll)
add_library(mylib SHARED source1.cpp source2.cpp)

导入外部库

cmake 复制代码
# 导入预编译的共享库
add_library(thirdparty SHARED IMPORTED)
set_target_properties(thirdparty PROPERTIES
    IMPORTED_LOCATION "/path/to/libthirdparty.so"
)

set_target_properties--设置目标文件的属性

基本用法

常用语设置库的相关属性,栗子,参考上方

cmake 复制代码
set_target_properties(target1 target2 ...
                     PROPERTIES
                     prop1 value1
                     prop2 value2 ...)

target_include_directories--添加头文件搜索路径

基本用法

cmake 复制代码
target_include_directories(<target> 
    <INTERFACE|PUBLIC|PRIVATE> [items1...]
    <INTERFACE|PUBLIC|PRIVATE> [items2...])

解释

  • target: 目标文件
  • <INTERFACE|PUBLIC|PRIVATE>: 权限
  • item: 头文件搜索路径

栗子

PRIVATE

cmake 复制代码
# 只有当前目标能使用这些包含目录
target_include_directories(mylib PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}/internal
)

PUBLIC

cmake 复制代码
# 当前目标和链接此目标的其他目标都能使用这些包含目录
target_include_directories(mylib PUBLIC
    ${CMAKE_CURRENT_SOURCE_DIR}/include
)

INTERFACE

cmake 复制代码
# 只有链接此目标的其他目标能使用这些包含目录
target_include_directories(mylib INTERFACE
    ${CMAKE_CURRENT_SOURCE_DIR}/public_api
)

基本用法

cmake 复制代码
target_link_libraries(<target>
    <PRIVATE|PUBLIC|INTERFACE> <item>...
    [<PRIVATE|PUBLIC|INTERFACE> <item>...]...)

解释

  • target: 链接后的名称
  • <PRIVATE|PUBLIC|INTERFACE>: 权限
  • item: 要链接的包名
相关推荐
别说我什么都不会12 小时前
ohos.net.http请求HttpResponse header中set-ccokie值被转成array类型
网络协议·harmonyos
码是生活13 小时前
鸿蒙开发排坑:解决 resourceManager.getRawFileContent() 获取文件内容为空问题
前端·harmonyos
鸿蒙场景化示例代码技术工程师13 小时前
基于Canvas实现选座功能鸿蒙示例代码
华为·harmonyos
小脑斧爱吃鱼鱼14 小时前
鸿蒙项目笔记(1)
笔记·学习·harmonyos
鸿蒙布道师14 小时前
鸿蒙NEXT开发对象工具类(TS)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
zhang10620915 小时前
HarmonyOS 基础组件和基础布局的介绍
harmonyos·基础组件·基础布局
马剑威(威哥爱编程)15 小时前
在HarmonyOS NEXT 开发中,如何指定一个号码,拉起系统拨号页面
华为·harmonyos·arkts
GeniuswongAir16 小时前
Flutter极速接入IM聊天功能并支持鸿蒙
flutter·华为·harmonyos
90后的晨仔19 小时前
鸿蒙ArkUI框架中的状态管理
harmonyos
别说我什么都不会1 天前
OpenHarmony 5.0(API 12)关系型数据库relationalStore 新增本地数据变化监听接口介绍
api·harmonyos