CMakeLists.txt中如何添加编译选项?

news/2024/5/9 13:07:26

1. 引子

编译器有多种可供选择,如g++c++clang++等,如下以c++作为示例。

2. 使用CMAKE_CXX_FLAGS添加编译选项

Makefile中可能用类似如下的指令来添加编译选项:
/usr/bin/c++ -Wall -Wextra -Wno-sign-compare -Wno-unused-variable -Wno-unused-parameter -O2

那么-Wall -Wextra -Wno-sign-compare -Wno-unused-variable -Wno-unused-parameter -O2这些在CMakeLists.txt中如何添加呢?
方法是通过给变量CMAKE_CXX_FLAGS赋值来实现。

如果对于DebugRelease有不同的编译选项,可分别通过CMAKE_CXX_FLAGS_DEBUGCMAKE_CXX_FLAGS_RELEASE来设置。

对于Debug模式,编译选项实际使用的值是CMAKE_CXX_FLAGSCMAKE_CXX_FLAGS_DEBUG的值的组合(不管CMAKE_CXX_FLAGS_RELEASE设置什么值都不会被加入到编译选项中)。
对于Release模式,编译选项实际使用的值是CMAKE_CXX_FLAGSCMAKE_CXX_FLAGS_RELEASE的值的组合(不管CMAKE_CXX_FLAGS_DEBUG设置什么值都不会被加入到编译选项中)。

所以编译器实际使用的编译选项不只是来源于CMAKE_CXX_FLAGS,而是来自CMAKE_CXX_FLAGS与其它变量(如CMAKE_CXX_FLAGS_DEBUGCMAKE_CXX_FLAGS_RELEASECMAKE_CXX_STANDARD 等)的组合。

例如上面的编译选项可在CMakeLists.txt中添加:
set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-sign-compare -Wno-unused-variable -Wno-unused-parameter") 实现。

3. 通过CMAKE_CXX_FLAGS添加编译选项的示例

工程目录如下:
在这里插入图片描述
文件一,CMakeLists.txt

if(" ${CMAKE_SOURCE_DIR}" STREQUAL " ${CMAKE_BINARY_DIR}")message(FATAL_ERROR "
FATAL: In-source builds are not allowed.You should create a separate directory for build files.
")
endif()cmake_minimum_required(VERSION 3.4.1)set(CMAKE_VERBOSE_MAKEFILE ON)  # !!!楔子,此句对于在make时展示实际使用的编译选项很重要!!!set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)project(learnCMake VERSION 1.0.0.0 DESCRIPTION "setting cxx flags" HOMEPAGE_URL "https://blog.csdn.net/liugan528" LANGUAGES C CXX)#set (CMAKE_C_COMPILER "aarch64-linux-gnu-gcc")
#set (CMAKE_CXX_COMPILER "aarch64-linux-gnu-g++")message(STATUS "000--->${CMAKE_BUILD_TYPE}<---000")
if(NOT CMAKE_BUILD_TYPE)set(CMAKE_BUILD_TYPE Release)
endif()
set(CMAKE_CXX_FLAGS_RELEASE "-O2")
set(CMAKE_CXX_FLAGS_DEBUG "-D NDEBUG -Og -g -pg")
set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-sign-compare -Wno-unused-variable -Wno-unused-parameter")
message(STATUS "111--->${CMAKE_BUILD_TYPE}<---111")
message(STATUS "222--->${CMAKE_CXX_FLAGS}<---222")add_executable(runMain main.cpp)

文件二,main.cpp

#include <iostream>int main(){std::cout << "Hello CMake World!" << std::endl;
}

进入build之后执行cmake ..结果如下:

root@tegra-ubuntu:/mnt/learnCMake/build# cmake ..
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- 000---><---000
-- 111--->Release<---111
-- 222--->-Wall -Wextra -Wno-sign-compare -Wno-unused-variable -Wno-unused-parameter<---222
-- Configuring done
-- Generating done
-- Build files have been written to: /mnt/learnCMake/build

再执行make进行编译:

root@tegra-ubuntu:/mnt/learnCMake/build# make
Scanning dependencies of target runMain
[ 50%] Building CXX object CMakeFiles/runMain.dir/main.cpp.o
[100%] Linking CXX executable runMain
[100%] Built target runMain

执行可执行程序:

root@tegra-ubuntu:/mnt/learnCMake/build# ./runMain 
Hello CMake World!

4. 如何直观地看到使用CMAKE_CXX_FLAGS添加的编译选项被编译器使用了呢?

4.1 Release模式,执行cmake时不加参数,或加上参数-DCMAKE_BUILD_TYPE=Release(默认)。

通过在CMakeLists.txt中添加语句set(CMAKE_VERBOSE_MAKEFILE ON) ,然后在make时加上参数VERBOSE=1即可看到详细的编译过程,其中就会展示实际的编译选项。
章节3的示例已经加了set(CMAKE_VERBOSE_MAKEFILE ON) ,只是make的时候没加参数VERBOSE=1,加上VERBOSE=1之后编译的过程如下:

root@tegra-ubuntu:/mnt/learnCMake/build# cmake ..
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- 000---><---000
-- 111--->Release<---111
-- 222--->-Wall -Wextra -Wno-sign-compare -Wno-unused-variable -Wno-unused-parameter<---222
-- Configuring done
-- Generating done
-- Build files have been written to: /mnt/learnCMake/build

make加上VERBOSE=1进行编译,可展示详细的编译过程(同时会有编译选项的输出):

root@tegra-ubuntu:/mnt/learnCMake/build# make VERBOSE=1
/usr/bin/cmake -S/mnt/learnCMake -B/mnt/learnCMake/build --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /mnt/learnCMake/build/CMakeFiles /mnt/learnCMake/build/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/mnt/learnCMake/build'
make -f CMakeFiles/runMain.dir/build.make CMakeFiles/runMain.dir/depend
make[2]: Entering directory '/mnt/learnCMake/build'
cd /mnt/learnCMake/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /mnt/learnCMake /mnt/learnCMake /mnt/learnCMake/build /mnt/learnCMake/build /mnt/learnCMake/build/CMakeFiles/runMain.dir/DependInfo.cmake --color=
Dependee "/mnt/learnCMake/build/CMakeFiles/runMain.dir/DependInfo.cmake" is newer than depender "/mnt/learnCMake/build/CMakeFiles/runMain.dir/depend.internal".
Dependee "/mnt/learnCMake/build/CMakeFiles/CMakeDirectoryInformation.cmake" is newer than depender "/mnt/learnCMake/build/CMakeFiles/runMain.dir/depend.internal".
Scanning dependencies of target runMain
make[2]: Leaving directory '/mnt/learnCMake/build'
make -f CMakeFiles/runMain.dir/build.make CMakeFiles/runMain.dir/build
make[2]: Entering directory '/mnt/learnCMake/build'
[ 50%] Building CXX object CMakeFiles/runMain.dir/main.cpp.o
/usr/bin/c++    -Wall -Wextra -Wno-sign-compare -Wno-unused-variable -Wno-unused-parameter -O2   -std=gnu++2a -o CMakeFiles/runMain.dir/main.cpp.o -c /mnt/learnCMake/main.cpp
[100%] Linking CXX executable runMain
/usr/bin/cmake -E cmake_link_script CMakeFiles/runMain.dir/link.txt --verbose=1
/usr/bin/c++  -Wall -Wextra -Wno-sign-compare -Wno-unused-variable -Wno-unused-parameter -O2   CMakeFiles/runMain.dir/main.cpp.o  -o runMain 
make[2]: Leaving directory '/mnt/learnCMake/build'
[100%] Built target runMain
make[1]: Leaving directory '/mnt/learnCMake/build'
/usr/bin/cmake -E cmake_progress_start /mnt/learnCMake/build/CMakeFiles 0

由上可看到实际使用的编译选项是:/usr/bin/c++ -Wall -Wextra -Wno-sign-compare -Wno-unused-variable -Wno-unused-parameter -O2 -std=gnu++2a,确实是CMAKE_CXX_FLAGSCMAKE_CXX_FLAGS_RELEASE的值的组合的结果。

执行可执行程序:

root@tegra-ubuntu:/mnt/learnCMake/build# ./runMain 
Hello CMake World!

4.2 Debug模式,执行cmake时加上参数-DCMAKE_BUILD_TYPE=Debug

root@tegra-ubuntu:/mnt/learnCMake/build# cmake -DCMAKE_BUILD_TYPE=Debug ..
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- 000--->Debug<---000
-- 111--->Debug<---111
-- 222--->-Wall -Wextra -Wno-sign-compare -Wno-unused-variable -Wno-unused-parameter<---222
-- Configuring done
-- Generating done
-- Build files have been written to: /mnt/learnCMake/build

make加上VERBOSE=1进行编译,可展示详细的编译过程(同时会有编译选项的输出):

root@tegra-ubuntu:/mnt/learnCMake/build# make VERBOSE=1
/usr/bin/cmake -S/mnt/learnCMake -B/mnt/learnCMake/build --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /mnt/learnCMake/build/CMakeFiles /mnt/learnCMake/build/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/mnt/learnCMake/build'
make -f CMakeFiles/runMain.dir/build.make CMakeFiles/runMain.dir/depend
make[2]: Entering directory '/mnt/learnCMake/build'
cd /mnt/learnCMake/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /mnt/learnCMake /mnt/learnCMake /mnt/learnCMake/build /mnt/learnCMake/build /mnt/learnCMake/build/CMakeFiles/runMain.dir/DependInfo.cmake --color=
Dependee "/mnt/learnCMake/build/CMakeFiles/runMain.dir/DependInfo.cmake" is newer than depender "/mnt/learnCMake/build/CMakeFiles/runMain.dir/depend.internal".
Dependee "/mnt/learnCMake/build/CMakeFiles/CMakeDirectoryInformation.cmake" is newer than depender "/mnt/learnCMake/build/CMakeFiles/runMain.dir/depend.internal".
Scanning dependencies of target runMain
make[2]: Leaving directory '/mnt/learnCMake/build'
make -f CMakeFiles/runMain.dir/build.make CMakeFiles/runMain.dir/build
make[2]: Entering directory '/mnt/learnCMake/build'
[ 50%] Building CXX object CMakeFiles/runMain.dir/main.cpp.o
/usr/bin/c++    -Wall -Wextra -Wno-sign-compare -Wno-unused-variable -Wno-unused-parameter -D NDEBUG -Og -g -pg   -std=gnu++2a -o CMakeFiles/runMain.dir/main.cpp.o -c /mnt/learnCMake/main.cpp
[100%] Linking CXX executable runMain
/usr/bin/cmake -E cmake_link_script CMakeFiles/runMain.dir/link.txt --verbose=1
/usr/bin/c++  -Wall -Wextra -Wno-sign-compare -Wno-unused-variable -Wno-unused-parameter -D NDEBUG -Og -g -pg   CMakeFiles/runMain.dir/main.cpp.o  -o runMain 
make[2]: Leaving directory '/mnt/learnCMake/build'
[100%] Built target runMain
make[1]: Leaving directory '/mnt/learnCMake/build'
/usr/bin/cmake -E cmake_progress_start /mnt/learnCMake/build/CMakeFiles 0

由上可看到实际使用的编译选项是:/usr/bin/c++ -Wall -Wextra -Wno-sign-compare -Wno-unused-variable -Wno-unused-parameter -D NDEBUG -Og -g -pg -std=gnu++2a,确实是CMAKE_CXX_FLAGSCMAKE_CXX_FLAGS_DEBUG的值组合的结果。

执行可执行程序:

root@tegra-ubuntu:/mnt/learnCMake/build# ./runMain 
Hello CMake World!

Reference

CMAKE__FLAGS
CMake编译选项CMAKE_CXX_FLAGS详解
How to use gprof with cmake


http://www.mrgr.cn/p/86283152

相关文章

深入理解Python协程:从基础到实战

title: 深入理解Python协程:从基础到实战 date: 2024/4/27 16:48:43 updated: 2024/4/27 16:48:43 categories:后端开发tags:协程 异步IO 并发编程 Python aiohttp asyncio 网络爬虫第1章:协程基础 1.1 协程概念介绍 协程(Coroutines)是一种特殊的软件构造,它允许程序在执…

leetCode60. 排列序列

leetCode60. 排列序列 方法一:语法版&#xff0c;面试官不认可的方法&#xff1a;next_permutation函数 // 方法一&#xff1a;使用next_permutation函数&#xff0c;将某容器设置为当前按照字典序 // 的下一个全排列的内容 class Solution { public:string getPermutation(in…

四数之和 ---- 双指针

题目链接 题目: 分析: 我们已经知道三数之和如何求取, 并去重了 三数之和 那么四数之和同理, 需要固定两个数a和b 然后用"双指针算法" , 只要两指针之和等于target-a-b即可同样对于四个数都要进行去重 代码: class Solution {public List<List<Integer>…

Vue入门到关门之前端引入

一、前端发展历史 1、什么是前端&#xff1f; 前端&#xff1a;针对浏览器的开发&#xff0c;代码在浏览器运行后端&#xff1a;针对服务器的开发&#xff0c;代码在服务器运行 2、前后端不分的时代 互联网发展的早期&#xff0c;前后端开发是一体的&#xff0c;前端代码是…

Git 使用教程(新手学习)

Git 是一种分布式版本控制系统,用于管理软件项目的源代码。它是由 Linux 之父 Linus Torvalds 开发的,并已经成为了现代软件开发领域中最流行的版本控制系统之一。 使用 Git 可以追踪代码的历史修改记录,方便团队协作、代码共享和代码重构。Git 的基本工作流程如下: 在开始…

jwt的思路

我们通常在项目中使用登录接口的时候,会利用jwt的token实现一个对其他接口的一个请求头这层的一个验证,那么如何去应用呢,正常来讲我们需要写出两个功能 1.jwt基本的加密和解密 2.jwt的一个拦截器,检验token请求头使用依赖 jdk1.8仅需<dependency><groupId>io.json…

一道编程题引发的C中关于数组、指针的思考

7-163 谷歌的招聘由一道编程题引发的C中关于数组、指针的思考先来看三种数组定义方式 #include <stdio.h> #include <stdlib.h>int main(){//方式1int array_1[4] = {1};//方式2,变长数组int n2;scanf("%d",&n2);int array_2[n2]; //使用变长数组pri…

【003_音频开发_基础篇_Linux进程通信(20种你了解几种?)】

003_音频开发_基础篇_Linux进程通信&#xff08;20种你了解几种&#xff1f;) 文章目录 003_音频开发_基础篇_Linux进程通信&#xff08;20种你了解几种&#xff1f;)创作背景Linux 进程通信类型fork() 函数fork() 输出 2 次fork() 输出 8 次fork() 返回值fork() 创建子进程 方…

力扣-498. 对角线遍历

1.题目 题目地址(498. 对角线遍历 - 力扣(LeetCode)) https://leetcode.cn/problems/diagonal-traverse/ 题目描述 给你一个大小为 m x n 的矩阵 mat ,请以对角线遍历的顺序,用一个数组返回这个矩阵中的所有元素。示例 1:输入:mat = [[1,2,3],[4,5,6],[7,8,9]] 输出:[1,…

在控制台实现贪吃蛇

在控制台实现贪吃蛇 前备知识Win32APICOORD这个结构体的声明如下&#xff1a;GetStdHandle 函数GetConsoleCursorInfo 函数SetConsoleCursorInfo 函数 SetConsoleCursorPosition 函数getAsyncKeyState 函数 控制台窗口的大小以及字符打印介绍控制台中的坐标宽字符及本地化介绍s…

MySQL第一次作业

解压完安装包 以管理员进入命令行 初始化并记住初始随机密码 创建服务名称 启动mysql 使用随机密码登录 修改密码 退出并重登服务器 MySQL创建数据库和表 创建数据库 创建表 1.进入数据库 创建表 向表中插入数据

启动 UE4编辑器报 加载 Plugin 失败

启动 UE4编辑器报 加载 Plugin 失败&#xff0c;报如下错误&#xff1a; Plugin ‘SteamVR’ failer to load because module ‘SteamVR’ could not be found. Please ensure the plugin is properly installed, otherwise consider disabling the plugin for this project. …

[ARC176F] Colorful Star

数数My Blogs [ARC176F] Colorful Star 感觉很考验想象力和计数基本功 QWQ。 首先考虑给定了局面之后如何进行判定。考虑把覆盖的过程倒着做:如果 \(i\) 旁边有和它颜色相同的棋子,那它就可以变成任意的颜色,然后要求最终能不能 \(n\) 种颜色都只剩一种。 然后这个还是不太本…

LayuiMini使用时候初始化模板修改(下载源码)

忘记加了 下载 地址 &#xff1a; layui-mini: layuimini&#xff0c;后台admin前端模板&#xff0c;基于 layui 编写的最简洁、易用的后台框架模板。只需提供一个接口就直接初始化整个框架&#xff0c;无需复杂操作。 LayuiMini使用时候初始化模板官网给的是&#xff1a; layu…

IIS中搭建.Net Core项目,步骤详解

一、准备服务器 1&#xff09;安装IIS 这个比较简单&#xff0c;百度一下就行 2&#xff09;安装 .NET Core 运行时 下载地址&#xff1a;下载 .NET(Linux、macOS 和 Windows) 因为我是本地开发&#xff0c;所以我下载的是SDK 安装成功之后显示如下&#xff1a; 检查是否安装…

WPF Prism

WPF编程-Prism世有伯乐,然后有千里马。千里马常有,而伯乐不常有。一、背景 Winform和WPF1. WinForms和WPF技术架构:WinForms是基于传统的窗体和控件的技术,使用的是类似于VB6时代的设计理念。 WPF是基于XAML(可扩展应用程序标记语言)的技术,允许更灵活、高度可定制化的用…

NIO之ByteBuffer

NIO中的ByteBuffer是缓冲区&#xff0c;其中有几个比较重要的属性capacity&#xff0c;position和limit。 capacity&#xff1a; 其中&#xff0c;capacity是缓冲区的容量大小&#xff0c;在分配内存空间后不会改变。 limit&#xff1a; limit是限制位置&#xff0c;在读写模…

SpringBoot集成minio前后端联调

基本配置 初始化项目 新建一个 SpringBoot 项目,集成 lombok mybatis-plus minio hutool-core(可有可无)。 新建一个数据表 attachement,用于存储文件上传后在 minio 中的位置。 drop table if exists attachment; create table attachment (id int auto_inc…