gcc使用及动静态库制作
一. GCC的使用
1. GCC的编译过程

(1)预处理(cpp)gcc -E(输出问价通常以 .i 结尾),将头文件展开,宏替换等操作;
(2)编译器(gcc)gcc -S(输出问价以 .s 结尾)生成汇编代码;
(3)汇编器(as)gcc -c(输出文件以 .o 结尾)将汇编编译成二进制文件;
(4)连接器(ld)gcc,链接 lib 库生成可执行文件。
执行过程如下(hello.c):
#include<stdio.h> int main()
{
printf("hello world\n");
return ;
}
Linux执行过程:
[root@centos1 src]# gcc -E hello.c >> hello.i
[root@centos1 src]# gcc -S hello.i
[root@centos1 src]# gcc -c hello.s
[root@centos1 src]# gcc -o hello.out hello.o
[root@centos1 src]# ./hello.out
hello world
注:第4步如果使用 ld 会报如下错误
[root@centos1 src]# ld hello.o
ld: warning: cannot find entry symbol _start; defaulting to 00000000004000b0
hello.o: In function `main':
hello.c:(.text+0xa): undefined reference to `puts'
没有 __start 是因为C程序以main为主函数,汇编以start为主函数入口,改用gcc连接就可以,如果非用ld,需要自己链接libc.so库。
2. GCC编译参数
- -I 包含头文件路径(可以使绝对路径,也可以是相对路径)
- -O 优化选项,1-3越高优先级越高
- -L 包含的库路径
- -l(L的小写)指定库名(通常libxxx.so或者libxxx.a,-lxxx)
- -o 目标文件
- -c 编译成.o文件
- -g 用于gdb调试不加此选项不能gdb调试
- -Wall 显示更多的警告
- -D 指定宏编译
- -lstdc++ 编译c++代码
二. 动静库
1. 制作库文件作用
作用:将实现某部分功能的代码封装成库文件,以方便调用,或者是对代码进行保护加密。
应用场景:有时想将某代码提供给别人用,但是又不想公开源代码,这时可以将代码封装成库文件。在开发中调用其他人员编写的库。
2. 静态库
(1)制作步骤
1)编译.o文件
2)将.o文件打包:ar rcs libname.a file1.o file2.o file3.o ...
3)将头文件与库一起发布
文件内容及路径分布如下:
[root@centos1 calc]# tree
.
├── include
│ └── head.h
├── lib
├── main.c
└── src
├── add.c
└── sub.c
#include<stdio.h> int add(int a, int b);
int sub(int a, int b);
head.h
#include "head.h" int main(void)
{
int a = , b = ; printf("%d + %d is %d\n", a, b, add(a, b));
printf("%d - %d is %d\n", a, b, sub(a, b)); return ;
}
main.c
#include "head.h" int add(int a, int b)
{
return a + b;
}
add.c
#include "head.h" int sub(int a, int b)
{
return a - b;
}
sub.c
- 编译为.o文件
进入到 src 目录下执行:
[root@centos1 src]# gcc -c *.c -I ../include/
[root@centos1 src]# ll
总用量
-rw-r--r--. root root 4月 : add.c
-rw-r--r--. root root 4月 : add.o
-rw-r--r--. root root 4月 : sub.c
-rw-r--r--. root root 4月 : sub.o
- 将.o文件打包,制作成libCalc.a静态库
[root@centos1 src]# ar rcs libCalc.a *.o
[root@centos1 src]# ll
总用量
-rw-r--r--. root root 4月 : add.c
-rw-r--r--. root root 4月 : add.o
-rw-r--r--. root root 4月 : libCalc.a
-rw-r--r--. root root 4月 : sub.c
-rw-r--r--. root root 4月 : sub.o
(2)使用
编译时需要加静态库名(记得路径),-I 包含头文件
- 使用静态库编译main.c并执行main
我们将libCalc.a移动到上层的lib中并退回到calc目录,编译main.c并执行:
[root@centos1 calc]# gcc main.c -o main -I include/ -L ./lib -lCalc
[root@centos1 calc]# ll
总用量 24
drwxr-xr-x. 2 root root 4096 4月 20 15:07 include
drwxr-xr-x. 2 root root 4096 4月 20 15:14 lib
-rwxr-xr-x. 1 root root 6838 4月 20 15:14 main
-rw-r--r--. 1 root root 179 4月 20 14:57 main.c
drwxr-xr-x. 2 root root 4096 4月 20 15:14 src
[root@centos1 calc]# ./main
10 + 10 is 20
10 - 10 is 0
可以用 nm 命令查看文件内容:
[root@centos1 calc]# nm lib/libCalc.a add.o:
0000000000000000 T add sub.o:
0000000000000000 T sub
(3)静态库优缺点
优点:
1)执行快
2)发布应用时不需要发布库
缺点:
1)执行程序体积会比较大
2)库变更时需要重新编译程序
三. 动态库
1. 制作步骤
(1)编译与位置无关的代码(下图共享库),生成.o目标文件,关键参数 -fPIC
进程虚拟地址空间

(2)将.o文件打包,关键参数 -shared
(3)将库与头文件一起发布
- 生成.o目标文件
文件路径和内容同上,进入到src目录,生成.o目标文件:
[root@centos1 src]# gcc -fPIC -c *.c -I ../include/
[root@centos1 src]# ll
总用量
-rw-r--r--. root root 4月 : add.c
-rw-r--r--. root root 4月 : add.o
-rw-r--r--. root root 4月 : sub.c
-rw-r--r--. root root 4月 : sub.o
- 将.o文件打包生成动态库
[root@centos1 src]# gcc -shared -o libCalc.so *.o
[root@centos1 src]# ll
总用量
-rw-r--r--. root root 4月 : add.c
-rw-r--r--. root root 4月 : add.o
-rwxr-xr-x. root root 4月 : libCalc.so
-rw-r--r--. root root 4月 : sub.c
-rw-r--r--. root root 4月 : sub.o
2. 使用
- 使用生成的动态库,-L 指定动态库路径 -l 指定库名(gcc main.c -o main -I include/ -L ./lib -lCalc)
退出到calc目录下,将动态库拷贝到lib目录下并编译mian.c并执行main:
[root@centos1 calc]# gcc main.c -o main -I include/ -L ./lib -lCalc
[root@centos1 calc]# ll
总用量 24
drwxr-xr-x. 2 root root 4096 4月 20 15:07 include
drwxr-xr-x. 2 root root 4096 4月 20 15:29 lib
-rwxr-xr-x. 1 root root 7066 4月 20 15:30 main
-rw-r--r--. 1 root root 179 4月 20 14:57 main.c
drwxr-xr-x. 2 root root 4096 4月 20 15:29 src
[root@centos1 calc]# ./main
./main: error while loading shared libraries: libCalc.so: cannot open shared object file: No such file or directory
无法找到动态库目标文件,解决方法有三个:
(1)拷贝到/lib下(不允许,容易与别人库命名重合)
(2)将库路径增加到环境变量LD_LIBRARY_PATH中(不是特别推荐)
[root@centos1 calc]# export LD_LIBRARY_PATH=/home/xuejiale/src/calc/lib/:$LD_LIBRARY_PATH
[root@centos1 calc]# ./main
+ is
- is
(3)配置/etc/ld.so.conf文件,增加 /home/xuejiale/src/calc/lib/ 路径,执行 ldconfig -v,并执行main
/home/xuejiale/src/calc/lib/
[root@centos1 calc]# ./main
+ is
- is
3. 优缺点总结
缺点:
- 执行时需要加载动态库,相对而言,比静态库慢
- 发布应用时需要同步发布动态库
优点:
- 执行程序体积小
- 库变更时,一般不需要重新编译应用
动静态库总结:
静态库特点:
- 库的代码会编译进程序里面,所以静态库编译的程序比较大。
- 由静态库编译的程序不用依赖于系统的环境变量,所以环境变量有没有这个库文件,也可以运行。
动态库特点:
- 库的代码不会编译进程序里面,所以动态库编译的程序比较小。
- 由动态库编译的程序依赖于系统的环境变量有没有这个库文件,没有则运行不了。
gcc使用及动静态库制作的更多相关文章
- gcc总结【基本用法】【选项】【动静态库】(转)
1.////////////////////////////////////////////////////////////////////////////////////////////////// ...
- Linux下Gcc生成和使用静态库和动态库详解(转)
一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库. 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不同( ...
- Linux下Gcc生成和使用静态库和动态库详解
参考文章:http://blog.chinaunix.net/uid-23592843-id-223539.html 一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库 ...
- 技巧:Linux 动态库与静态库制作及使用详解
技巧:Linux 动态库与静态库制作及使用详解 标准库的三种连接方式及静态库制作与使用方法 Linux 应用开发通常要考虑三个问题,即:1)在 Linux 应用程序开发过程中遇到过标准库链接在不同 L ...
- 【转】Linux下gcc生成和使用静态库和动态库详解
一.基本概念 1.1 什么是库 在Windows平台和Linux平台下都大量存在着库. 本质上来说,库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不 ...
- Linux下GCC生成和使用静态库和动态库【转】
本文转载自:http://www.cppblog.com/deane/articles/165216.html 一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库. 本 ...
- Linux动静态库
gcc编译过程 预处理,gcc -E,.c->.i 展开宏和头文件,替换条件编译,删除注释.空白和空行 编译, gcc -S,.i -> .s 检查语法规范 [消耗时间和系统资源最多] 汇 ...
- Xcode6.1标准Framework静态库制作方法。工程转Framework,静态库加xib和图片。完美解决方案。
http://www.cocoachina.com/bbs/read.php?tid-282490.html Xcode6.1标准Framework静态库制作方法.工程转Framework,静态库加x ...
- iOS : 静态库制作
一.静态库简介 1. 什么是库? 库 就是程序代码的集合, 是共享程序代码的一种方式 2. 库的分类? 开源库 公开源代码, 能看到具体实现 例如MJExtension, MJRefresh, AFN ...
随机推荐
- vue-devtools的安装与使用
安装 vue.js devtools vue官方中文文档:http://www.uihtm.com/vue/v2/guide/index.html# 安装 vue.js devtools 前提是Goo ...
- 关于MapReduce二次排序的一点解答
上一篇博客说明了怎么自定义Key,而且用了二次排序的例子来做测试,但没有详细的说明二次排序,这一篇说详细的说明二次排序,为了说明曾经一个思想的误区,特地做了一个3个字段的二次排序来说明.后面称其为“三 ...
- maven 安装m2e 报错
Eclipse安装maven插件m2e m2e - http://m2eclipse.sonatype.org/sites/m2e m2e-extras - http://m2eclipse.sona ...
- java 命令查字节码文件, 查.class文件内容
1. 需要用javac,javap命令,所以先配下环境变量 2.配置环境变量 单击“计算机-属性-高级系统设置”,单击“环境变量”.在“系统变量”栏下单击“新建”,创建新的系统环境变量. 3.写需要用 ...
- unix socket服务器
只能处理单个消息,一发一收. int loop(void) { struct sockaddr_un client_addr; int server_socket, client_socket; ...
- 【源码】HashMap源码及线程非安全分析
最近工作不是太忙,准备再读读一些源码,想来想去,还是先从JDK的源码读起吧,毕竟很久不去读了,很多东西都生疏了.当然,还是先从炙手可热的HashMap,每次读都会有一些收获.当然,JDK8对HashM ...
- hdu2054 通过率低是有理由的
这虽然是一道水题,但却巨坑,他题面上不说数据范围,也没有说数据类型,事实就是数据范围巨大,整型实型都有,所以必须用字符串去写,但是又涉及到小数,所以还要删除小数后面多余的0,比如1==1.0000,这 ...
- 关于LinQ中“from"前置的原因
原文地址:http://blog.csdn.net/yuzifen/article/details/6754003 概括来说是:为了IDE的智能感知(Intelisence)功能,(或说为了进行类型推 ...
- 面试-java反射
问题:简述Java中的反射使用 答: 1.作用: 可以通过配置文件来动态配置和加载类,以实现软件工程理论里所提及的类与类,模块与模块之间的解耦.反射最经典的应用是spring框架. 2. 定义 反射简 ...
- 谷歌浏览器导出excel失败问题解决(网上都没解决)
java poi导出excel报了网络错误,信息已经写回到chrome浏览器(IE/FF均无此问题).如下所示: 从chrome的network大小部分也可以看出是正确的. 网上很多答案说将file. ...