未分类选项

  • -o outfile: 指定编译的输出文件名称,缺省时默认为 a.out
  • -std=c++11: 指定使用的 c++标准

优化相关

编译器的优化选项有 4 个级别

  • —O0: 默认情形,不进行优化(大写字母 O 后接数字 0)
  • -O1 -O: 较低的优化级别,编译器会尝试减少空间大小和优化程序的执行时间,但不执行需要消耗大量编译时间的优化
  • -O2: 较高的优化级别,牺牲更多编译时间来提高程序的性能
  • -O3: 最高的优化级别,宁愿牺牲空间来提升程序的执行速度
  • -Og: 主要使用-O1优化, 除了那些影响调试的部分
  • ​-Os: 侧重于优化文件的体积

注意:

  • 这里优化通常不是压缩可执行文件的大小,指的是优化运行速度等,优化得到的可执行文件体积可能还更大
  • 优化的必然代价就是编译时间更长,执行逻辑与源代码不再逐行对应,难以调试,因此 debug 模式最好不要用高等级的优化

调试相关

  • -g: 在编译的时候,同时产生基本的调试信息
  • -ggdb: 尽可能的生成 gdb 的可以使用的调试信息。重复使用-g-ggdb是无用的,从结果看,gcc 会忽略-g,使-ggdb生效
  • -w: 不生成任何警告信息(这会关闭所有警告信息,不建议使用)
  • -Wall: 生成主要的警告信息
  • -Wextra: 生成一些额外的警告信息
  • -Werror: 把所有的警告信息升级为报错信息,导致编译失败
  • -v: 详细的编译过程输出

例如

1
2
3
4
5
6
7
8
-Wall -Wextra  # 开启大部分警告和额外警告
-Wpedantic # 对不符合ISO语言规范的发出警告
-Werror # 视所有警告为错误, 不建议使用
-Wshadow # 局部变量遮盖上一层的变量时报错
-Wfatal-errors # 遇到第一个错误即停止
-Wsign-compare # 有符号与无符号比较 被包含在-Wextra
-Wconversion # 隐式转换可能导致值出现错误
-Wno-unused-parameter # 关闭未使用参数警告, 未使用局部变量依然有效

宏定义相关

除了在源文件中使用预编译指令中的宏定义,还可以通过 gcc 的编译命令传递宏定义。

  • -Dmacro: 相当于源文件中的#define macro,在缺省时默认把宏定义为字符串 1
  • -Dmacro=defn: 相当于源文件中的#define macro=a
  • -Umacro: 相当于源文件中的#undef macro
  • -undef: 取消对任何非标准宏的定义

目录相关

  • -Idir: 指定头文件的查找路径
  • -I-: 就是取消前一个参数的功能, 一般在-Idir之后使用
  • -Ldir: 指定编译时,库文件的查找路径
  • -Wl,-rpath=your_dir: 指定运行时,动态库的查找路径

库相关

  • -lxxx: 链接 xxx 库
  • -shared: 生成共享目标文件,通常用在建立共享库时
  • -fPIC: 生成位置无关的代码,通常用在建立共享库时
  • -static: 生成可执行文件时,禁止生成任何共享链接,包括标准库都使用静态链接
  • -share: 生成可执行文件时,倾向于使用动态链接
  • -static-libstdc++: 如果没有这个选项,则默认使用 libstdc++共享库,而这个选项可以指定使用 libstdc++静态库
  • -Wa,option: 此选项传递 option 给汇编程序;如果 option 中间有逗号,就将 option 分成多个选项,然后传递给会汇编程序
  • -Wl,option: 此选项传递 option 给链接程序;如果 option 中间有逗号,就将 option 分成多个选项,然后传递给会链接程序,例如
    • -Wl,-Bstatic: 指示跟在后面的-l选项都使用静态链接,
    • -Wl,-Bdynamic: 指示跟在后面的-l选项都使用动态链接,一直有效,在后面还可以被这类选项进行更改。注意这两种选项需要保证在最后生效的是-Wl,-Bdynamic,这是为了最后动态链接基础库而准备的

其它选项

部分编译

完整的编译过程: 预处理\(\Rightarrow\)编译\(\Rightarrow\)汇编\(\Rightarrow\)链接

gcc 可以使用选项,选择不进行完整的编译过程,在某一步骤完成后停止。

  • -E: 只完成预处理,得到.i文件
  • -S: 只完成预处理和编译,得到.s文件
  • -c: 只完成预处理、编译和汇编,得到.o目标文件

自定义语言识别

  • -x language filename: 明确指定文件所使用的语言,使后缀名无效,对后续的源文件都有效。也就是根据约定 C 语言的后缀名称是.c,而 C++的后缀名是.C 或者.cpp,如果需要把 C 代码文件的后缀名改成.pig,就要用这个参数。其中的语言可以选择 c,c++等。
  • -x none filename: 关掉上一个语言设置选项,也就是让 gcc 回到默认状态:根据文件名后缀,自动识别文件类型。
1
gcc -x c hello.pig -x none hello2.c

编码选项

gcc 与编码相关的选项比如

  • -finput-charset=UTF-8
  • -fexec-charset=GB18030

注意:

  • gcc 对于文件路径的处理上比较鸡肋,尽量不要使用复杂的路径,比如含中文、数字开头、空格、特殊符号等,否则很可能导致错误!(说的就是 Windows,路径很容易出问题)
  • 建议尽量使用 UTF-8 编码,尽量不要在源文件中出现中文注释等非 ASCII 码
  • 除非 io 必须要用到中文,并且已经出现了中文乱码,否则不去管这些编码选项,巨坑:一个情景下 OK 的,可能换一个情景下又是乱码,只要一个环节编码对不上,就必然乱码

CMake 编译选项

CMake 在各种编译模式下使用的默认选项:

  • Release 模式: ​​-O3 -DNDEBUG​​
  • Debug 模式: ​​-g​​
  • MinSizeRel 模式: ​​-Os -DNDEBUG​​
  • RelWithDebInfo 模式: ​-O2 -g -DNDEBUG​​

我们可以修改为如下的编译选项,在 CMakeLists 中添加

1
2
3
4
5
6
7
8
9
# 修改编译选项
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
# debug 默认选项是 -g
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall -Wextra -Wfatal-errors -Wshadow -Wno-unused-parameter -O0") # -Og使用-O1优化, 除了那些影响调试的部分
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Wextra -Wfatal-errors -Wno-unused-parameter -Wshadow -O0") # -Og使用-O1优化, 除了那些影响调试的部分
# release 默认选项是 -O3 -DNDEBUG
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Wall -Wextra -Wfatal-errors -Wno-unused-parameter -Wshadow")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wall -Wextra -Wfatal-errors -Wno-unused-parameter -Wshadow")
endif()