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

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

bash 复制代码
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

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

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

bash 复制代码
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进行编译:

bash 复制代码
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

执行可执行程序:

bash 复制代码
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之后编译的过程如下:

bash 复制代码
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进行编译,可展示详细的编译过程(同时会有编译选项的输出):

bash 复制代码
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的值的组合的结果。

执行可执行程序:

bash 复制代码
root@tegra-ubuntu:/mnt/learnCMake/build# ./runMain 
Hello CMake World!

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

bash 复制代码
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进行编译,可展示详细的编译过程(同时会有编译选项的输出):

bash 复制代码
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的值组合的结果。

执行可执行程序:

bash 复制代码
root@tegra-ubuntu:/mnt/learnCMake/build# ./runMain 
Hello CMake World!

Reference

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

相关推荐
flysnow0103 个月前
Linux CMakeLists编写之静态库
linux·cmake·cmakelists.txt
软件架构师-叶秋4 个月前
esp32开发中CMakeLists.txt文件在编译时添加打印信息
esp32·打印·cmakelists.txt
geniusChinaHN9 个月前
ros2+rviz2示例代码--cmakelists.txt与package.xml备份
xml·ros2·cmakelists.txt·packages.xml
编码熊(Coding-Bear)1 年前
C/C++跨平台构建工具CMake-----在C++源码中读取CMakeLists.txt配置文件中的内容
c++·cmakelists.txt·cmake构建
编码熊(Coding-Bear)1 年前
C/C++跨平台构建工具CMake入门
c++·cmake·构建工具·cmakelists.txt
寅恪光潜1 年前
ROS通信机制之话题(Topics)的发布与订阅以及自定义消息的实现
rostopic·rqt_graph·rospy.publisher·subscriber·catkin_make·package.xml·cmakelists.txt