本次将使用CMakeLists来设置编译器选项。一般来说,这些命令都是可以在编译过程中,使用命令行直接敲进去的,都是编译时加入的选项/参数。以下的这些-fPIC、-Wall等编译器选项,实质上与g++/gcc编译时的-o、-i、-g等参数并没有太大区别。(当前这么理解不知道是否有误2022-02-18)。
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(recipe-08 LANGUAGES CXX)
message("C++ compiler flags: ${CMAKE_CXX_FLAGS}")
list(APPEND flags "-fPIC" "-Wall")
if(NOT WIN32)
list(APPEND flags "-Wextra" "-Wpedantic")
endif()
add_library(geometry
STATIC
geometry_circle.cpp
geometry_circle.hpp
geometry_polygon.cpp
geometry_polygon.hpp
geometry_rhombus.cpp
geometry_rhombus.hpp
geometry_square.cpp
geometry_square.hpp
)
target_compile_options(geometry
PRIVATE
${flags}
)//为库文件的编译添加选项:-Wextra -Wpedantic -fPIC -Wall
add_executable(compute-areas compute-areas.cpp)
target_compile_options(compute-areas
PRIVATE
"-fPIC"
)//为可执行文件的编译添加选项:-fPIC
target_link_libraries(compute-areas geometry)
需要注意的是以上target_compile_options()的参数PRIVATE,这是一个可见性的标记,除了PRIVATE外还有PUBLIC和INTERFACE标记,具体的标记含义如下:
但是以上的 INTERFACE 和 PUBLIC 的差异还是没搞明白
我们进行了如上的设置,但如何验证我们的设置是否起效了呢?于是可以使用如下的编译指令,在编译过程的输出中进行实时的查看:本例中,设置VERBOSE=1
$ mkdir -p build
$ cd build
$ cmake ..
$ cmake --build . -- VERBOSE=1
除了以上的方式对编译选项添加一些设置/标志,还可以通过在命令行中使用类似配置option的方式来对其进行设置。同样是使用-D命令,在命令行中对CMAKE_CXX_FLAGS进行设置。这种方式将对所有的对象添加所设置的编译标志。
$ mkdir -p build
$ cd build
$ cmake -D CMAKE_CXX_FLAGS="-fno-exceptions -fno-rtti" ..
$ cmake --build . -- VERBOSE=1
使用如上方法,为所有对象添加-fno-exceptions 以及 -fno-rtti编译标志,在build命令执行完后,可以在命令行中看到对应的输出结果得以验证。
但是以上的方法是一种全局的设置,在实际工程中,我们还是推荐为每个目标设置编译器标志,使用target_compile_options()设置每一个对象,不仅允许对编译选项进行细粒度控制,而且还可以更好地与CMake的更高级特性进行集成(这部分我们放在之后的章节进行介绍)。
CMake的一大优点在于其可以跨平台为我们的工程提供构建、编译的方案。所以对不同厂商提供的编译器,不一定相互理解各自的标志,故这里我们提供如下方法解决项目跨平台编译、对于不同平台给出不同标志的方案。
以下这种方法对CMake内置变量CMAKE_
if(CMAKE_CXX_COMPILER_ID MATCHES GNU)//对于GCC/G++我们给出一套编译选项的标志设置方案
list(APPEND CMAKE_CXX_FLAGS "-fno-rtti" "-fno-exceptions")
list(APPEND CMAKE_CXX_FLAGS_DEBUG "-Wsuggest-final-types" "-Wsuggest-final-methods" "-Wsuggest-override")
list(APPEND CMAKE_CXX_FLAGS_RELEASE "-O3" "-Wno-unused")
endif()//对于不同的版本:Debug/Release版本,我们为其添加不同的标志
if(CMAKE_CXX_COMPILER_ID MATCHES Clang)//对于Clang我们给出一套编译选项的标志设置方案
list(APPEND CMAKE_CXX_FLAGS "-fno-rtti" "-fno-exceptions" "-Qunused-arguments" "-fcolor-diagnostics")
list(APPEND CMAKE_CXX_FLAGS_DEBUG "-Wdocumentation")
list(APPEND CMAKE_CXX_FLAGS_RELEASE "-O3" "-Wno-unused")
endif()//Clang编译器不一定支持GCC/G++中的一些标志,但是我们可以发现其中的确有些标志是重复/通用的
以下还提供了更细粒度的设置/书写方法,该方法中,不直接使用CMake的内置变量,而是直接自定义一个特定的标志列表:
set(COMPILER_FLAGS)
set(COMPILER_FLAGS_DEBUG)
set(COMPILER_FLAGS_RELEASE)
if(CMAKE_CXX_COMPILER_ID MATCHES GNU)
list(APPEND CXX_FLAGS "-fno-rtti" "-fno-exceptions")
list(APPEND CXX_FLAGS_DEBUG "-Wsuggest-final-types" "-Wsuggest-final-methods" "-Wsuggest-override")
list(APPEND CXX_FLAGS_RELEASE "-O3" "-Wno-unused")
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES Clang)
list(APPEND CXX_FLAGS "-fno-rtti" "-fno-exceptions" "-Qunused-arguments" "-fcolor-diagnostics")
list(APPEND CXX_FLAGS_DEBUG "-Wdocumentation")
list(APPEND CXX_FLAGS_RELEASE "-O3" "-Wno-unused")
endif()
稍后,使用生成器表达式来设置编译器标志的基础上,为每个配置和每个目标生成构建系统:
target_compile_option(compute-areas
PRIVATE
${CXX_FLAGS}
"$<$:${CXX_FLAGS_DEBUG}>"
"$<$:${CXX_FLAGS_RELEASE}>"
)
??勘误:以上set的三个列表好像都没有用到?!这里是不是有错误–待定2022-02-19