任何一种高级语言,要想在机器上执行,必须翻译为机器能读懂的机器语言。编译器就至关于翻译官,将高级语言翻译为机器语言。java
GCC 最初只用了编译 C 语言程序,全称是 GNU C Compiler。后来扩展为能够编译多种语言,因此又称为 GNU Compiler Collection。GCC 是开源免费的编译器。linux
GCC 是一组工具的集合,这些工具能够执行预处理、编译、汇编、连接等任务。GCC 经过文件后缀名来识别文件并调用合适的工具,例如对于 .c 文件会调用 C 编译器,对于 .cpp 文件会调用 C++ 编译器。c++
a.out
文件,经过 ./a.out
能够执行:# gcc 1.c # ./a.out
-o 输出文件名
指定生成的可执行文件名称:# gcc -o build 1.c # ./build
--save-temps
选项保留编译过程当中产生的全部中间文件:[root@VM_139_38_centos define]# ls main.c [root@VM_139_38_centos define]# gcc --save-temps main.c [root@VM_139_38_centos define]# ll total 44 -rwxr-xr-x 1 root root 8568 Jan 19 15:32 a.out -rw-r--r-- 1 root root 325 Jan 19 14:39 main.c -rw-r--r-- 1 root root 16901 Jan 19 15:32 main.i -rw-r--r-- 1 root root 1600 Jan 19 15:32 main.o -rw-r--r-- 1 root root 561 Jan 19 15:32 main.s
-v
选项输出编译过程当中产生的全部信息:# gcc -v -o build 1.c Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/lto-wrapper Target: x86_64-redhat-linux Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux Thread model: posix gcc version 4.8.5 20150623 (Red Hat 4.8.5-28) (GCC) COLLECT_GCC_OPTIONS='-v' '-o' 'build' '-mtune=generic' '-march=x86-64' /usr/libexec/gcc/x86_64-redhat-linux/4.8.5/cc1 -quiet -v 1.c -quiet -dumpbase 1.c -mtune=generic -march=x86-64 -auxbase 1 -version -o /tmp/ccgJDXWv.s GNU C (GCC) version 4.8.5 20150623 (Red Hat 4.8.5-28) (x86_64-redhat-linux) compiled by GNU C version 4.8.5 20150623 (Red Hat 4.8.5-28), GMP version 6.0.0, MPFR version 3.1.1, MPC version 1.0.1 GGC heuristics: --param ggc-min-expand=97 --param ggc-min-heapsize=127047 ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/4.8.5/include-fixed" ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../x86_64-redhat-linux/include" #include "..." search starts here: #include <...> search starts here: /usr/lib/gcc/x86_64-redhat-linux/4.8.5/include /usr/local/include /usr/include End of search list. GNU C (GCC) version 4.8.5 20150623 (Red Hat 4.8.5-28) (x86_64-redhat-linux) compiled by GNU C version 4.8.5 20150623 (Red Hat 4.8.5-28), GMP version 6.0.0, MPFR version 3.1.1, MPC version 1.0.1 GGC heuristics: --param ggc-min-expand=97 --param ggc-min-heapsize=127047 Compiler executable checksum: fbe9869a2e70aadeaf82d7c32bbeabe0 COLLECT_GCC_OPTIONS='-v' '-o' 'build' '-mtune=generic' '-march=x86-64' as -v --64 -o /tmp/ccmzAIx7.o /tmp/ccgJDXWv.s GNU assembler version 2.25.1 (x86_64-redhat-linux) using BFD version version 2.25.1-22.base.el7 COMPILER_PATH=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/:/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/:/usr/libexec/gcc/x86_64-redhat-linux/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/:/usr/lib/gcc/x86_64-redhat-linux/ LIBRARY_PATH=/usr/lib/gcc/x86_64-redhat-linux/4.8.5/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../:/lib/:/usr/lib/ COLLECT_GCC_OPTIONS='-v' '-o' 'build' '-mtune=generic' '-march=x86-64' /usr/libexec/gcc/x86_64-redhat-linux/4.8.5/collect2 --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o build /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../.. /tmp/ccmzAIx7.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtend.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crtn.o
预处理时,会把全部的 include 替换为所引入文件的代码,把 define 宏定义都替换为具体的定义元素。对 C 程序预处理后,获得 .i 文件。对应 GCC 的选项是 gcc -E
,例如web
gcc -E -o my.i 1.c
命令能够获得 my.i 这个文件。编程
对 C 程序编译后,获得汇编程序。对应 GCC 的选项是 gcc -S
,例如bootstrap
gcc -S -o my.s 1.c
命令能够获得 my.s 这个汇编文件。这个步骤对应上面的输出信息为:centos
/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/cc1 -quiet -v 1.c -o /tmp/ccgJDXWv.s -quiet -dumpbase 1.c -mtune=generic -march=x86-64 -auxbase 1 -version
将上一步编译获得的汇编程序,转为 .o
输出文件,这是能够被计算机直接读懂的二进制文件。可是须要注意,由于没有连接进额外的资源,一般这个文件是不能直接执行的。对应 GCC 的选项是 gcc -c
,这个选项会在汇编前自动调用编译工具。例如bash
gcc -c -o my.out my.s
命令能够获得 my.out 这个输出文件,此时还须要连接,还不能直接执行。app
连接,能够将多个 .o
输出文件组成一个可执行文件,能够自动连接所需的依赖。例如svg
gcc -o myExe my.out
对应 GCC 的选项是 gcc -o
,若是指定的输入是 .c 或 .s 后缀的文件,这个选项在连接前会自动调用编译或/和汇编两个工具。
一般使用 GCC 时,直接调用 gcc -o myOutName xx.c yy.c zz.c
便可自动完成上述全部步骤,获得一个可执行文件。
C 语言有两种方式引入头文件:
#include "my.h"
,首先在当前目录下寻找,找不到的话再去系统库中寻找。用于本身实现的头文件。#include <stdio.h>
,直接在系统库中寻找。项目中一般把头文件放在单独的目录中,例如项目根目录下的 inc 目录。这时可用在使用 GCC 时经过 -I 头文件位置
来指定要查找头文件的目录。
[root@VM_139_38_centos header]# gcc main.c main.c:2:16: fatal error: my.h: No such file or directory #include "my.h" ^ compilation terminated. [root@VM_139_38_centos header]# gcc -I inc main.c [root@VM_139_38_centos header]# ./a.out Hello World! 123
编译错误主要是语法错误。例如括号不配对,变量名写错。
连接时发现缺乏所需的文件,例如函数定义缺失,会报连接错误。例如对下面的代码:
#include <stdio.h> void fun(); int main() { fun(); return 0; }
编译时会有以下报错,其中 collect2 命令是连接时用的程序:
/tmp/cc2lEZt4.o: In function `main': main.c:(.text+0x15): undefined reference to `fun' collect2: error: ld returned 1 exit status
解决方法也很简单,在同一个文件中实现这个方法后,从新编译便可。若是方法的实如今另外一个文件中,能够在用 GCC 编译时指定这个文件便可,例如方法声明在 1.c 中,而方法体在 2.c 这个文件中,则用下面的命令编译便可:
gcc -o my.out 1.c 2.c
固然,一般每一个文件都是单独编译的,最后连接到一块儿:
gcc -c -o 1.o 1.c gcc -c -o 2.o 2.c gcc -o my.out 1.o 2.o
例如,一个方法在多个文件中定义,而连接时须要把这几个文件整合为一个可执行文件,就会报错:
fun.o: In function `fun': fun.c:(.text+0x0): multiple definition of `fun' main.o:main.c:(.text+0x0): first defined here collect2: error: ld returned 1 exit status