简介
GNU编译器套装(英语:GNU Compiler Collection,缩写为GCC),一套编程语言编译器,以GPL及LGPL许可证所发布的自由软件,也是GNU项目的关键部分,也是GNU工具链的主要组成部份之一。GCC(特别是其中的C语言编译器)也常被认为是跨平台编译器的事实标准。1985年由理查德·马修·斯托曼开始发展,现在由自由软件基金会负责维护工作。
原名为GNU C语言编译器(GNU C Compiler),因为它原本只能处理C语言。GCC很快地扩展,变得可处理C++。之后也变得可处理Fortran、Pascal、Objective-C、Java、Ada,以及Go与其他语言。
许多操作系统,包括许多类Unix系统,如Linux及BSD家族都采用GCC作为标准编译器。苹果电脑Mac OS X 操作系统也采用这个编译器。
原本用C开发,后来因为LLVM、Clang的崛起,令GCC更快将开发语言转换为C++。许多C的爱好者在对C++一知半解的情况下主观认定C++的性能一定会输给C,但是Taylor给出了不同的意见,并表明C++不但性能不输给C,而且能设计出更好,更容易维护的程序(GCC’s move to C++)。
ps: 摘自 wiki http://zh.wikipedia.org/zh-cn/GCC
一些基础概念
一些文件:
后缀名 | 含义 | 后缀名 | 含义 |
---|---|---|---|
.o | c 代码文件 | .s/.S | 汇编语言原始程序 |
.c/.cc/.cxx | C++ 代码文件 | .h | 预处理文件(头文件) |
.m | Objective-C 代码文件 | .o | 可重定向文件 |
.i | 经过预处理的 C 代码文件 | .a/.so | 编译后的库文件 |
.ii | 经过预处理的 C++ 代码文件 |
gcc的编译流程分为了四个步骤:
预处理(Pre-Processing—->编译(Compiling)—–>汇编(Assembling)—–>链接(Linking)
常用编译选项
gcc有超过100个的可用选项,主要包括总体选项、告警和出错选项、优化选项和体系结构相关选项。这里列一些常用选项
选项 | 含义 |
---|---|
-c | 生成目标文件“.o” |
-S | 生成汇编代码 |
-E | 只进行预编译 |
-g | 在可执行程序中包含标准调试信息 |
-o | 输出文件 |
-v | 打印出编译过程 |
-I | 添加头文件搜索目录 |
-L | 添加库搜索目录 |
-static | 生成链接静态库 |
-llibrary | 连接名为library的库文件(注意没有空格) |
-fPIC | 地址无关代码 |
-shared | 生成共享库 |
关于 -fPIC 选项是使共享库能使代码可以在多个进程间共享,需要一些汇编知识和代码运行堆栈机制知识,其实我还没怎么搞懂。
静态库和共享库
静态库: 在linux中一般以 libxxx.a命名.静态库中包含了所有代码和数据,在编译时会把代码和数据拷贝合并到可执行文件当中.因此,静态库是编译时需要的,不是执行时需要的.
共享库:在linux中一般以libxxx.M.N.so命名,MN为主副版本号,so文件当中有自己的代码和函数,当可执行文件运行并调用动态库中的文件时需要借助连接程序 ld 把控制全交给动态库中执行.
Linux系统中动态链接库的配置文件一般在/etc/ld.so.conf文件内,它里面存放的内容是可以被Linux共享的动态联库所在的目录的名字. /etc/ld.so.cache 是 /lib/ /usr/lib/ 目录下 /etc/ld.so.conf 中的记录 /etc/ld.so.conf.d/ 目录下所有文件的记录的缓存.动态加载时系ld 加载器会从这个缓存中找共享库的位值(这里要注意和windows不同,linux不会从可执行文件所在的目录搜索共享库,如果是临时使用可以使用命令ldconfig `pwd`)
实例
下面举个实例说明:
cat.c
#include <stdio.h>
void cat_say(){
printf("I am cat\n");
}
mouse.c
#include <stdio.h>
void mouse_say(){
printf("I am cat\n");
}
animal.h
#ifndef __ANIMAL_H__
void cat_say();
void mouse_say();
#endif
main.c
#include <stdlib.h>
#include "animal.h"
int main(){
cat_say();
exit(0);
}
[aquarius@localhost libtest]$ ll
-rw-rw-r--: 1 aquarius aquarius 65 Mar 1 15:16 animal.h
-rw-rw-r--: 1 aquarius aquarius 63 Mar 1 17:05 cat.c
-rw-rw-r--: 1 aquarius aquarius 78 Mar 1 15:20 main.c
-rw-rw-r--: 1 aquarius aquarius 67 Mar 1 15:21 mouse.c
直接生成可执行文件
[aquarius@localhost libtest]$ gcc -o main main.c cat.c
[aquarius@localhost libtest]$ ./main
I am cat
使用静态库
[aquarius@localhost libtest]$ gcc -c cat.c mouse.c
[aquarius@localhost libtest]$ ll *.o
-rw-rw-r--. 1 aquarius aquarius 1488 Mar 8 22:09 cat.o
-rw-rw-r--. 1 aquarius aquarius 1488 Mar 8 22:09 mouse.o
[aquarius@localhost libtest]$ ar -crv libanimal.a cat.o mouse.o
a - cat.o
a - mouse.o
[aquarius@localhost libtest]$ gcc -o main main.c -L. -lanimal
[aquarius@localhost libtest]$ ./main
I am cat
-L. 选项: 库搜索目录列表添加当前目录(注意后面有个点,没有空格)
-lanimal 选项: 连接名位libanimal.a后者libanimal.M.N.so的库文件,M为主版本号N为副版本号(注意 l 后面没有空格)
使用共享库
[aquarius@localhost libtest]$ gcc -fPIC -shared -o libanimal.so cat.c mouse.c
[aquarius@localhost libtest]$ gcc -o main main.c -L. -lanimal.1.0
[aquarius@localhost libtest]$ ./main
./main: error while loading shared libraries: libanimal.1.0.so: cannot open shared object file: No such file or directory
出错了,为什么呢, 用 ldd 命令看一下依赖关系
[aquarius@localhost libtest]$ ldd ./main
linux-vdso.so.1 => (0x00007fff921f8000)
libanimal.1.0.so => not found
libc.so.6 => /lib64/libc.so.6 (0x00007fd5d0fd7000)
/lib64/ld-linux-x86-64.so.2 (0x00007fd5d13bc000)
[aquarius@localhost libtest]$ sudo ldconfig `pwd`
找不到动态库,为什么呢,上面说了,没有配置 ld 加载缓存
[aquarius@localhost libtest]$ ldd ./main
linux-vdso.so.1 => (0x00007fff477fb000)
libanimal.1.0.so => /home/aquarius/libtest/libanimal.1.0.so (0x00007f45cb476000)
libc.so.6 => /lib64/libc.so.6 (0x00007f45cb0b8000)
/lib64/ld-linux-x86-64.so.2 (0x00007f45cb69f000)
[aquarius@localhost libtest]$ ./main
I am cat
总结
好了,这就是linux下用gcc编译程序的过程和一些总结,但是在实际生成环境中真的是这样编译代码的吗?
当然不是的,这个过程只是为了学习一下gcc的编译过程以及静态库和共享库的一些知识,在实际生产环境中是使用 make 工具进行管理工程和编译的以及安装卸载的,make 工具需要 Makefile 文件,那么这个 Makefile 文件是手动编写的吗?
当然可以手动编写,但生产环境一般是用 automake 工具进行自动生成 Makefile 文件的(就是你编译安装软件是用的 ./configure)这个工具的使用篇幅也不小,有空在写吧…
Linux(Debian)安装软件缺少动态连接库.so:http://www.linuxdiyf.com/linux/7017.html