GCC快速入门

文章目录

  • 目的
  • 基础使用
  • C/C++混合编译
  • 静态链接库和动态链接库
  • 总结

目的

GCC(GNU Compiler Collection)是GNU出品的用来编译 C、C++、Objective-C、Fortran、Ada、Go 等语言的一系列编译器集合。GCC里面最常用的就是gcc和g++两个工具了,主要用来编编译C和C++的程序,这篇文章将对相关内容做个说明。

基础使用

通常我们使用gcc来编译C语言程序,首先准备下面代码,将它保存为hello.c文件:

#include 

int main(void)
{
     
	printf("Hello, world!\n");
}

在Linux(这里使用树莓派进行演示,在Windows上可以安装 Mingw-w64 进行测试)上直接使用gcc hello.c就可以编译生成可执行文件:
GCC快速入门_第1张图片
上面演示中直接一步到位出成果,但实际上这中间涉及了好几个步骤。C/C++从程序文本经由编译器处理成为目标文件的步骤主要是下面几个:
在这里插入图片描述
可以使用一些选项来控制这些过程:

选项 功能
-E 预处理指定的源文件,不进行编译
-S 编译指定的源文件,但是不进行汇编
-c 编译、汇编指定的源文件,但是不进行链接
-o 指定生成文件的文件名

GCC快速入门_第2张图片
GCC快速入门_第3张图片
如果源程序有语法错误那么在编译过程中会报错:
GCC快速入门_第4张图片
如果一个程序代码使用了多个文件那么也可以在指定这多个文件进行编译:
GCC快速入门_第5张图片
通常来说多个文件编译的时候头文件不需要指定,就像上面例子(不过这样做在某些情况下会有问题)。另外可以用 * 作为通配符,比如 *.c 就是指定所有 .c 文件:
GCC快速入门_第6张图片

常用方式
使用gcc一步到位方式编译时每次进行所有文件都需要经历预处理、编译、汇编、链接几个环节,这在文件多的情况下会非常耗时。如果程序经常修改,每次所有文件都需要重复上面过程的话会非常浪费时间。通常情况下我们将整个过程拆分成两步:

  • 使用 -c 选项生成 *.o 的文件;
  • 链接生成目标文件;

这样的话每次只需要对有修改的文件使用 -c 选项生成 *.o 的文件,然后再链接就行,其它没修改的文件就不需要再预处理、编译、汇编了,对大项目来说可以节省很多时间。

更多常用选项
对于大型项目来说手动处理上面两步其实也挺麻烦的,更多的时候会配合Makefile使用,在这个过程中通常还会用到下面这些选项:

选项 功能
-MM 生成文件关联的信息,忽略由 #include造成的依赖关系
-MMD 将-MM的信息写道.d文件中
-w 不生成任何警告信息
-Wall 生成所有警告信息
-O0 -O1 -O2 -O3 代码优化等级,-O0表示不优化,-O3表示最高等级优化

C/C++混合编译

上面演示了gcc编译C程序,而对于C++程序我们可以用g++来编译:
GCC快速入门_第7张图片
C++是向下兼容的C语言的,所以g++也可以用来编译C程序:
GCC快速入门_第8张图片
理论上对于C/C++混合程序而言理论上可以全都用g++来编译,但这样做对程序体积、性能等会有影响,甚至可能会编译出错,所以通常的处理方式如下:

  • 声明C语言程序的头文件中内容使用 extern “C” { } 包围,比如下面这样;
    #ifndef __MYFILE_H__ 
    #define __MYFILE_H__
    
    #ifdef __cplusplus
    extern "C" {
           
    #endif
    
    void myfun(void);
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif // __MYFILE_H__ 
    
  • 使用gcc -c编译.c文件;
  • 使用g++ -c编译.cpp文件;
  • 使用g++链接生成目标文件;

GCC快速入门_第9张图片

静态链接库和动态链接库

一般来说我们写代码时调用的那些系统中自带的库函数都不是.c或是.cpp这些明文的文件,而是一个个封装起来的库文件,通常分为两类:

静态链接库

静态链接库实现链接操作的方式很简单,即程序文件中哪里用到了库文件中的功能模块,GCC 编译器就会将该模板代码直接复制到程序文件的适当位置,最终生成可执行文件。
使用静态链接库生成的文件通常体积较大,但运行时不再依赖库文件,可以拷贝到别的设备上运行。
在Linux中静态链接库文件的后缀名通常用.a表示;在Windows系统中,静态链接库文件的后缀名为.lib。

动态链接库

动态链接库,又称为共享链接库。和静态链接库不同,采用动态链接库实现链接操作时,程序文件中哪里需要库文件的功能模块,GCC 编译器不会直接将该功能模块的代码拷贝到文件中,而是将功能模块的位置信息记录到文件中,直接生成可执行文件。
使用动态链接库生成的文件通常体积较小,但运行时依赖库文件。
在Linux中,动态链接库的后缀名通常用.so 表示;在Windows系统中,动态链接库的后缀名为.dll。

通常情况下GCC在编译过程中默认使用动态链接库,我们可以使用 -static 选项指定使用静态链接库:
GCC快速入门_第10张图片
静态链接库和动态链接库我们也可以自己制作,只要是不包含main函数的文件都可以打包成库文件。可以一个文件打包成一个库文件也可以将多个文件打包成一个库文件。

通常可以使用 ar rcs 静态链接库名称 目标文件1 目标文件2 ... 方式将.o文件打包成名称为 libxxx.a 的静态链接库:
GCC快速入门_第11张图片
通常可以使用 gcc -fpic -shared 源文件名... -o 动态链接库名 方式将源文件打包成名称为 libxxx.so 的动态链接库(也可以拆分为 gcc -c -fpic ...gcc -shared -o ... 两步):
GCC快速入门_第12张图片
上面演示中可以看到使用动态链接库生成的程序运行时回去默认的库目录去寻找用到的动态链接库,如果没有找到程序就无法运行。通常Linux中动态链接库放置在/usr/lib/目录下,当我将库移动到该目录下后程序就可以运行了。

一般的像是头文件、库文件的路径或是指定的文件这些都可以手动设置,相关选项如下:

选项 功能
-I (大写i) 指定头文件路径
-i 指定头文件名字
-L 指定库文件路径
-l (小写L) 指定库文件名字

除了在使用gcc是指定选项的方式,还可以使用环境变量或是配置文件等方式来指定路径和文件。

总结

GCC基础使用是比较简单的,基本上直接使用是比较少的,通常会配合Makefile使用。而Makefile文件的编写则需要稍稍对GCC的基础使用有一些了解,基本上了解上面那些内容就够了。

更多内容可以参考下面链接:
https://www.gnu.org/software/gcc/

你可能感兴趣的:(编程相关,gcc,g++,GNU,编译,makefile)