linux环境下的编译器gcc
gcc:
-o 编译链接生成可执行文件
-O -O1 -O2 -O3 编译优化
-g -g1 -g2 -g3 产生调试信息至可执行文件
-w 关闭所有的警告
-W all,error -Wall显示所有的警告 -Werror把所有的警告当错误
-c 编译生成目标文件 不链接
-E 预编译
-S 编译成汇编
-D 在命令行中添加宏定义
-x 指定语言的编译类型 gcc -x c xxxx.c gcc -x assembler xxx.s
-std=c89 -std=c99指定语言的编译标准
注意:gcc编译器自动调用链接器ld
restrict关键字 int add( int* restrict a){}优化编译器的编译,函数参数中的指针指向的值放在寄存器中,提高效率,在c99中支持,c89不支持
接下来讲很好玩的静态库的编译
通常我们需要调用很多库编译,简单例子
写一个 add.c 存 int add(int a,int b){return a+b;}
写一个sub.c 同理存减法函数
写一个main.c 调用add,sub
编译 gcc main.c add.c sub.c ====> a.out
当我们的文件写的很多时,就显得很不便,就有了静态库的生成
第一步:编译成目标文件
gcc -c -static add.c ====》 目标文件add.o
gcc -c -static sub.c=====> 目标文件sub.o
第二步:归档成静态库
ar工具来了
-r ar -r ku.a add.o sub.o ===》把目标文件归档成静态库ku.a
-t ar -t ku.a 显示你的静态库含有哪些目标文件
nm工具(查看函数符号的功能)
nm 目标文件/可执行文件/静态库/动态库
小应用:***** 使用gcc静态库,输入一个菱形半径,打印菱形
1.写一个半径输入库封装IOinput库
2.写一个菱形的打印库封装graphics库
计划: 1.实现输入 2.实现菱形 3.编译成静态库 4.调用静态库
很好玩的~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
动态库:
141 四.动态库的编译
142 1.什么是动态库?(共享库)
143 动态库是可以执行,静态库不能执行
144 但动态库没有main,不能独立执行
145 动态库不会链接成程序的一部分。
146 程序执行的时候,必须需要动态库文件。
147 2.工具
148 ldd 查看程序需要调用的动态库
149 ldd 只能查看可执行文件
150 readelf -h a.out linux下的可执行文件为elf,最初始unix是a.out
151
152 readelf -h 查看执行程序的头
153 nm查看库中的函数符号
154 3.动态库的编译
155 3.1.编译
156 -c -fpic(可选)
157 3.2.链接
158 -shared //
159 4.调用动态库
160 gcc 代码 动态库名
161 gcc 代码 -l库名 -L动态库所在的路径
step 1: gcc -c -fpic iotool.c ===>iotool.o
step2: gcc -c fpic graphics.c====>graphics.o
step3: gcc -shared -olibdemo1.so iotool.o graphics.o ======>生成动态库libdemo1.so
step4: gcc main.c -ldemo1 -L. -omain ======>链接当前目录下的动态库 生成可执行文件main
164 问题:
165 4.1.执行程序怎么加载到动态库?
166 4.2.动态库没有作为执行程序的一部分,为什么链接需要指定动态库以及目录呢?
167 连接器需要确定函数在动态库中的位置
168
169
170 动态库的加载:
171 1.找到动态库
172 2.加载动态库到内存
173 3.映射到用户的内存空间
174 系统对动态库的查找规则:
175 /lib
176 /usr/lib
177
178 到环境变量LD_LIBRARY_PATH指定的路径中查找
179 export LD_LIBRARY_PATH=.:说明动态库文件路径