【Linux C/C++】 第02讲 HelloWorld程序编译流程详解
2016-05-25 10:04
507 查看
也许你习惯了VC的编译方式,只需要点击一下编译按钮即可,至于VC的编译流程已经被VS封装好了,看到本文之前你可能对详细流程还是一头雾水,通过GCC的编译流程的学习,你可以很好的理解编译过程的各个阶段,下面详细分解一下HelloWorld程序的编译流程细节。
一 HelloWorld.c程序编译流程
1.0 gcc 命令参数
-o 指定输出文件名
-O -O0 -O1 -O2 -O3 编译优化
-g -g0 -g1 -g2 -g3 产生调试信息
-W all error
-Wall 显示所有警告
-Werror 把警告当错误
-w 关闭警告
-c 只编译不链接
-E 预编译
-S 汇编
1.1 预编译 生成.i文件
预编译就是处理头文件包含,将宏替换掉等等预编译指令
HelloWorld.i的内容如下:
1.2 编译 生成.o目标文件
1.3 汇编 生成.s汇编文件
HelloWorld.s内容如下:
1.4 链接 ld
链接器 ld 和 gcc是两个相对的独立的工具(两个exe文件)
gcc负责编译,ld负责将gcc编译生成的.o文件链接
ld的执行和参数指定是自动完成的
二 静态库的编译过程
2.1 编译成目标文件(*.a a是archive的缩写,意为归档)
-static 可选
gcc -c -static 源文件.c
2.2 归档成静态库
ar工具
-r 归档文件 被归档的文件
ar -r 静态库文件.a 被归档文件1.o 被归档文件2.o ...
-t 查看静态库里的目标文件列表
nm工具 -查看函数符号表
nm 动态库/静态库/可执行文件/目标文件
2.3 库的使用
直接指定库名 gcc main.c 静态库.a
-l 指定库名 注意此时的库名必须以lib开头,如libmath.a
-L 指定目录
三 动态库的编译过程
3.1 工具
ldd 查看程序依赖的动态库列表
readelf -h ./a.out 查看可执行文件的头信息,elf是可执行文件格式
3.2 动态库的编译
3.2.1 编译
-c -fpic(可选)
-fpic 是-f(format格式缩写) + pic(position independent code)
3.2.2 链接
-shared
3.3 使用动态库
gcc 代码 动态库名
gcc 代码 -l -L
命名规则
lib库名.so
动态库的加载过程
3.3.1 找到动态库
3.3.2 加载动态库到内存
3.3.3 映射到用户的内存空间
系统对动态库的查找规则
/lib
/usr/lib
export LD_LIBRARY_PATH (是动态库的目录,类似windows下的path)
LD_LIBRARY_PATH 只对当前终端有效
缓冲机制:
linux启动时会把:/lib:/usr/lib:LD_LIBRARY_PATH加载到缓冲
/sbin/ldconfig -v 刷新缓冲中的.so
四 使用libdl.so库
动态库加载的原理
动态库中函数的查找已经封装成函数libdl.so
dlopen 打开一个动态库
dlsym 在打开的动态库查找一个函数
dlclose 关闭动态库
一 HelloWorld.c程序编译流程
#include <stdio.h> int main() { printf("Hello World\n"); return 0; }
1.0 gcc 命令参数
-o 指定输出文件名
-O -O0 -O1 -O2 -O3 编译优化
-g -g0 -g1 -g2 -g3 产生调试信息
-W all error
-Wall 显示所有警告
-Werror 把警告当错误
-w 关闭警告
-c 只编译不链接
-E 预编译
-S 汇编
1.1 预编译 生成.i文件
预编译就是处理头文件包含,将宏替换掉等等预编译指令
HelloWorld.i的内容如下:
1.2 编译 生成.o目标文件
1.3 汇编 生成.s汇编文件
HelloWorld.s内容如下:
1.4 链接 ld
链接器 ld 和 gcc是两个相对的独立的工具(两个exe文件)
gcc负责编译,ld负责将gcc编译生成的.o文件链接
ld的执行和参数指定是自动完成的
二 静态库的编译过程
2.1 编译成目标文件(*.a a是archive的缩写,意为归档)
-static 可选
gcc -c -static 源文件.c
//lib1.c int add(int a,int b) { return a+b; } //lib2.c int sub(int a,int b) { return a-b; } //main.c int main() { int r = add(1,2); int s = sub(2,1); }先生成*.o文件,再归档
2.2 归档成静态库
ar工具
-r 归档文件 被归档的文件
ar -r 静态库文件.a 被归档文件1.o 被归档文件2.o ...
-t 查看静态库里的目标文件列表
nm工具 -查看函数符号表
nm 动态库/静态库/可执行文件/目标文件
2.3 库的使用
直接指定库名 gcc main.c 静态库.a
-l 指定库名 注意此时的库名必须以lib开头,如libmath.a
-L 指定目录
三 动态库的编译过程
3.1 工具
ldd 查看程序依赖的动态库列表
readelf -h ./a.out 查看可执行文件的头信息,elf是可执行文件格式
3.2 动态库的编译
3.2.1 编译
-c -fpic(可选)
-fpic 是-f(format格式缩写) + pic(position independent code)
3.2.2 链接
-shared
3.3 使用动态库
gcc 代码 动态库名
gcc 代码 -l -L
命名规则
lib库名.so
动态库的加载过程
3.3.1 找到动态库
3.3.2 加载动态库到内存
3.3.3 映射到用户的内存空间
系统对动态库的查找规则
/lib
/usr/lib
export LD_LIBRARY_PATH (是动态库的目录,类似windows下的path)
LD_LIBRARY_PATH 只对当前终端有效
缓冲机制:
linux启动时会把:/lib:/usr/lib:LD_LIBRARY_PATH加载到缓冲
/sbin/ldconfig -v 刷新缓冲中的.so
四 使用libdl.so库
动态库加载的原理
动态库中函数的查找已经封装成函数libdl.so
dlopen 打开一个动态库
dlsym 在打开的动态库查找一个函数
dlclose 关闭动态库
#include <dlfcn.h> int main() { void* handle = dlopen("./libmath.so",LD_LAZY); int(* func)(int,int) = dlsym(handle,"add"); int ret = func(1,2); dlclose(handle); return 0; }
相关文章推荐
- Linux socket 初步
- Linux Kernel 4.0 RC5 发布!
- linux lsof详解
- linux 文件权限
- Linux 执行数学运算
- 10 篇对初学者和专家都有用的 Linux 命令教程
- Linux 与 Windows 对UNICODE 的处理方式
- Ubuntu12.04下QQ完美走起啊!走起啊!有木有啊!
- 解決Linux下Android开发真机调试设备不被识别问题
- 运维入门
- 运维提升
- Linux 自检和 SystemTap
- Ubuntu Linux使用体验
- c语言实现hashmap(转载)
- Linux 信号signal处理机制
- linux下mysql添加用户
- Scientific Linux 5.5 图形安装教程
- Linux 下无损图片压缩小工具介绍