本文使用的相关软件环境信息如下:
软件名称 | 软件版本 |
---|---|
Linux操作系统 | Ubuntu 22.04 LTS(X64) |
cmake | 3.22.1 |
g++ | 11.4.0 |
-
target_compile_options
命令格式:
target_compile_options(<target> [BEFORE] <INTERFACE|PUBLIC|PRIVATE> [items1...] [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
该命令添加编译选项到编译目标中,与add_compile_options不同的是,target_compile_options针对构建的目标添加编译选项,而add_compile_options是针对源文件添加预编译选项(实际上也隐含对当前构建目标添加编译选项)。
因此,target_compile_options要求构建目标已经存在,也就是被add_executable()或add_library()等函数创建出来。此外,target_compile_options还要求对每一个编译选项指定范围,范围有三个选项:PUBLIC、PRIVATE和INTERFACE。通过PUBLIC和PRIVATE范围限定的预编译选项会被添加到构建目标的COMPILE_OPTIONS属性中,通过PUBLIC和INTERFACE范围限定的预编译选项会被添加到构建目标的INTERFACE_COMPILE_OPTIONS属性中。总结起来就是PUBLIC既给自己用,也给别人用;PRIVATE只给自己用;INTERFACE只给别人用。
当多个构建目标在一起链接的时,最终的可执行文件会将各个构建目标的INTERFACE_COMPILE_OPTIONS属性继承过来。
总体来说,target_compile_options与add_compile_options的关系,和add_compile_definitions与target_compile_definitions的关系类似。下面通过一个例子来演示一下:
1、构建一个test库,对test使用PUBLIC、PRIVATE和INTERFACE三个编译选项,分别对应编译选项-Wunused-variable(未使用的变量)、-Wreturn-type(函数缺少返回值)、-Wuninitialized(变量使用前未初始化);
2、构建一个main可执行文件,对main使用PRIVATE的编译选项-Wunused-parameter(从未使用过的函数参数);
3、对test.cpp和main.cpp都模拟未使用的变量、函数缺少返回值、变量使用前未初始化、从未使用过的函数参数这4种情况。
CMakeLists.txt文件内容:
CMAKE_MINIMUM_REQUIRED(VERSION 3.22) PROJECT(compile_options_test) ADD_LIBRARY(test test.cpp) TARGET_COMPILE_OPTIONS(test PUBLIC -Wunused-variable PRIVATE -Wreturn-type INTERFACE -Wuninitialized) ADD_EXECUTABLE(main main.cpp) TARGET_COMPILE_OPTIONS(main PRIVATE -Wunused-parameter) TARGET_LINK_LIBRARIES(main test)
test.h文件内容
#ifndef __TEST_TT__ #define __TEST_TT__ int test(int para); #endif
test.cpp文件内容:
#include "test.h" int test(int para/* 未使用的函数参数 */) { int a = 5; // 未使用的变量 int i; // 未初始化的变量 if (i == 0) { } // 函数缺少返回值 }
main.cpp文件内容:
#include "test.h" int main(int argc, char** argv /* 未使用的函数参数 */) { const char* not_use_var = "Hello world!"; // 未使用的变量 int i; // 未初始化的变量 test(i); //return 0; // 函数缺少返回值 }
运行
cmake .
和make VERBOSE=1
,关键信息输出如下:…… [ 25%] Building CXX object CMakeFiles/test.dir/test.cpp.o /usr/bin/c++ -Wunused-variable -Wreturn-type -MD -MT CMakeFiles/test.dir/test.cpp.o -MF CMakeFiles/test.dir/test.cpp.o.d -o CMakeFiles/test.dir/test.cpp.o -c /XXX/test.cpp /XXX/test.cpp: In function ‘int test(int)’: /XXX/test.cpp:5:9: warning: unused variable ‘a’ [-Wunused-variable] 5 | int a = 5; // 未使用的变量 | ^ /XXX/test.cpp:11:1: warning: no return statement in function returning non-void [-Wreturn-type] 11 | } | ^ [ 50%] Linking CXX static library libtest.a …… [ 75%] Building CXX object CMakeFiles/main.dir/main.cpp.o /usr/bin/c++ -Wunused-parameter -Wunused-variable -Wuninitialized -MD -MT CMakeFiles/main.dir/main.cpp.o -MF CMakeFiles/main.dir/main.cpp.o.d -o CMakeFiles/main.dir/main.cpp.o -c /XXX/main.cpp /XXX/main.cpp: In function ‘int main(int, char**)’: /XXX/main.cpp:5:17: warning: unused variable ‘not_use_var’ [-Wunused-variable] 5 | const char* not_use_var = "Hello world!"; // 未使用的变量 | ^~~~~~~~~~~ /XXX/main.cpp:3:14: warning: unused parameter ‘argc’ [-Wunused-parameter] 3 | int main(int argc, char** argv /* 未使用的函数参数 */) | ~~~~^~~~ /XXX/main.cpp:3:27: warning: unused parameter ‘argv’ [-Wunused-parameter] 3 | int main(int argc, char** argv /* 未使用的函数参数 */) | ~~~~~~~^~~~ /XXX/main.cpp:7:9: warning: ‘i’ is used uninitialized [-Wuninitialized] 7 | test(i); | ~~~~^~~ [100%] Linking CXX executable main
可以看到,对于test库,其PUBLIC和PRIVATE编译选项生效,2种告警提示;对于main可执行文件,继承了test库的PUBLIC和INTERFACE编译选项,加上自身的PRIVATE编译选项,3种告警提示。
网友评论