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
赋值来实现。
如果对于Debug
,Release
有不同的编译选项,可分别通过CMAKE_CXX_FLAGS_DEBUG
、CMAKE_CXX_FLAGS_RELEASE
来设置。
对于Debug
模式,编译选项实际使用的值是CMAKE_CXX_FLAGS
和CMAKE_CXX_FLAGS_DEBUG
的值的组合(不管CMAKE_CXX_FLAGS_RELEASE
设置什么值都不会被加入到编译选项中)。
对于Release
模式,编译选项实际使用的值是CMAKE_CXX_FLAGS
和CMAKE_CXX_FLAGS_RELEASE
的值的组合(不管CMAKE_CXX_FLAGS_DEBUG
设置什么值都不会被加入到编译选项中)。
所以编译器实际使用的编译选项不只是来源于CMAKE_CXX_FLAGS
,而是来自CMAKE_CXX_FLAGS
与其它变量(如CMAKE_CXX_FLAGS_DEBUG
、CMAKE_CXX_FLAGS_RELEASE
、CMAKE_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_FLAGS
和CMAKE_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_FLAGS
和CMAKE_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