CMake 笔记

news2024/9/22 19:33:35

CMake 笔记

  • CMake 笔记
    • 基础项目
    • 多个目录创建项目
      • 链接库
        • 用到的指令
        • 实验
      • 使用自定义库
        • 用到的指令
        • 实验
    • 指定 C++ 标准
    • CMake常见变量名

基础项目

实现一个CMakeLists.txt最简单是以下三步:

# 最低 CMake 版本要求:指定项目所需的最低 CMake 版本
cmake_minimum_required(VERSION 3.12)

# 项目名称:使用 project() 命令设置项目的名称
project(MyProject)

# 将源文件添加到项目中
add_executable(myapp main.cpp)

以后接触到的CMakeLists.txt内容都是基于这三步进行扩展和延伸
问题来了,如果我们只有一个源文件,用这三步当然可以,但是,如果我们有100个呢?这种方式显然不适用了。

aux_source_directory

该命令会查找指定目录下的所有源文件,然后将结果存进指定变量名。

aux_source_directory(<dir> <variable>)
  • dir:指定目录
  • variable:变量

因此,可以修改 CMakeLists.txt 如下:

# 最低 CMake 版本要求:指定项目所需的最低 CMake 版本
cmake_minimum_required(VERSION 3.12)

# 项目名称:使用 project() 命令设置项目的名称
project(MyProject)

# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)

# 将源文件添加到项目中
add_executable(myapp ${DIR_SRCS})

多个目录创建项目

链接库

上述过程都是建立在一个目录下的,实际的项目往往包含几十个甚至上百个目录,因此我们需要添加需要编译的子目录。

用到的指令

# 于添加子目录的命令,用于将其他 CMakeLists.txt 文件所在的子目录添加到当前项目中
add_subdirectory(<directory> [binary_dir] [EXCLUDE_FROM_ALL])
# - directory:子目录的路径,可以是相对路径或绝对路径
# - binary_dir:放置输出文件的目录,若未指定,输出到 source_dir 指定的目录下
# - EXCLUDE_FROM_ALL:只在生成的输出目录中开始构建
# 用于创建库(静态库或共享库)的命令
add_library(<name> [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL]
            [source1] [source2 ...])
# - name:要创建的库的名称。
# - 库的类型:(STATIC,SHARED 或 MODULE),默认创建一个静态库
# - EXCLUDE_FROM_ALL 是一个可选标志,表示将库排除在构建系统的 "all" 目标之外,即不会随默认构建一起构建
# - [source1] [source2 ...] 是库的源文件列表。可以将源文件逐个列出,也可以使用变量、通配符等方法指定源文件
# 用于为目标添加包含目录的命令,它指定了目标(可执行文件、库等)的头文件搜索路径
target_include_directories(target_name [SYSTEM] [BEFORE]
                           <INTERFACE|PUBLIC|PRIVATE> [directory1] [directory2 ...])
# - target_name:目标的名称,通过 add_executable 或 add_library 命令定义的名称
# - directoryx:添加的目录列表,可以指定一个或多个目录
# - <INTERFACE|PUBLIC|PRIVATE> 是一个可选标记,用于指定目录的可见性范围。这些标记之间的区别如下:
#   - INTERFACE 表示指定目录为接口依赖项,并适用于目标的使用者。
#   - PUBLIC 表示指定目录为公共依赖项,并适用于目标的使用者和目标本身。
#   - PRIVATE 表示指定目录仅适用于目标本身。
# 为目标添加链接库的命令。它用于将库与可执行文件或其他库进行链接
target_link_libraries(target_name [PRIVATE|PUBLIC|INTERFACE] library1 library2 ...)

实验

首先,在math文件夹中创建一个 CMakeLists.txt 文件,写入

# 查找当前目录下的所有源文件,保存到 DIR_LIB_SRCS 变量
aux_source_directory(. DIR_LIB_SRCS)

# 生成链接库
add_library (mathlib ${DIR_LIB_SRCS})

其次,回到项目目录下,在 CMakeLists.txt 文件写入

# 最小版本
cmake_minimum_required(VERSION 3.0)
# 工程名
project(Test VERSION 1.0)

# # 添加 math 子目录
add_subdirectory(math)

# 将所有相关文件都添加进来,用于编译
add_executable(myapp main.cpp)

# 为目标添加包含目录的命令
# 添加库的搜索路径,PROJECT_SOURCE_DIR 是工程顶层目录
target_include_directories(myapp PUBLIC "${PROJECT_SOURCE_DIR}/math")

# 链接库
target_link_libraries (myapp mathlib)

源码见Demo2

使用自定义库

CMake 允许为项目增加编译选项,从而可以根据用户的环境和需求选择最合适的编译方案。例如,可以将 mathlib 库设为一个可选的库。

用到的指令

option(<option_name> <option_description> [default_value])
# <option_name> 是选项的名称,可以是任意合法的标识符。
# <option_description> 是对选项的描述,将在配置过程中显示给用户(随便写)
# [default_value] 是一个可选参数,用于指定选项的默认值。如果未提供默认值,则默认为 OFF
# 示例:option(ENABLE_FEATURE "Enable some feature" ON)
# 添加头文件搜索路径,以便编译器可以找到所需的头文件
include_directories([AFTER|BEFORE] [SYSTEM] directory1 [directory2 ...])
# AFTER 或 BEFORE 是可选标记,用于指定添加目录的位置,是在已有目录之后还是之前,默认是 AFTER。
# SYSTEM 是可选标记,用于标记目录为系统目录,以区分于用户目录。某些编译器可能会有不同的处理方式。
# directory1 [directory2 ...] 是一个或多个目录路径,用于添加到包含目录中。
# 示例:include_directories(include)

与 target_include_directories 区别在于后者是已经得到可执行目标文件

实验

基于 Demo2 只修改项目根目录下的 CMakeLists.txt 文件

# 最小版本
cmake_minimum_required(VERSION 3.0)
# 工程名
project(Test VERSION 1.0)

# 加入一个配置头文件,用于处理 CMake 对源码的设置
configure_file (
  "${PROJECT_SOURCE_DIR}/config.h.in"
  "${PROJECT_SOURCE_DIR}/config.h"
  )

# 是否使用自己的库
option(USE_MYLIB "Use my math implementation" ON)
if(USE_MYLIB)
    include_directories("${PROJECT_SOURCE_DIR}/math")
    # 添加 math 子目录
    add_subdirectory(math)
    # 这将把变量 EXTRA_LIBS 的当前值与 mathlib 连接起来,并将结果赋值给 EXTRA_LIBS 变量。新值将包含原始值和新添加的值
    set(EXTRA_LIBS ${EXTRA_LIBS} mathlib)
endif(USE_MYLIB)

# 将所有相关文件都添加进来,用于编译
add_executable(myapp main.cpp)

# 添加库的搜索路径,PROJECT_SOURCE_DIR 是工程顶层目录
target_include_directories(myapp PUBLIC "${PROJECT_SOURCE_DIR}/math")

# 链接库
target_link_libraries (myapp ${EXTRA_LIBS})

main.cpp

#include <cstdlib>
#include <iostream>
#include "config.h"
using namespace std;


#ifdef USE_MYLIB
  #include "head.h"
#else
  #include <math.h>
#endif

int main(int argc, char const *argv[]) {
  int a = 20;
  int b = 12;
  printf("a = %d, b = %d\n", a, b);
  printf("a + b = %d\n", add(a, b));
  printf("a - b = %d\n", subtract(a, b));
  printf("a / b = %f\n", divide(a, b));
  printf("a * b = %d\n", multiply(a, b));
  printf("a / b = %f\n", divide(a, b));

  #ifdef USE_MYLIB
  cout<<"use my lib"<<endl;
  #else
  cout<<"don't use my lib"<<endl;
  #endif
  return 0;
}

执行后会自动生成一个 config.h 文件,如果 option(USE_MYLIB "Use my math implementation" ON)就会用自己的库,如果option(USE_MYLIB "Use my math implementation" OFF)就会调用 math.h

set

# SET 指令的语法是:
# [] 中的参数为可选项, 如不需要可以不写
SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])

find_package

指定 C++ 标准

#最小版本
cmake_minimum_required(VERSION 3.0)
#工程名
project(Test)

#这两个命令通常一起使用,以确保编译器使用所需的 C++ 标准进行编译。
set(CMAKE_CXX_STANDARD 11)#设置要使用的 C++ 标准为 C++11
set(CMAKE_CXX_STANDARD_REQUIRED True)#表示要求编译器使用指定的 C++ 标准

#add_subdirectory(doctest)

aux_source_directory(. DIR_SRCS)

#将所有相关文件都添加进来,用于编译
add_executable(myapp ${DIR_SRCS})

CMake常见变量名

CMake常用变量和指令

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/728601.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

<网络编程>网络基础

目录 计算机网络背景 认识“协议”&#xff1a; TCP/IP五层模型 网络传输基本流程 不在一个局域网进行通信 了解网络发展背景&#xff0c;对局域网/广域网的概念认识 了解网络协议意义&#xff0c;重点理解TCP/IP五层结构 学习网络传输的基本流程&#xff0c;理解封装和…

gRPC远程调用协议

gRPC 简介 gRPC是一个现代的、高性能、开源的和语言无关的通用 RPC 框架&#xff0c;基于 HTTP2 协议设计&#xff0c;序列化使用PB(Protocol Buffer)&#xff0c;PB 是一种语言无关的高性能序列化框架&#xff0c;基于 HTTP2PB 保证了的高性能。 HTTP2.0 grpc采用HTTP2.0&…

NFT Insider #100:The Sandbox 展示泰国 2023 年元宇宙生态系统,​游戏巨头世嘉暂缓链游项目开发

引言&#xff1a;NFT Insider由NFT收藏组织WHALE Members、BeepCrypto联合出品&#xff0c;浓缩每周NFT新闻&#xff0c;为大家带来关于NFT最全面、最新鲜、最有价值的讯息。每期周报将从NFT市场数据&#xff0c;艺术新闻类&#xff0c;游戏新闻类&#xff0c;虚拟世界类&#…

第三章 数据链路层【计算机网络】

第三章 数据链路层【计算机网络】 前言推荐第三章 数据链路层3.1 数据链路层的几个共同问题3.1.1 数据链路和帧3.1.2 三个基本问题 3.2点对点协议PPP3.2.1 PPP协议的特点3.2.2 PPP协议的帧格式3.2.3 PPP协议的工作状态 3.3 使用广播信道的数据链路层3.3.1 局域网的数据链路层3.…

ADManager Plus:企业自动化管理的利器

在当今数字化时代&#xff0c;企业管理面临着越来越多的挑战。为了提高效率、降低成本并确保信息安全&#xff0c;自动化管理成为了企业的首要选择。而在众多自动化管理工具中&#xff0c;ADManager Plus无疑是一款卓越的解决方案。本文将为您介绍ADManager Plus的功能与优势&a…

【Accumulate】Gitee解决每次推送输入账户密码问题

【前言】 每次建立私人仓库后&#xff0c;一推送就得输入账户密码&#xff0c;真的巨烦人啊。 【解决】 step1&#xff1a; 绑定私匙&#xff1a; 配置Git_犟小孩的博客-CSDN博客 step2&#xff1a; 每次绑定远程仓库的时候&#xff0c;使用SSH绑定 如果已经绑定过了&…

虚拟化技术(KVM)基础

如何实现虚拟化技术&#xff1f; 三种类型的虚拟机管理软件Hypervisor KVM(kernrl -bsed v m) 环境检查和部署 一、虚拟化技术概述 虚拟化技术就是对资源的抽象 1.1、从资源提供角度分类 平台虚拟化即硬件平台虚拟化&#xff0c;可以把物理机的CPU和MEM提供给来宾主机做资源…

使用Electron来给若依系统打包成exe程序,出现登录成功但是不跳转页面(已解决)

阿丹&#xff1a; 之前解决了css找不到文件等问题&#xff0c;那么新问题就来了&#xff01; 问题描述&#xff1a; 进入到登录页面发现问题&#xff1a; 点击登录一直在转圈&#xff0c;但是不进去&#xff01;&#xff01;&#xff01; 更诡异的是&#xff01;后台相应的很…

vue启动失败;‘vue-cli-service‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件。

问题1&#xff1a; 启动vue项目失败&#xff1a; vue启动失败&#xff1b;‘vue-cli-service‘ 不是内部或外部命令&#xff0c;也不是可运行的程序 或批处理文件。 获或者问题2&#xff1a;npm i 失败&#xff1a; C:\Users\28602\AppData\Roaming\npm-cache_logs\2023-07-07…

一篇看懂web端音频

三方音频录制的库 recorder-core库&#xff1a; github地址&#xff1a;https://github.com/xiangyuecn/Recorder 支持录音格式&#xff1a;mp3 wav ogg webm amr pcm 该库基于Web Audio API&#xff08;html5&#xff09;的录音库&#xff0c;支持在大部分已实现getUserMedi…

安装yum源

三个源&#xff0c;httpd的&#xff1a; 首先&#xff1a;安装yum源 关闭防火墙和安全机制 然后访问本机ip 显示出来&#xff0c;删除掉&#xff0c;然后创建本地yum源 挂载&#xff0c;但是test没有 创建test&#xff0c;然后挂载 必须要进入到这个目录下创建挂载才行&…

(vue)el-table表格删除操作加气泡确认框

(vue)el-table表格删除操作加气泡确认框 效果&#xff1a; 代码&#xff1a; <el-table-column fixed"right" label"操作" width"120"><template slot-scope"scope"><el-popconfirm title"确定移除吗&#xff…

Keepalived及其工作原理

目录 一、keepalived概述 1.1.1 管理LVS负载均衡软件 1.1.2 支持故障自动切换&#xff08;failover&#xff09; 1.1.3 实现LVS集中节点的健康检查&#xff08;health checking&#xff09; 1.1.4 实现LVS负载调度器 节点服务器的高可用性&#xff08;HA&#xff09; 二、…

Stable Diffusion 使用lora-scripts WebUI训练LoRA模型

如果对代码使用有困难的小伙伴可以直接使用WebUI版的LoRA模块进行训练操作。不管是训练人物&#xff0c;场景&#xff0c;风格&#xff0c;还是服装都是一套通用的模式&#xff0c;仅仅是使用不同的数据集得到的结果不同。 文章目录 lora-scripts WebUI的安装LoRA训练过程SD切分…

【贪心】CF1845 C

Problem - C - Codeforces 题意&#xff1a; Code&#xff1a; #include <bits/stdc.h>//#define int long longusing namespace std;const int mxn3e510; const int mxe1e510; const int mod1e97; const int Inf0x3f3f3f3f;string s,l,r;int M;void solve(){s.clear…

前端部署--入门Vercel

Vercel Vercel 你可以理解为一个部署工具&#xff0c;支持部署静态网页和Node服务&#xff0c;部署后你还可以访问它自带生成的域名https。 模版支持 Nuxt.js: Vue的SSR框架 Hexo: 快速生成博客网站 Remix&#xff1a; 一款边缘原生的全栈 JavaScript 框架 … Vercel的核心…

免押租赁软件开发|租赁小程序适合各种产品开发

租赁小程序适合各种产品开发&#xff0c;特别是那些可以通过租赁方式提供给用户使用的产品。以下是一些适合开发租赁小程序的产品类型&#xff1a;   租房&#xff1a;租赁小程序可以方便房东和租客之间的房屋租赁交易。租客可以通过小程序浏览房源信息并联系房东&#xff0c…

力扣 | 数组和字符串简介

数组是数据结构中的基本模块之一。因为字符串是由字符数组形成的&#xff0c;所以二者是相似的。力扣LeetBook——数组和字符串 文章目录 &#x1f4da;数组简介&#x1f449;寻找数组的中心索引&#x1f449;搜索插入位置&#x1f449;合并区间 &#x1f4da;二维数组简介&…

adb连接安卓模拟器或真机hook参数加密详细过程(frida)

app逆向时&#xff0c;参数与函数的确定很关键&#xff0c;找到可疑的函数&#xff0c;不确定是否由该函数生成&#xff0c;该怎么解决&#xff1f;hook就应允而生了&#xff0c;首先是要求本地电脑和安卓模拟器&#xff08;网易mumu模拟器支持多系统&#xff0c;该模拟器作为主…

Docker学习笔记23

Docker Swarm架构&#xff1a; Swarm中以集群&#xff08;Cluster&#xff09;为单位进行管理&#xff0c;支持服务层面的操作。 集群是Swarm所管理的对象。 基本概念&#xff1a; 节点&#xff08;Node&#xff09;为Swarm集群中的一个Docker Engine实例。其中管理节点&#…