本文部分翻译自https://www.man7.org/linux/man-pages/man1/g++.1.html,过程中借助AI工具进行翻译,并进行微调。
一、名称
gcc c和c++编译器
二、概要
gcc [-c|-S|-E] [-std=standard]
[-g] [-pg] [-Olevel]
[-Wwarn...] [-Wpedantic]
[-Idir...] [-Ldir...]
[-Dmacro[=defn]...] [-Umacro]
[-foption...] [-mmachine-option...]
[-o outfile] [@file] infile...
g++和gcc绝大部分选项是一致的。
三、常用选项
-E
在预处理之后停止;不执行编译。输出形式为预处理后的源代码,该代码被发送到标准输出。
不需要预处理的输入文件将被忽略。
示例:
$ g++ -E main.cpp -I ./lib
输出:
# 0 "main.cpp"
# 0 "<built-in>"
# 0 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 0 "<command-line>" 2
# 1 "main.cpp"
# 1 "./lib/add.h" 1
int g_value;
int Add(int a, int b);
# 3 "main.cpp" 2
int main(){
int a = 10, b = 11;
int sum = Add(a, b);
return 0;
}
-S
在编译之后停止;不进行汇编。输出形式为汇编代码文件。
默认情况下,源文件的汇编文件名是通过将后缀 .c、.i 等替换为 .s 来生成的。
不需要编译的输入文件将被忽略。
源代码--编译-->汇编代码
示例:
$ g++ -E main.cpp -I ./lib
查看:
$ cat main.s
输出结果:
.file "main.cpp"
.text
.globl g_value
.bss
.align 4
.type g_value, @object
.size g_value, 4
g_value:
.zero 4
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movl $10, -12(%rbp)
movl $11, -8(%rbp)
movl -8(%rbp), %edx
movl -12(%rbp), %eax
movl %edx, %esi
movl %eax, %edi
call _Z3Addii@PLT
movl %eax, -4(%rbp)
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0"
.section .note.GNU-stack,"",@progbits
.section .note.gnu.property,"a"
.align 8
.long 1f - 0f
.long 4f - 1f
.long 5
0:
.string "GNU"
1:
.align 8
.long 0xc0000002
.long 3f - 2f
2:
.long 0x3
3:
.align 8
4:
main.s是汇编代码
-c
编译或汇编源文件,但不进行链接。链接不会执行。最终输出是每个源文件的一个目标文件。
默认情况下,源文件的目标文件名是通过将后缀 .c、.i、.s 等替换为 .o 来生成的。
不要求编译或汇编的、无法识别的输入文件将被忽略。
汇编代码--汇编-->二进制代码
示例:
编译main.cpp
$ g++ -c main.cpp -I ./lib
使用objdump命令查看目标文件
$ objdump -DS main.o
输出(部分):
main.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <main>:
0: f3 0f 1e fa endbr64
4: 55 push %rbp
5: 48 89 e5 mov %rsp,%rbp
8: 48 83 ec 10 sub $0x10,%rsp
c: c7 45 f4 0a 00 00 00 movl $0xa,-0xc(%rbp)
13: c7 45 f8 0b 00 00 00 movl $0xb,-0x8(%rbp)
1a: 8b 55 f8 mov -0x8(%rbp),%edx
1d: 8b 45 f4 mov -0xc(%rbp),%eax
20: 89 d6 mov %edx,%esi
22: 89 c7 mov %eax,%edi
24: e8 00 00 00 00 call 29 <main+0x29>
29: 89 45 fc mov %eax,-0x4(%rbp)
2c: b8 00 00 00 00 mov $0x0,%eax
31: c9 leave
32: c3 ret
Disassembly of section .bss:
0000000000000000 <g_value>:
0: 00 00 add %al,(%rax)
可以看到,编译后目标文件已经是二进制代码。
-o file
指定输出文件名称
-std=
指定语言标准,目前只支持c和c++
示例:
$ g++ -std=c++11 main.cpp -I ./lib
-shared
生成一个动态库,然后可以与其他对象链接以形成可执行文件。并非所有系统都支持此选项。为了得到可预测的结果,您在指定此链接器选项时,也必须指定用于编译的同一组选项(-fpic、-fPIC 或 model 子选项)。
-g
生成调试信息,debug模式下用于调试代码
-pthread
链接到POSIX线程库
-I dir
添加搜索头文件目录
-Ldir
添加库文件搜索目录
-fpic
生成适用于共享库的与地址无关的代码(PIC)(如果机器支持的话)
-fPIC
生成与位置无关的的代码,适用于使用动态库,与“-fpic”的区别在于去除去全局偏移表的任何限制(如果机器支持的话)