Android CMakeLists.txt语法详解
一.CMake简介

你或许听过好几种 Make 工具,例如 GNU Make ,QT 的 qmake ,微软的 MSnmake,BSD Make(pmake),Makepp,等等。这些 Make 工具遵循着不同的规范和标准,所执行的 Makefile 格式也千差万别。这样就带来了一个严峻的问题:如果软件想跨平台,必须要保证能够在不同平台编译。而如果使用上面的 Make 工具,就得为每一种标准写一次 Makefile ,这将是一件让人抓狂的工作。
CMake CMake附图 1 CMake就是针对上面问题所设计的工具:它首先允许开发者编写一种平台无关的 CMakeList.txt 文件来定制整个编译流程,然后再根据目标用户的平台进一步生成所需的本地化 Makefile 和工程文件,如 Unix 的 Makefile 或 Windows 的 Visual Studio 工程。从而做到“Write once, run everywhere”。显然,CMake 是一个比上述几种 make 更高级的编译配置工具。一些使用 CMake 作为项目架构系统的知名开源项目有 VTK、ITK、KDE、OpenCV、OSG 等。
二.常用命令
指定 cmake 的最小版本:
cmake_minimum_required(VERSION 3.4.1)
这行命令是可选的,我们可以不写这句话,但在有些情况下,如果 CMakeLists.txt 文件中使用了一些高版本 cmake 特有的一些命令的时候,就需要加上这样一行,提醒用户升级到该版本之后再执行 cmake。
设置项目名称:
project(demo)
设置编译类型:
add_executable(demo demo.cpp) # 生成可执行文件
add_library(common STATIC util.cpp) # 生成静态库
add_library(common SHARED util.cpp) # 生成动态库或共享库
add_library 默认生成是静态库,通过以上命令生成文件名字:demo libcommon.a libcommon.so
指定编译包含的源文件:
明确指定包含哪些源文件
add_library(demo demo.cpp test.cpp util.cpp)
搜索所有的 cpp 文件
aux_source_directory(. SRC_LIST) # 搜索当前目录下的所有.cpp文件
add_library(demo ${SRC_LIST})
自定义搜索规则:
file(GLOB SRC_LIST "*.cpp" "protocol/*.cpp")
add_library(demo ${SRC_LIST})
# 或者
file(GLOB SRC_LIST "*.cpp")
file(GLOB SRC_PROTOCOL_LIST "protocol/*.cpp")
add_library(demo ${SRC_LIST} ${SRC_PROTOCOL_LIST})
# 或者
file(GLOB_RECURSE SRC_LIST "*.cpp") #递归搜索
FILE(GLOB SRC_PROTOCOL RELATIVE "protocol" "*.cpp") # 相对protocol目录下搜索
add_library(demo ${SRC_LIST} ${SRC_PROTOCOL_LIST})
# 或者
aux_source_directory(. SRC_LIST)
aux_source_directory(protocol SRC_PROTOCOL_LIST)
add_library(demo ${SRC_LIST} ${SRC_PROTOCOL_LIST})
查找指定的库文件:
find_library(VAR name path)查找到指定的预编译库,并将它的路径存储在变量中。
默认的搜索路径为 cmake 包含的系统库,因此如果是 NDK 的公共库只需要指定库的 name 即可。
find_library( # Sets the name of the path variable.log-lib# Specifies the name of the NDK library that# you want CMake to locate.log )
设置包含的目录:
include_directories(${CMAKE_CURRENT_SOURCE_DIR}${CMAKE_CURRENT_BINARY_DIR}${CMAKE_CURRENT_SOURCE_DIR}/include
)
设置 target 需要链接的库:
指定链接动态库或静态库
target_link_libraries(demo libface.a) # 链接libface.a
target_link_libraries(demo libface.so) # 链接libface.so
指定全路径
target_link_libraries(demo ${CMAKE_CURRENT_SOURCE_DIR}/libs/libface.a)
target_link_libraries(demo ${CMAKE_CURRENT_SOURCE_DIR}/libs/libface.so)
指定链接多个库
target_link_libraries(demo${CMAKE_CURRENT_SOURCE_DIR}/libs/libface.aboost_system.aboost_threadpthread)
三.CMake使用案例1
#include <stdio.h>
#include <stdlib.h>
/*** power - Calculate the power of number.* @param base: Base value.* @param exponent: Exponent value.** @return base raised to the power exponent.*/
double power(double base, int exponent)
{int result = base;int i;if (exponent == 0) {return 1;}for(i = 1; i < exponent; ++i){result = result * base;}return result;
}
int main(int argc, char *argv[])
{if (argc < 3){printf("Usage: %s base exponent \n", argv[0]);return 1;}double base = atof(argv[1]);int exponent = atoi(argv[2]);double result = power(base, exponent);printf("%g ^ %d is %g\n", base, exponent, result);return 0;
}
最简单的 CMakeLists.txt 文件:
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (Demo1)
# 指定生成目标
add_executable(Demo main.cc)
多个源文件
同一目录,多个源文件
本小节对应的源代码所在目录:Demo2。
上面的例子只有单个源文件。现在假如把 power 函数单独写进一个名为MathFunctions.c 的源文件里,使得这个工程变成如下的形式:
./Demo2|+--- main.cc|+--- MathFunctions.cc|+--- MathFunctions.h
这个时候,CMakeLists.txt 可以改成如下的形式:
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (Demo2)
# 指定生成目标
add_executable(Demo main.cc MathFunctions.cc)
唯一的改动只是在 add_executable 命令中增加了一个 MathFunctions.cc 源文件。这样写当然没什么问题,但是如果源文件很多,把所有源文件的名字都加进去将是一件烦人的工作。更省事的方法是使用 aux_source_directory 命令,该命令会查找指定目录下的所有源文件,然后将结果存进指定变量名。其语法如下:
aux_source_directory(<dir> <variable>)
因此,可以修改 CMakeLists.txt 如下:
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (Demo2)
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)
# 指定生成目标
add_executable(Demo ${DIR_SRCS})
这样,CMake 会将当前目录所有源文件的文件名赋值给变量 DIR_SRCS ,再指示变量 DIR_SRCS 中的源文件需要编译成一个名称为 Demo 的可执行文件。
多个目录,多个源文件
本小节对应的源代码所在目录:Demo3。
现在进一步将 MathFunctions.h 和 MathFunctions.cc 文件移动到 math 目录下。
./Demo3|+--- main.cc|+--- math/|+--- MathFunctions.cc|+--- MathFunctions.h
对于这种情况,需要分别在项目根目录 Demo3 和 math 目录里各编写一个 CMakeLists.txt 文件。为了方便,我们可以先将 math 目录里的文件编译成静态库再由 main 函数调用。
根目录中的 CMakeLists.txt :
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (Demo3)
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)
# 添加 math 子目录
add_subdirectory(math)
# 指定生成目标
add_executable(Demo main.cc)
# 添加链接库
target_link_libraries(Demo MathFunctions)
该文件添加了下面的内容: 第3行,使用命令 add_subdirectory 指明本项目包含一个子目录 math,这样 math 目录下的 CMakeLists.txt 文件和源代码也会被处理 。第6行,使用命令 target_link_libraries 指明可执行文件 main 需要连接一个名为 MathFunctions 的链接库 。
子目录中的 CMakeLists.txt:
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_LIB_SRCS 变量
aux_source_directory(. DIR_LIB_SRCS)
# 生成链接库
add_library (MathFunctions ${DIR_LIB_SRCS})
四.CMake使用案例2
例一
目录结构为:
lzj@lzj:~/C-Plus-Plus/makefile_cmake/cmake_1$ tree
.
├── build
├── CMakeLists.txt
└── src├── hello│ ├── hello.cc│ └── hello.h├── main.cpp└── world├── world.cc└── world.h
src 目录中不同属性类维护在不同目录中
main.cpp中使用hello.h和world.h
CMakeLists.txt为 :
cmake_minimum_required (VERSION 3.0)
project (test_1)aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/src/hello SOURCE_HELLO)
aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/src/world SOURCE_WORLD)add_definitions("-g -Wall -std=c++11")add_executable(main${CMAKE_CURRENT_LIST_DIR}/src/main.cpp${SOURCE_HELLO}${SOURCE_WORLD})
例二
目录结构为:
lzj@lzj:~/C-Plus-Plus/makefile_cmake/cmake_2$ tree
.
├── build
├── CMakeLists.txt
├── include
│ └── person.h
└── src├── main.cpp└── person.cc
include目录下统一包含头文件和宏定义之类, 源文件放在 src 目录下维护
person 类是一个简单的空类, 拥有一个私有成员变量val, 一个公有成员函数来打印该变量, 在main.cpp中调用
CMakeLists.txt为 :
cmake_minimum_required(VERSION 3.0)
project(test_2)include_directories(${PROJECT_SOURCE_DIR}/include)add_definitions("-g -Wall -std=c++11")add_executable(main${PROJECT_SOURCE_DIR}/src/main.cpp #这个路径看这个main.cpp位于哪里了 ${PROJECT_SOURCE_DIR}/src/person.cc)
例三
目录结构为:
lzj@lzj:~/C-Plus-Plus/makefile_cmake/cmake_3$ tree
.
├── build
├── CMakeLists.txt
├── main.cpp
└── src├── CMakeLists.txt├── hello.cc├── hello.h├── world.cc└── world.h
将编写的代码编译为库, 在main.cpp中使用, 编译main.cpp时链接该库
顶层目录中CMakeLists.txt为:
cmake_minimum_required (VERSION 3.0)
project (test_3)add_subdirectory(src)add_definitions("-g -Wall -std=c++11")add_executable(main main.cpp)
target_link_libraries(main TEST3) #自己的库名为TEST3
子目录 src 中的CMakeLists.txt为:
aux_source_directory(. DIR_LIB_SRCS)add_library (TEST3 ${DIR_LIB_SRCS})
当然如果src目录下为多文件时, 每个目录下都要添加该语句的CMakeLists.txt
相关文章:
Android CMakeLists.txt语法详解
一.CMake简介 你或许听过好几种 Make 工具,例如 GNU Make ,QT 的 qmake ,微软的 MSnmake,BSD Make(pmake),Makepp,等等。这些 Make 工具遵循着不同的规范和标准,所执行的…...
Vue3快速上手(二)VSCode官方推荐插件安装及配置
一、VSCode官方插件安装,如下图2款插件 在用vite创建的程序里,提示提安装推荐的插件了,如下图: 二、配置 在设置-扩展里找到Volar插件,将Dot Value勾选上。这样在ref()修改变量时,会自动填充.value,无需…...
等保2、3级所需设备
三级等保要求及所需设备 《等级保护基本要求》所需设备 结构安全(G3) b)应保证网络各个部分的宽带满足业务高峰期需要; g)应按照对业务服务的需要次序来指定宽带分配优先级别,保证在网络发生拥堵的时候优先保护重要主机 负载均衡…...
6 scala-面向对象编程基础
Scala 跟 Java 一样,是一门面向对象编程的语言,有类和对象的概念。 1 类与对象 与 Java 一样,Scala 也是通过关键字 class 来定义类,使用关键字 new 创建对象。 要运行我们编写的代码,同样像 Java 一样,…...
【linux温故】linux调度机制
假如你是设计者,你会设计怎样的调度机制呢? 时间片 最简单的,小学生都能想出来的一种,每个 ready task,按照一个固定的时间片轮流执行。 大家不要抢,挨个儿排队执行。执行完时间片,就排在后面…...
django中如何使用mysql连接池
一:介绍 在Django中使用MySQL时,通常情况下,Django的数据库层会为你管理数据库连接。Django的数据库接口是线程安全的,这意味着它会自动为每个线程创建和管理数据库连接。在大多数情况下,你不需要手动创建线程池来管理…...
3D高斯溅射:面向三维场景的实时渲染技术
1. 前言 高斯溅射技术【1】一经推出,立刻引起学术界和工业界的广泛关注。相比传统的隐式神经散射场渲染技术,高斯溅射依托椭球空间,显性地表示多目图像的三维空间关系,其计算效率和综合性能均有较大的提升,且更容易理…...
【数据结构】13:表达式转换(中缀表达式转成后缀表达式)
思想: 从头到尾依次读取中缀表达式里的每个对象,对不同对象按照不同的情况处理。 如果遇到空格,跳过如果遇到运算数字,直接输出如果遇到左括号,压栈如果遇到右括号,表示括号里的中缀表达式已经扫描完毕&a…...
MySQL进阶查询篇(9)-视图的创建和应用
数据库视图是MySQL中一个非常重要的概念。它是一个虚拟表,由一个查询的结果集组成。数据库视图为用户提供了一种简化数据查询和操作的方式。本文将介绍MySQL数据库视图的创建和应用。 1. 创建数据库视图 要创建MySQL数据库视图,我们使用CREATE VIEW语句…...
Rhino.Inside带材质将Revit模型bake到Rhino
Hello大家好!我是九哥~ 今天来讲一个小技巧,就是我通常采用RIR将Revit的模型的Geometry Bake到Rhino,肯定是没有材质的,那么如果我们需要带材质那要怎么办呢? 对于会的人,其实挺简单的,只需要…...
随记-Java项目处理SQL注入问题
现象:http://10.xx.xx.xx:xx/services/xxService 存在SQL注入情况 加固意见: 需要对网站所有参数中提交的数据进行过滤,禁止输入“"、"xor"、"or"、”--“、”#“、”select“、”and“等特殊字符;所有…...
精读《js 模块化发展》
1 引言 如今,Javascript 模块化规范非常方便、自然,但这个新规范仅执行了 2 年,就在 4 年前,js 的模块化还停留在运行时支持,10 年前,通过后端模版定义、注释定义模块依赖。对经历过来的人来说,…...
Proteus -模拟串口被关闭后怎样打开
Proteus -模拟串口被关闭后怎样打开 点击恢复弹出窗口,即可重新打开...
【深度学习】pytorch 与 PyG 安装(pip安装)
【深度学习】pytorch 与 PyG 安装(pip安装) 一、PyTorch安装和配置(一)、安装 CUDA(二)、安装torch、torchvision、torchaudio三个组件(1)下载镜像文件(2)创建…...
Bert与ChatGPT
1. Bert模型 BERT(Bidirectional Encoder Representations from Transformers)是一种预训练语言表示的方法,由Google AI在2018年提出。它标志着自然语言处理(NLP)领域的一个重大进步,因为它能够理解单词在…...
微信自动预约小程序开发指南:从小白到专家
随着互联网的发展,小程序已经成为了一个备受欢迎的在线预约平台。本文将详细介绍如何使用第三方制作平台,如乔拓云网,来搭建一个从入门到精通的预约小程序。 首先,我们需要登录乔拓云网,并选择一个适合自己的小程序模板…...
巴尔加瓦算法图解【完结】:算法运用(下)
目录 布隆过滤器HyperLogLogSHA算法比较文件检查密码 Diffie-Hellman密钥交换线性规划结语(完结) 布隆过滤器 在元素很多的情况下,判断一个元素是否在集合中可以使用布隆过滤器。布隆过滤器(Bloom Filter)是 1970 年由…...
hexo部署到gitee(码云)
引言 Hexo 是一个基于Node.js的静态博客框架,而 Gitee(也被称为码云)是一个国内的代码托管平台,支持 Git 版本控制系统,与 GitHub 类似。将 Hexo 部署到 Gitee Pages 可以让你的博客受益于 Gitee 的国内服务器…...
linux系统非关系型数据库memcached
memcached 特点原理配置安装Memcached 特点 内置内存存储方式-----------为了提高性能,memcached中保存的数据都存储在memcache内置的内存存储空间中。由于数据仅存在于内存中,重启操作系统会导致全部数据消失简单key/value存储---------------服务器不…...
前端vite+vue3——自动化配置路由布局
文章目录 ⭐前言💖vue3系列文章 ⭐ 自动化配置路由💖引入vite版本自定义目录映射💖自动化读取文件下的路由💖main入口加载路由💖入口app.vue配置💖layout基础布局配置💖效果 ⭐总结⭐结束 ⭐前言…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...
【Linux】自动化构建-Make/Makefile
前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具:make/makfile 1.背景 在一个工程中源文件不计其数,其按类型、功能、模块分别放在若干个目录中,mak…...
Linux部署私有文件管理系统MinIO
最近需要用到一个文件管理服务,但是又不想花钱,所以就想着自己搭建一个,刚好我们用的一个开源框架已经集成了MinIO,所以就选了这个 我这边对文件服务性能要求不是太高,单机版就可以 安装非常简单,几个命令就…...
在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南
在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南 背景介绍完整操作步骤1. 创建Docker容器环境2. 验证GUI显示功能3. 安装ROS Noetic4. 配置环境变量5. 创建ROS节点(小球运动模拟)6. 配置RVIZ默认视图7. 创建启动脚本8. 运行可视化系统效果展示与交互技术解析ROS节点通…...
