GCC编译程序

GCC编译程序

包括四个过程:

  • 预处理(pre—processing)
  • 编译(compiling)
  • 汇编(assembling)
  • 链接(linking)

在这里插入图片描述

预处理:将头文件和宏定义进行展开

编译阶段:gcc调用不同语言的编译器,例如C语言调用的编译器ccl,编译程序的过程中gcc会调用不同的工具

汇编阶段:gcc调用汇编器进行汇编,汇编器可生成可重定位的目标文件,重定位能够将源代码的代码、变量等定位为内存的具体地址

链接阶段: 将程序所需要的目标文件进行连接成可执行文件

GCC常用选项

选项名作用
-o产生目标(.i、.s、.o、可执行文件等)
-E只运行C预编译器
-S告诉编译器产生汇编程序文件后停止编译,产生的汇编语言文件拓展名为.s
-c通知gcc取消连接步骤,即编译源码,并在最后生成目标文件
-Wall使gcc对源文件的代码有问题的地方发出警告
-Idir将dir目录加入搜索头文件的目录路径
-Ldir将dir目录加入搜索库的目录路径
-llib连接lib库
-g在目标文件中嵌入调试信息,以便gdb之类的调试程序调试

下面通过简单例子进行操作说明:

我们有源文件hello.c

gcc -E hello.c -o hello.i 对hello.c文件进行预处理,生成hello.i文件

gcc -s hello.i -o hello.s 对预处理文件进行编译,生成汇编文件

gcc -c hello.s -o hello.o 对汇编文件进行编译,生成目标文件

gcc hello.o -o hello 对目标文件进行链接,生成可执行文件

gcc hello.c -o hello 直接编译链接成可执行的目标文件

gcc -c hello.c 或 gcc -c hello.c -o hello.o 编译生成可重定位的目标文件

GCC编译多个文件

假设有三个文件,分别是hello.c、hello.h、main.c

/*
	hello.c
*/
#include <stdio.h>
#include "hello.h"
void printHello(){
	printf("Hello World!\n");
}
/*
	main.c
*/
#include <stdio.h>
#include "hello.h"
int main(){
    printHello();
    return 0;
}
/*
	hello.h
*/
#ifndef _HELLO_
#define _HELLO_

void printHello();

#endif

编译上面三个文件,可以一次执行:

gcc hello.c main.c -o main

也可以单独编译,单独编译的好处是当其中某一个模块发送改变时,只需要编译该模块就行,不需要重新编译全部的文件,这样可以节省编译的时间。

gcc -Wall -c main.c -o main.o

gcc -Wall -c hello.c -o hello.o

gcc -Wall main.o hello.o -o main

外部库的使用

在使用C语言和其他语言进行程序设计的时候,我们需要头文件来提供对常数的定义和对系统及库函数调用的声明。库文件是一些预先编译好的函数集合,那些函数都是按照可重用原则编写的。它们通常由一组互相关联的可重用原则编写的,它们通常由一组互相关联的用来完成某项常见工作的函数构成。使用库的优点在于:

  • 模块化的开发
  • 可重用性
  • 可维护性

库又可以分为静态库与动态库:

  • 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。静态库比较占用磁盘空间,而且程序不可以共享静态库。运行时也是比较占内存的,因为每个程序都包含了一份静态库。
  • 动态库(.so或.sa):程序在运行的时候才去链接共享库的代码,多个程序共享使用库的代码,这样就减少了程序的体积。

一般头文件或库文件的位置在:

  • /usr/include及其子目录底下的include文件夹
  • /usr/local/include及其子目录底下的include文件夹
  • /usr/lib
  • /usr/local/lib
  • /lib

静态库的生成

为了生成.a文件,我们需要先生成.o文件。下面这行命令将我们的hello.o打包成静态库libhello.a:

ar rcs libhello.a hello.o

ar是gun归档工具,rcs表示replace and create,如果libhello之前存在,将创建新的libhello.a并将其替换。

然后就可以这样来使用静态库libhello.a

gcc -Wall main.c libhello.a -o main

还有另外一种使用方式:

gcc -Wall -L. main.c -o main -lhello 【lhello 是 libhello的缩写】

其中 -L表示库文件的位置在当前目录下,由于libhello.a是我们自己生成的,并存放在当前录下下,所以需要加上-L.选项。默认库文件是在系统的目录下进行搜索。同样的,-I.选项用于头文件的搜索。

共享库的生成

生成一个共享库,名称的规则是libxxx.so。将刚才hello.o生成libhello.so的命令为:

gcc -shared -fPIC hello.o -o libhello.so

生成了共享库之后,可以这样来使用共享库:

gcc -Wall main.o -o main -L. -lhello

该命令与使用静态库的命令相同,但是在共享库与静态库共存的情况下,优先使用共享库。

共享库有时候并不不在当前的目录下,为了让gcc能够找得到共享库,有下面几种方法:

  1. 拷贝.so文件到系统共享库路径下,一般指/usr/lib
  2. 在~/.bash_profile文件中,配置LD_LIBRARY_PATH变量
  3. 配置/etc/ld.so.conf,配置完成后调用ldconfig更新ld.so.cache

其中,shared选项表示生成共享库格式。fPIC表示产生位置无关码(position independent code),位置无关码表示它的运行、加载与内存位置无关,可以在任何内存地址进行加载。

库的搜索路径

库的搜索路径遵循几个搜索原则:从左到右搜索-I -l指定的目录,如果在这些目录中找不到,那么gcc会从由环境 变量指定的目录进行查找。头文件的环境变量是C_INCLUDE_PATH,库的环境变量是LIBRARY_PATH.如果还是找不到,那么会从系统指定指定的目录进行搜索。

文章借鉴:http://www.cnblogs.com/QG-whz/p/5456720.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值