gcc常用选项
一些gcc常用的选项
-c
: 只编译但不链接, 生成目标文件(.o), 无法识别的文件将被忽略; 原文:
Compile or assemble the source files, but do not link. The linking stage simply is not done. The ultimate output is in the form of an object file for each source file.
By default, the object file name for a source file is made by replacing the suffix ‘.c’, ‘.i’, ‘.s’, etc., with ‘.o’.
Unrecognized input files, not requiring compilation or assembly, are ignored.
-S
: 将源代码编译成汇编代码,而不是直接生成机器代码或可执行文件。使用这个选项时,GCC会执行编译过程中的前几个步骤(如预处理、编译),但会停在生成汇编代码这一步,不会进一步进行汇编成目标代码或进行链接。-E
: -E选项用于仅执行预处理步骤。GCC会处理源代码中的预处理指令,如宏定义的扩展、条件编译指令的处理、包含文件的插入等,但它不会编译、汇编或链接代码。注意: 默认情况下,这个输出会直接发送到标准输出(即屏幕), 所以可以使用|
传到vim或者其他编辑器中查看:1
gcc -E helloworld.c | vim -
-o
: 这一部分强烈推荐看原文,-o
选项允许指定主输出文件的名称和位置,这适用于任何类型的输出,无论是可执行文件、目标文件、汇编文件还是预处理的C代码。这一部分我直接贴出gpt对原文的解读:
主输出定位:如果没有指定-o选项,默认情况下,可执行文件会被放置在a.out中,源文件source.suffix的目标文件会命名为source.o,其汇编文件命名为source.s,预编译头文件命名为source.suffix.gch,所有预处理的C源代码输出到标准输出(屏幕)。
辅助输出和转储输出:虽然-o仅指定主输出,但它也影响辅助输出和转储输出的命名和定位。除非有其他指定,这些输出文件默认被放置在主输出文件相同的目录下。对于辅助输出,输入文件的后缀会被替换为辅助输出文件类型的后缀;对于转储输出,转储文件的后缀会被添加到输入文件后缀之后。在编译命令中,辅助输出和转储输出的基础名称是主输出的名称;在编译并链接命令中,主输出名称(去掉可执行文件后缀)与输入文件名称结合使用。如果它们的基础名称相同,结果就是该基础名称,否则,它们通过短横线连接。
示例:
gcc -c foo.c ...
会产生foo.o
作为主输出,辅助输出和转储输出也会放置在它旁边,例如辅助文件foo.dwo
(对于-gsplit-dwarf
)和转储文件foo.c.???r.final
(对于-fdump-rtl-final
)。如果明确指定了非链接器的输出文件,辅助和转储文件默认使用相同的基础名称。例如,
gcc -c foo.c -o dir/foobar.o ...
将辅助输出命名为dir/foobar.*
,转储输出命名为dir/foobar.c.*
。链接输出会为辅助和转储输出添加前缀。例如,
gcc foo.c bar.c -o dir/foobar ...
通常会将辅助输出命名为dir/foobar-foo.*和dir/foobar-bar.*
,转储输出命名为dir/foobar-foo.c.*
和dir/foobar-bar.c.*
。唯一的例外是当可执行文件与单一输入文件共享基础名称时,例如
gcc foo.c -o dir/foo ...
,这种情况下,辅助输出被命名为dir/foo.*
,转储输出被命名为dir/foo.c.*
。调整辅助和转储输出的位置和名称:可以通过
-dumpbase
、-dumpbase-ext
、-dumpdir
、-save-temps=cwd
和-save-temps=obj
选项调整辅助和转储输出的位置和名称。简而言之,-o选项不仅允许你指定主输出文件的名称和位置,它还间接影响了辅助输出和转储输出的命名和定位规则。这在管理大型项目和自定义构建过程时非常有用。
-g
: 在可执行文件中生成标准调试信息。-g
选项生成的调试信息会尽量适配不同的调试器,但主要还是以GDB(GNU Debugger)为主。-ggdb
:为GDB调试器优化,生成最丰富的调试信息,包括一些特定于GDB的优化,以提供更好的调试体验。-Wall
: 开启大多数编译器警告,有助于发现潜在的错误。Werror
: 将所有的警告当作错误处理。-D
: 定义宏,即在编译时从命令行向源代码中引入宏定义。 基本语法如下:-Dname
或者-Dname=definition
, 其中,name是要定义的宏的名称,definition是这个宏的值。如果没有指定definition,宏name的值默认为1。- eg:
1
2
3
4
5
6
7
8
9
10
int main() {
printf("Debug mode is enabled.\n");
printf("Debug mode is not enabled.\n");
return 0;
}
使用-D选项来定义DEBUG宏:
1
gcc -DDEBUG example.c -o example
这将使得编译的程序在运行时输出:“Debug mode is enabled.” 因为DEBUG宏在编译时被定义了,所以预处理器会包含#ifdef DEBUG和#endif之间的代码。- eg: