cmake:设置编译选项 您所在的位置:网站首页 cmake多线程编译 cmake:设置编译选项

cmake:设置编译选项

2023-09-18 09:14| 来源: 网络整理| 查看: 265

此文为:轻松入门cmake系列教程

常用

1、 cmake debug和release设置

# default is "Debug" #set(CMAKE_BUILD_TYPE "Release") if (!CMAKE_BUILD_TYPE STREQUAL "RELEASE") add_definitions("-g") endif()

2、启用Makefile版本中的详细输出。

# set this to see the compilation commands # set(CMAKE_VERBOSE_MAKEFILE 1)

3、根据cmake的debug和release设置编译选项

IF("${CMAKE_BUILD_TYPE}" MATCHES "Debug") message(STATUS "building for: debugging") ## unfortunately these produce errors #include(CheckCXXCompilerFlag) #CHECK_CXX_COMPILER_FLAG("-Wformat-signedness" CXX_FORMAT_SIGNEDNESS) #CHECK_CXX_COMPILER_FLAG("-Werror=format-security" CXX_FORMAT_SECURITY) #CHECK_CXX_COMPILER_FLAG("-fstack-protector-all" CXX_STACK_PROTECTOR) set(CXX_FORMAT_SIGNEDNESS "-Wformat-signedness") set(CXX_FORMAT_SECURITY "-Werror=format-security") set(CXX_STACK_PROTECTOR "-fstack-protector-all") set(CXX_FLAGS_DEBUG "-O0") set(CMAKE_C_STANDARD 99) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O1 -ggdb -Wall -Wextra -DNETDATA_INTERNAL_CHECKS=1 -DNETDATA_VERIFY_LOCKS=1 ${CXX_FORMAT_SIGNEDNESS} ${CXX_FORMAT_SECURITY} ${CXX_STACK_PROTECTOR} ${CXX_FLAGS_DEBUG}") ELSE() message(STATUS "building for: release") cmake_policy(SET CMP0069 "NEW") include(CheckIPOSupported) check_ipo_supported(RESULT ipo_supported OUTPUT error) IF(${ipo_supported}) message(STATUS "link time optimization: supported") set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) ELSE() message(STATUS "link time optimization: not supported") ENDIF() ENDIF() 设置CMAKE_CXX_FLAGS # Use C++11. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions") #禁用运行时类型信息 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti") # 禁用异常机制 理论 GCC编译选项 -E:只进行预处理,不编译-S:只编译,不汇编-c:只编译、汇编,不链接-g:包含调试信息-I:指定include包含文件的搜索目录-o:输出成指定文件名 常用选项 优化选项 -O0:关闭所有优化选项-O1:第一级别优化,使用此选项可使可执行文件更小、运行更快,并不会增加太多编译时间,可以简写为-O-O2:第二级别优化,采用了几乎所有的优化技术,使用此选项会延长编译时间-O3:第三级别优化,在-O2的基础上增加了产生inline函数、使用寄存器等优化技术-Os:此选项类似于-O2,作用是优化所占用的空间,但不会进行性能优化,常用于生成最终版本 高级选项 -ggdb:在可执行文件中包含可供 GDB使用的调试信息-v:详细输出编译过程中所采用的每一个选项-C:预处理时保留注释信息-fverbose-asm:在编译成汇编语言时,把C变量的名称作为汇编语言中的注释-save-temps::自动输出预处理文件、汇编文件、对象文件,编译正常进行-fsyntax-only::只测试源文件语法是否正确,不会进行任何编译操作-ffreestanding:编译成独立程序,而非宿主程序 出错提示

当GCC在编译过程中检查出错误的话,它就会中止编译;但检测到警告时却能继续编译生成可执行程序,因为警告只是针对程序结构的诊断信息,它不能说明程序一定有错误,而是存在风险,或者可能存在错误。虽然GCC提供了非常丰富的警告,但前提是你已经启用了它们,否则它不会报告这些检测到的警告。

-Wall:开启大部分警告提示-Wextra:对所有合法但值得怀疑的表达式发出警告-w:忽略所有警告-Werror:不区分警告和错误,遇到任何警告都停止编译-Wshadow:一旦某个局部变量屏蔽了另一个局部变量,编译器就发出警告.(此警告未包含在-Wall选项中,需单独开启)-Wlong-long: 如果使用了long long 类型就发出警告.该警告是缺省项.使用-Wno-long-long选项能够防止这个警告.-Wlong-long和-Wno-long-long仅在 -pedantic之下才起作用. -Waggregate-return: 如果定义或调用了返回结构或联合的函数,编译器就发出警告(从语言角度你可以返回一个数组,然而同样会 导致警告.) -Wstrict-prototypes: 如果函数的声明或定义没有指出参数类型,编译器就发出警告.(如果函数的前向引用说明指出了参数类型,则允许后面 使用旧式风格的函数定义,而不会产生警告.) -Wmissing-prototypes 如果没有预先声明函数原形就定义了全局函数,编译器就发出警告即使函数定义自身提供了函数原形也会产生这个警告.他的目的是检查没有在头文件中声明的全局函数. 使用示例:-Wall选项

在众多的警告选项之中,最常用的就是-Wall选项。该选项能发现程序中一系列的常见错误警告,该选项用法举例如下:

命令行: $ gcc -Wall test.c -o test cmakelist.txt: add_definitions( "-W" "-Wall" "-Werror" "-Wshadow" )

该选项相当于同时使用了下列所有的选项:

unused-function:遇到仅声明过但尚未定义的静态函数时发出警告。unused-label:遇到声明过但不使用的标号的警告。unused-parameter:从未用过的函数参数的警告。unused-variable:在本地声明但从未用过的变量的警告。unused-value:仅计算但从未用过的值得警告。Format:检查对printf和scanf等函数的调用,确认各个参数类型和格式串中的一致。implicit-int:警告没有规定类型的声明。implicit-function-:在函数在未经声明就使用时给予警告。char-subscripts:警告把char类型作为数组下标。这是常见错误,程序员经常忘记在某些机器上char有符号。missing-braces:聚合初始化两边缺少大括号。Parentheses:在某些情况下如果忽略了括号,编译器就发出警告。return-type:如果函数定义了返回类型,而默认类型是int型,编译器就发出警告。同时警告那些不带返回值的 return语句,如果他们所属的函数并非void类型。sequence-point:出现可疑的代码元素时,发出报警。Switch:如果某条switch语句的参数属于枚举类型,但是没有对应的case语句使用枚举元素,编译器就发出警告(在switch语句中使用default分支能够防止这个警告)。超出枚举范围的case语句同样会导致这个警告。strict-aliasing:对变量别名进行最严格的检查。unknown-pragmas:使用了不允许的#pragma。Uninitialized:在初始化之前就使用自动变量。

需要注意的是,各警告选项既然能使之生效,当然也能使之关闭。比如假设我们想要使用-Wall来启用个选项,同时又要关闭unused警告,利益通过下面的命令来达到目的:

gcc -Wall -Wno-unused test.c -o test gcc -Wall详解 使用示例:-Wpointer-arith 任何语句如果依赖于函数类型的大小(size)或者void类型的大小,编译器就发出警告.GNU C为了 便于计算void *指针和函数指针,就把这些类型的大小定义为1.在C++中,当算术运算涉及"NULL"时也要发出警告. #include int main() { void *test = NULL; int value_int[] = {12, 34, 56, 67, 27}; char value_char[] = {'H', 'e', 'I', 'I', 'O'}; test = (void *) value_char; printf("%c\n", *((char*)(test + 1))); return 0; }

在这里插入图片描述

-Waggregate-return -Waggregate-return: 当返回结构、联合或数组时给出警告

引发警告的小例子:

class foo{}; foo f(void){return foo{};} int main(){} $ g ++ -std = c ++ 0x -Waggregate-return -o main main.cpp main.cpp:在函数'foo f()'中: main.cpp:2:5:warning:函数返回一个聚合[-Waggregate-返回]

另一个不引发警告的小例子:

#include std::string f(void){return "test";} int main(){}

使用-Waggregate-return可以获得什么好处? 为什么有人想要对此发出警告? 另外,std :: string不是一个类吗? - 为什么我不警告第二个例子中的’返回聚合’?

回答: 主要有两种可能的解释:

1)警告用户返回聚合对象使他意识到如果返回聚合对象(在堆栈上分配),堆栈可能会溢出.2)显然,一些旧的C编译器不支持返回aggrregates(你必须返回一个指针).

讨论请参见这里

-Wmissing-prototypes

这个选项仅适用于C编译,如果是C++,会警告:

在这里插入图片描述

讨论请参见这里

语言标准 -ansi:ANSI标准-std=c99:C99标准-std=gnu89:ISO/IEC 9899:1990 以及GNU扩充-std=gnu99:ISO/IEC 9899:1999 以及GNU扩充-trigraphs:支持ISO C三字符组 其他 -D_REENTRANT(很重要)

在一个多线程程序中,默认情况下,只有一个errno变量供所有的线程共享。在一个线程准备获取刚才的错误代码时,该变量很容易被另一个线程中的函数调用所改变。类似的问题还存在于fputs之类的函数中,这些函数通常用一个单独的全局性区域来缓存输出数据

为解决这个问题,需要使用可重入的例程。可重入代码可以被多次调用而仍然工作正常。编写的多线程程序,通过定义宏_REENTRANT来告诉编译器我们需要可重入功能,这个宏的定义必须出现于程序中的任何#include语句之前。

_REENTRANT为我们做三件事情,并且做的非常优雅:

它会对部分函数重新定义它们的可安全重入的版本,这些函数名字一般不会发生改变,只是会在函数名后面添加_r字符串,如函数名gethostbyname变成gethostbyname_r。stdio.h中原来以宏的形式实现的一些函数将变成可安全重入的函数在error.h中定义的变量error现在将成为一个函数调用,它能够以一种安全的多线程方式来获取真正的errno的值 设置编译器标志 为每个目标设置编译标志

CMake支持以多种不同方式设置编译标志:

使用target_compile_definitions()函数使用CMAKE_C_FLAGS和CMAKE_CXX_FLAGS变量。 target_compile_options target_compile_options( [BEFORE] [items1...] [ [items2...] ...])

编译选项可以添加三个级别的可见性: INTERFACE 、 PUBLIC 和 PRIVATE 。可见性的含义如下:

PRIVATE,编译选项会应用于给定的目标,不会传递给与目标相关的目标。比如,即使exe将链接到A库,exe也不会继承A目标上设置的编译器选项。INTERFACE,给定的编译选项将只应用于指定目标,并传递给与目标相关的目标。PUBLIC,编译选项将应用于指定目标和使用它的目标。

可以为库、可执行文件设置编译选项。

target_compile_options(lib PRIVATE -O3) #-O3:编译器优化级别编译库 。 check_cxx_compiler_flag check_cxx_compiler_flag( )

检查C++编译器是否支持某个/某些flag标志,检测结果存放在var变量中。

统一设置所有目标的编译标志

使用 -D CLI标志直接修改CMAKE__FLAGS_变量,比如:

SET(CMAKE_CXX_FLAGS_RELEASE "-g -DNDEBUG -O3") 实验 实验一

编写代码

工程结构

在这里插入图片描述

CMakeLists.txt内容: cmake_minimum_required(VERSION 3.5) # Set a default C++ compile flag set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DEX2" CACHE STRING "Set C++ Compiler Flags" FORCE) # Set the project name project (compile_flags) # Add an executable add_executable(${PROJECT_NAME} main.cpp) target_compile_definitions(${PROJECT_NAME} PRIVATE EX3 ) main.cpp #include int main(int argc, char *argv[]) { std::cout


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有