• Cmake常用命令


    设置工程名

    # 以前的旧版本是没有设置的,这个可以设置,也可以不设置
    project("NdkDemo")
    
    • 1
    • 2

    最低支持的版本

    # 注意:这里并不能代表最终的版本,最终版本在app.build.gradle中设置的
    cmake_minimum_required(VERSION 3.10.2)
    
    • 1
    • 2

    生成静态库和动态库

    # SHARED表示生成动态库(.so)  STATIC表示生成静态库(.a)
    add_library(native-lib SHARED native-lib.cpp)
    
    • 1
    • 2

    批量导入源码文件

    file(GLOB ALL_FILE *.cpp *.c)
    # 或者使用aux_source_directory
    aux_source_directory(. ALL_FILE)
    add_library(native-lib SHARED  ${ALL_FILE})
    
    • 1
    • 2
    • 3
    • 4

    引入头文件

    include_directories(${CMAKE_SOURCE_DIR}/include)
    if(${CMAKE_ANDROID_ARCH_ABI} MATCHES "armeabi-v7a")
        include_directories(${CMAKE_SOURCE_DIR}/include/armeabi-v7a)
        message("This is armeabi-v7a")
    elseif(${CMAKE_ANDROID_ARCH_ABI} MATCHES "arm64-v8a")
        include_directories(${CMAKE_SOURCE_DIR}/include/arm64-v8a)
        message("This is arm64-v8a")
    endif()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    导入静态库或动态库(第一种方式)

    # 全部导入,需设置CMAKE_CXX_FLAGS环境变量容易出错
    # 设置库文件路径  设置CMAKE_CXX_FLAGS环境变量(库的路径)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}")
    
    • 1
    • 2
    • 3

    导入静态库或动态库(第二种方式)

    # 单个导入,比较清晰,但是工作量大
    # 导入静态库
    add_library(testNdk STATIC IMPORTED)
    # 开始真正导入
    set_target_properties(testNdk PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libtestNdk.a)
    
    # 导入动态库 
    add_library(testNdk SHARED IMPORTED)
    # 开始真正导入
    set_target_properties(testNdk PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}/libtestNdk.so)]]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    搜索指定的预构建库并将路径存储为变量

    # 找到log-lib库并存储为变量log
    find_library(log-lib log)
    
    • 1
    • 2

    链接第三方库或者系统库到目标库

    target_link_libraries(native-lib testNdk ${log-lib})
    
    • 1

    添加一个子目录并构建该子目录

    # sub/CMakeLists.txt
    cmake_minimum_required(VERSION 3.10.2)
    project(sub)
    add_library(sub test.cpp)
    
    # 父目录下的CMakeLists.txt
    cmake_minimum_required(VERSION 3.10.2)
    project(test)
    add_subdirectory(sub) 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    目录结构如下:

    ├── CMakeLists.txt  #父目录的CMakeList.txt
    ├── main.cpp     #源文件,包含main函数
    ├── sub     #子目录
     └── CMakeLists.txt #子目录的CMakeLists.txt
     └── test.h     #子目录头文件
     └── test.cpp    #子目录源文件

    常用内置变量

    • CMAKE_SOURCE_DIR :当前CMakeLists.txt文件所在的文件夹路径
    • CMAKE_BINRAY_DIR :对应cmake的build的目录,主要是运行时生成的文件目录
    • CMAKE_CURRENT_SOURCE_DIR :一般来说,一个工程会有多个cmakelists.txt文件,对应当前文件目录
    • CMAKE_CURRENT_BINARY_DIR :对应build里的目录
    • CMAKE_ANDROID_ARCH_ABI :当前android abi架构类型

    log 日志输出

    #[[
    (无):重要消息
    STATUS:非重要消息
    WARNING:CMake警告, 会继续执行
    AUTHOR_WARNING:CMake警告(dev), 会继续执行
    SEND_ERROR:CMake错误, 继续执行,但是会跳过生成的步骤
    FATAL_ERROR:CMake错误, 终止所有处理过程
    ]]
    message(STATUS "print message")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    变量

    # 声明变量:set(变量名 变量值),CMake中所有变量都是string类型
    set(var 666)
    # 引用变量
    message("var = ${var}")
    # 移除变量
    unset(var)
    # 会取不到值,因为被移除了
    message("my_var = ${var}")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    列表

    # 声明列表:set(列表名 值1 值2 ... 值N) 或 set(列表名 "值1;值2;...;值N")
    set(list_var 1 2 3 4 5)
    # 或者
    set(list_var2 "1;2;3;4;5")
    message("list_var = ${list_var}")
    message("list_var2 = ${list_var2}")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    条件判断

    一元测试命令:

    • EXIST:判断文件或者目录是否存在,存在时为真。需要提供全路径;如果文件或者目录是符号链接(例如软连接),则只有当链接的目标存在时返回真。格式为:if(EXISTS path-to-file-or-directory)。
    • COMMAND:如果给定的名称是命令、宏或者函数这类可被调用的对象,则返回真。格式为:if(COMMAND command-name)。
    • DEFINED:如果给定的变量(普通变量、缓存变量、环境变量)存在,则返回真。格式为:if(DEFINED <name>|CACHE{<name>}|ENV{<name>}),注意缓存变量前要加CACHE,环境变量前要加ENV。

    二元测试命令,二元操作符有的左边和右边需要提供变量:

    • EQUAL:左边两个字符串或者变量相等时为真。格式为:if(<variable|string> EQUAL <variable|string>)。
    • LESS:左边小于右边时为真(数值比较)。格式为:if(<variable|string> LESS <variable|string>)。
    • LESS_EQUAL:左边小于等于右边时为真(数值比较)。格式为:if(<variable|string> LESS_EQUAL <variable|string>)。
    • GREATER:左边大于右边时为真(数值比较)。格式为:if(<variable|string> GREATER <variable|string>)。
    • GREATER_EQUAL:左边大于等于右边时为真(数值比较)。格式为:if(<variable|string> GREATER_EQUAL <variable|string>)。
    • STREQUAL:左边与右边的字典顺序相等时为真(数值比较)。格式为:if(<variable|string> STREQUAL <variable|string>)。
    • STRLESS:左边的字典顺序小于右边的字典序时为真。格式为:if(<variable|string> STRLESS <variable|string>)。
    • STRLESS_EQUAL:左边的字典顺序小于等于右边的字典序时为真。格式为:if(<variable|string> STRLESS_EQUAL <variable|string>)。
    • STRGREATER:左边的字典顺序大于右边的字典序时为真。格式为:if(<variable|string> STRGREATER <variable|string>)。
    • STRGREATER_EQUAL:左边的字典顺序大于等于右边的字典序时为真。格式为:if(<variable|string> STRGREATER_EQUAL <variable|string>)。
    • VERSION_EQUAL:左右两边的版本号相等时为真。左右两边的版本号格式为major[.minor[.patch[.tweak]]],每个部分都要求是整数(省略的部分当做0),如果是非整数,从非整数的地方往后会被截断。格式为:if(<variable|string> VERSION_EQUAL <variable|string>)。
    • VERSION_LESS:左边版本号小于右边版本号时为真。左右两边的版本号格式为major[.minor[.patch[.tweak]]],每个部分都要求是整数(省略的部分当做0)),如果是非整数,从非整数的地方往后会被截断。格式为:if(<variable|string> VERSION_LESS <variable|string>)。
    • VERSION_LESS:左边版本号小于右边版本号时为真。左右两边的版本号格式为major[.minor[.patch[.tweak]]],每个部分都要求是整数(省略的部分当做0),如果是非整数,从非整数的地方往后会被截断。格式为:if(<variable|string> VERSION_LESS <variable|string>)。
    • VERSION_LESS_EQUAL:左边版本号小于等于右边版本号时为真。左右两边的版本号格式为major[.minor[.patch[.tweak]]],每个部分都要求是整数(省略的部分当做0),如果是非整数,从非整数的地方往后会被截断。格式为:if(<variable|string> VERSION_LESS_EQUAL <variable|string>)。
    • VERSION_GREATER:左边版本号大于右边版本号时为真。左右两边的版本号格式为major[.minor[.patch[.tweak]]],每个部分都要求是整数(省略的部分当做0),如果是非整数,从非整数的地方往后会被截断。格式为:if(<variable|string> VERSION_GREATER <variable|string>)。
    • VERSION_GREATER_EQUAL:左边版本号大于等于右边版本号时为真。左右两边的版本号格式为major[.minor[.patch[.tweak]]],每个部分都要求是整数(省略的部分当做0),如果是非整数,从非整数的地方往后会被截断。格式为:if(<variable|string> VERSION_GREATER_EQUAL <variable|string>)。
    • MATCHES:按照正则表达式去匹配,左边是待匹配的值,右边是正则表达式,能匹配为时为真。格式为:if(<variable|string> MATCHES regex)。

    一元逻辑操作符号:

    • NOT:条件不满足时为真。格式为:if(NOT <condition>)。

    二元逻辑操作符:

    • AND:左右两边条件均成立时为真。格式为:if(<cond1> AND <cond2>)。
    • OR:左右两边条件任一个成立时为真。格式为:if(<cond1> OR <cond2>)。

    CMake流程控制-条件命令

    # true(1,ON,YES,TRUE,Y,非0的值) === true
    # false(0,OFF,NO,FALSE,N,IGNORE,NOTFOUND)  === false
    set(if_tap OFF) # 定义一个变量if_tap,值为false
    set(elseif_tap ON) # 定义一个变量elseif_tap,值为ture
    
    if(${if_tap})
        message("if")
    elseif(${elseif_tap})
        message("elseif")
    else(${if_tap})   # 可以不加入 ${if_tap}
        message("else")
    endif() # 结束if 可以不加
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    CMake流程控制-循环命令while

    set(a "")
    while(NOT a STREQUAL "xxx")
        set(a "${a}x")
        message(">>>>>>a = ${a}")
    endwhile()
    #[[ 
    break()命令可以跳出整个循环
    continue()可以继续当前循环
    ]]
    
    foreach(item 1 2 3)
        message("1item = ${item}")
    endforeach(item) # 结束for
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    CMake流程控制-循环命令foreach

    foreach(item 1 2 3)
        message("1item = ${item}")
    endforeach(item) # 结束for
    
    foreach(item RANGE 2) # RANGE 默认从0开始
        message("2item = ${item}")
    endforeach(item)
    
    foreach(item RANGE 1 6 2) #  1 3 5 step为2
        message("3item = ${item}")
    endforeach(item)
    
    set(list_va3 1 2 3)
    # foreach(item IN LISTS ${list_va3}) # 没有报错,没有循环
    foreach(item IN LISTS list_va3) # 正规的写法
        message("item = ${item}")
    endforeach(item)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    CMake自定义函数

    # CMake自定义函数和Shell的函数很类似
    #[[
    ARGC:表示传入参数的个数
    ARGV0:表示第一个参数,ARGV1、ARGV2以此类推即可
    ARGV:表示所有参数
    ]]
    function(method n1 n2 n3)
        message("call num_method method")
        message("n1 = ${n1}")
        message("n2 = ${n2}")
        message("n3 = ${n3}")
        message("ARGC = ${ARGC}")
        message("arg1 = ${ARGV0} arg2 = ${ARGV1} arg3 = ${ARGV2}")
        message("all args = ${ARGV}")
    endfunction(method)
    method(10000 2000 3000)  # 调用method函数
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    参考文档

    https://cmake.org/cmake/help/latest/index.html

  • 相关阅读:
    【大学复健】两种质朴的素数筛法
    String类常用方法总结
    【OpenCV 例程200篇】208. Photoshop 对比度自动调整算法
    测试工作3年还在基础岗?可能只是因为你的工作能力差
    构建基于Transformer的推荐系统
    【C++学习笔记】静态多态与动态多态
    git常见问题操作
    LQ0143 砍竹子【序列处理】
    《最新出炉》系列初窥篇-Python+Playwright自动化测试-25-处理单选和多选按钮-中篇
    一些逻辑漏洞案例
  • 原文地址:https://blog.csdn.net/ZYJWR/article/details/125599556