news 2025/12/29 22:05:31

cmake_CMake内置属性解决头文件包含/CMake定义C/C++标准/include_directories()/宏定义

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
cmake_CMake内置属性解决头文件包含/CMake定义C/C++标准/include_directories()/宏定义

文章目录

  • 第二章 CMake基础语法
    • 2.20 CMake内置属性解决头文件包含
      • 2.20.1 CMake内置属性
      • 2.20.2 测试文件
      • 2.20.3 解决方法
      • 2.20.4 探究为什么可生成exe ?
    • 2.21 CMAKE_CXX_STANDARD变量设置C++标准
    • 2.22 include_directories()/target_include_directories()
    • 2.23 target_sources() 向目标添加源文件
    • 2.24 add_compile_definitions()/target_compile_definition()添加预定义

本文介绍CMake内置属性解决头文件包含、CMake定义C/C++标准、include_directories()和宏定义。

第二章 CMake基础语法

2.20 CMake内置属性解决头文件包含

2.20.1 CMake内置属性

CMake 中定义了很多范围(全局、目录、目标(例如可执行文件或库)源文件 测试 或者 缓存 等 )内置的属性(Property),用于控制CMake的行为和特性,内置属性可直接使用,而无需显式定义。

2.20.2 测试文件

头文件 和 源文件不在一个目录下面。

#include <iostream>#include "a.h"using namespace std;voidfuncA(){cout<<"Function A called"<<endl;}intmain(){#ifdef AfuncA();#endifcout<<"AAAAAA"<<endl;return0;}

CMakeLists.txt文件如下:

cmake_minimum_required(VERSION3.30)# 项目project(sourceCmake VERSION1.2LANGUAGES CXX)if(NOT CMAKE_BUILD_TYPE)set(CMAKE_BUILD_TYPE Debug CACHE STRING"选择编译类型"FORCE)endif()add_executable(A a.cpp)

编译如下:提示无法找到对应的头文件。

2.20.3 解决方法

在源文件中找不到头文件,使用cmake内置属性来解决。

cmake_minimum_required(VERSION3.30)# 项目project(sourceCmake VERSION1.2LANGUAGES CXX)if(NOT CMAKE_BUILD_TYPE)set(CMAKE_BUILD_TYPE Debug CACHE STRING"选择编译类型"FORCE)endif()add_executable(A a.cpp)# 定义目标属性set_target_properties(A PROPERTIES COMPILE_OPTIONS -Wall COMPILE_DEFINITIONS"A"INCLUDE_DIRECTORIES"${CMAKE_CURRENT_SOURCE_DIR}/sub")#获取目标的属性get_target_property(var1 A COMPILE_OPTIONS)message("COMPILE_OPTIONS=${var1}")# COMPILE_OPTIONS=-Wallget_target_property(var2 A COMPILE_DEFINITIONS)message(" COMPILE_DEFINITIONS=${var2}")# COMPILE_DEFINITIONS=Aget_target_property(var3 A INCLUDE_DIRECTORIES)message(" INCLUDE_DIRECTORIES=${var3}")# INCLUDE_DIRECTORIES=E:/cmakeLearning/chap2/13property/sub

上面找不到头文件问题即可解决。

2.20.4 探究为什么可生成exe ?

在目标属性中添加上 INCLUDE_DIRECTORY后,为什么可以包含头文件呢?,使用下面的-v选项查看。

PS E:\practice_Code\cmake\25>cmake --build build -v

-v 或 –verbose : 启用详细输出,方便查看执行过程。

原理:CMake将设置的目标属性,加入到编译选项中。

2.21 CMAKE_CXX_STANDARD变量设置C++标准

**CMAKE_C_STANDARD :**指定C语高标准、值可以是90 99 11 17 23,当目标创建时作为TARGET属性C_STANDARD的默认值
CMAKE_C_STANDARD_REQUIRED :设置为ON强制使用C标准,设置为OFF则表示可选。如果指定标准不可用,则可会“囊减”到以前的标准。当目标创建时作为TARGET属性C_STANDARD_REQUIRED的默认值
CMAKE_CXX_STANDARD指定C++语标准、值可以是98,11,14,17 ,23 26,当目标创建时作为TARGET属性CXX_STANDARD的默认值
CMAKE_CXX_STANDARD_REQUIRED设置为ON强制使用C++标准,设置为OFF则表示可选,如果指定标准不可用,则可能会“衰减”到以前的标准。当目标创建时作为TARGET属性CXX STANDARD REQUIRED的默认值

CMakeLists.txt

cmake_minimum_required(VERSION3.30)project(main VERSION1.0LANGUAGES CXX)# 查看C++标准message("CMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}")# 变量CMAKE_C_STANDARD=(没设置之前是空置)# 设置C++ 23 标准set(CMAKE_CXX_STANDARD23)message("CMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}")# CMAKE_CXX_STANDARD=23# 严格设置C++标准set(CMAKE_CXX_STANDARD_REQUIRED ON)add_executable(main main.cpp)

2.22 include_directories()/target_include_directories()

include_directories() 作用:告诉编译器去哪里找头文件,相当于-I/path/to/dir。设置头文件后,会传递到当前目录以及所有子目录下的所有cmake。

include_directories([AFTER][BEFORE][SYSTEM]dir1[dir2])

参数:

AFTER|BEFORE : AFTER 是默认行为,将路径添加到当前include列表的末尾或前边。 SYSTEM:告诉编译器这些目标在某些平台上是系统包含目录,设置后编译器会忽略这些目录下的头文件产生的警告。dir: 被添加的目录,相对路径被解释为相对于当前源目录。

include_directories()缺点:它会影响当前目录所有的目标。例如, target A 需要库 X,target B 不需要X, 用include_directories()会导致B也加上X的路径。
因此,现代CMake不推荐使用这个方法设置目标的头文件,而是使用target_include_directories设置目录头文件。
target_include_directories用于给特定的库或可执行文件添加头文件搜索路径,比 include_directories 更精细,不会污染全局,语法如下:

target_include_directories(<target>[SYSTEM][BEFORE]<INTERFACE|PUBLIC|PRIVATE>[items1...]...)

: 目标,可执行文件或库。
<INTERFACE|PUBLIC|PRIVATE>:为了说明这三个关键字作用,假如现在正在编译一个库MyLib,它依赖头文件目录A;

  • PRIVATE:为MyLib设置私有属性后,只给自己用,链接MyLib的人不能用。
  • INTERFACE: 只给使用这个三方库的人使用,编译这个库时,不能使用指定头文件目录。
  • PUBLIC: 链接库的人和自己都能使用这个头文件。

测试代码,目录如下:

最外层cmake如下:

cmake_minimum_required(VERSION3.30)project(main VERSION1.0LANGUAGES CXX)set(CMAKE_CXX_STANDARD23)set(CMAKE_CXX_STANDARD_REQUIRED ON)# 调用子目录add_subdirectory(lib)add_executable(main app/main.cpp)target_link_libraries(main PRIVATE mathlib)

库的cmake如下:

cmake_minimum_required(VERSION3.30)project(mathlib VERSION1.0LANGUAGES CXX)set(SOURCEFILE${CMAKE_CURRENT_SOURCE_DIR}/source/my_math.cpp)message("SOURCEFILE=${SOURCEFILE}")add_library(mathlib STATIC${SOURCEFILE})# 设置公开:谁调用这个库,都会包含这个目录target_include_directories(mathlib PUBLIC${CMAKE_CURRENT_SOURCE_DIR}/include)

2.23 target_sources() 向目标添加源文件

向目标添加源文件,使用target_sources(). 语法格式:

target_sources(<target><INTERFACE|PUBLIC|PRIVATE>[items1]<INTERFACE|PUBLIC|PRIVATE>[items2])

参数:由add_executable() 和 add_library() 或 add_custom_target() 等命令创建的目标,并且不能是目标别名。
INTERFACE | PUBLIC | PRIVATE : PUBLIC既给自己用,又给别人用;PRIVATE只给自己用,INTERFACE 只给别人用。

cmake_minimum_required(VERSION3.29)project(test29)add_executable(main)# 向目标加入源文件target_sources(main PUBLIC main.c PRIVATE a.c PRIVATE b.c)#获取目标属性get_target_property(var main SOURCES)message("目标 SOURCES=${var}")# 目标 SOURCES= main.c;a.c;b.cget_target_property(var main INTERFACE_SOURCES)message("目标 INTERFACE_SOURCES=${var}")# 目标 INTERFACE_SOURCES= E:/practice_Code/cmake/29/main.c

2.24 add_compile_definitions()/target_compile_definition()添加预定义

add_compile_definitions() 为当前目录以及子目录下的所有target添加宏定义,相当于在编译时添加 -D MY_MRO=1
语法:

add_compile_definitions(<definition>...)

例如:

# 定义一个带值的宏(相当于 #define MAX_BUFFER_SIZE 1024)add_compile_definitions(MAX_BUFFER_SIZE=1024)

add_compile_definitions 影响当前目录下的所有目标,假如指向给库mathlib添加一个宏,不想给其他target添加宏,推荐使用target_compile_definitions。
target_compile_definitions语法如下:

target_compile_definitions(mathlib PRIVATEMY_LIB_INTERNAL=1# 只有编译 mathlib 内部代码时可见PUBLICMY_LIB_API=1# 编译 mathlib 和 链接 mathlib 的人都可见INTERFACEMY_LIB_USER=1# 只有链接 mathlib 的人可见)

测试:给main添加一个宏:

intmain(){#ifdef VERSION_STRMyMath math;cout<<math.add(3,4)<<endl;#endifcout<<"hello world"<<endl;return0;}

cmake文件如下:

cmake_minimum_required(VERSION3.30)project(main VERSION1.0LANGUAGES CXX)set(CMAKE_CXX_STANDARD23)set(CMAKE_CXX_STANDARD_REQUIRED ON)# 调用子目录add_subdirectory(lib)add_executable(main app/main.cpp)target_link_libraries(main PRIVATE mathlib)# 给main添加一个宏target_compile_definitions(main PRIVATEVERSION_STR=1)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/26 16:38:36

PHP大马分析:从一句话木马到功能强大的WebShell

Z-Image-ComfyUI&#xff1a;从零部署到高效文生图实战 你有没有遇到过这样的场景&#xff1f;在深夜调试一个图像生成任务时&#xff0c;输入一句“穿着汉服的少女站在樱花树下”&#xff0c;几秒钟后屏幕上跳出一张光影细腻、氛围感拉满的高清图——人物姿态自然&#xff0c;…

作者头像 李华
网站建设 2025/12/28 2:57:08

Forest项目数据库迁移至MySQL指南

Forest项目数据库迁移至MySQL指南 在开发和学习Java EE应用的过程中&#xff0c;像Forest这样的教学项目常被用作演示JPA、EJB等企业级技术的实践模板。默认情况下&#xff0c;这类项目通常使用嵌入式数据库&#xff08;如Apache Derby&#xff09;&#xff0c;因其轻量、无需…

作者头像 李华
网站建设 2025/12/27 17:15:39

汇编语言全接触-50.PE教程1 PE文件格式一览

考虑到早期写的PE教程1是自己所有教程中最糟糕的一篇&#xff0c;此番决心彻底重写一篇以飨读者。PE 的意思就是 Portable Executable&#xff08;可移植的执行体&#xff09;。它是 Win32环境自身所带的执行体文件格式。它的一些特性继承自 Unix的 Coff (common object file f…

作者头像 李华
网站建设 2025/12/28 0:57:28

SQL基础查询与模糊匹配技巧

SQL基础查询与模糊匹配技巧 在开发和管理像 VibeVoice-WEB-UI 这样的智能语音内容生成系统时&#xff0c;结构化文本的处理效率直接决定了工作流的流畅性。尤其是面对多说话人对话脚本——比如播客访谈、戏剧剧本或教学录音——如何快速准确地提取所需信息&#xff0c;成了前端…

作者头像 李华
网站建设 2025/12/27 18:18:55

【电力仿真】并行共振并行RLC电路及其特性研究附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。&#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室&#x1f34a;个人信条&#xff1a;格物致知,完整Matlab代码及仿真咨询…

作者头像 李华
网站建设 2025/12/28 8:12:33

推荐8个牛逼的SpringBoot项目

前言 最近两年左右的时间&#xff0c;我一口气肝了8个实现项目。 包含了各种业界常见的技术&#xff0c;比如&#xff1a;SpringBoot、SpringCloud、SpringCloud Alibaba、Mybatis、JPA、Redis、MongoDB、ElasticSearch、MySQL、PostgreSQL、Minio、Caffine、RocketMQ、Prometh…

作者头像 李华