用GCC完成各项指令操作
一.用gcc生成.a静态库和.so动态库
例一
第 1 步:编辑生成例子程序 hello.h、hello.c 和 main.c
在Linux系统(Ubuntu)下,用vim指令生成文件hello.h、hello.c 和 main.c
第 2 步:将hello.c编译成.o文件
无论静态库,还是动态库,都是由.o 文件创建的。因此,我们必须将源程序 hello.c 通过 g cc 先编译成.o 文件。在系统提示符下键入以下命令得到 hello.o 文件。
我们运行 ls 命令看看是否生存了 hello.o 文件。
在 ls 命令结果中,我们看到了 hello.o 文件。
第 3 步:由.o 文件创建静态库
静态库文件名的命名规范是以 lib 为前缀,紧接着跟静态库名,扩展名为.a。例如:我们将 创建的静态库名为 myhello,则静态库文件名就是 libmyhello.a。在创建和使用静态库时, 需要注意这点。创建静态库用 ar 命令。在系统提示符下键入以下命令将创建静态库文件 libmyhello.a。
ar -crv libmyhello.a hello.o
第 4 步:在程序中使用静态库
在程序 main.c 中,我们包含了静态库的头文件 hello.h,然后在主程序 main 中直接调用 公用函数 hello。下面先生成目标程序 hello,然后运行 hello 程序
gcc -o hello main.c -L. –lmyhello
第 5 步:由.o 文件创建动态库文件
动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀 lib,但其 文件扩展名为.so。
gcc -shared -fPIC -o libmyhello.so hello.o
第 6 步:在程序中使用动态库
在程序中使用动态库和使用静态库完全一样,也是在使用到这些公用函数的源程序中包含 这些公用函数的原型声明,然后在用 gcc 命令生成目标文件时指明动态库名进行编译。我 们先运行 gcc 命令生成目标文件。
gcc -o hello main.c -L. -lmyhello
接下来运行hello会出错,找不到动态库文件 libmyhello.so。程序在运行时, 会在/usr/lib 和/lib 等目录中查找需要的动态库文件。若找到,则载入动态库,否则将提 示类似上述错误而终止程序运行。我们将文件 libmyhello.so 复制到目录/usr/lib 中。
mv libmyhello.so /usr/lib
这里再运行hello结果就正确了。
例二
1.静态库.a 文件的生成与使用。
同例一一样用vim命令新建四个文件 A1.c 、 A2.c、 A.h、 test.c。
生成目标文件A1.o,A2.o
gcc -c A1.c A2.c
生成静态库.a 文件
ar crv libafile.a A1.o A2.o
使用.a 库文件,创建可执行程序(若采用此种方式,需保证生成的.a 文件与.c 文件保 存在同一目录下,即都在当前目录下)
gcc -o test test.c libafile.a
./test
2.共享库.so 文件的生成与使用
生成目标文件(xxx.o() 此处生成.o 文件必须添加"-fpic"(小模式,代码少),否则在生成.so 文件时会出错)
gcc -c -fpic A1.c A2.c
生成共享库.so 文件
gcc -shared *.o -o libsofile.so
使用.so 库文件,创建可执行程序
gcc -o test test.c libsofile.so
./test
发现出现错误: ./test: error while loading shared libraries: libsofile.so: cannot open shared object file: No such file or directory
运行 ldd test
这是由于 linux 自身系统设定的相应的设置的原因,即其只在/lib and /usr/lib 下搜索对应 的.so 文件,故需将对应 so 文件拷贝到对应路径。
sudo cp libsofile.so /usr/lib
./test
作业练习
在上次作业的基础上再添加一个sub1.c文件,main函数代码将调用x2x和x2y
1.将这3个函数分别写成单独的3个 .c文件,并用gcc分别编译为3个.o 目标文件
2.将x2x、x2y目标文件用 ar工具生成1个 .a 静态库文件
3.用 gcc将 main函数的目标文件与此静态库文件进行链接,生成最终的可执行程序,记录文件的大小
gcc -o main1 main1.c libsubfile.a
文件大小
将x2x、x2y目标文件用 ar工具生成1个 .so 动态库文件, 然后用 gcc将 main函数的目标文件与此动态库文件进行链接,生成最终的可执行程序,记录文件的大小,并与之前做对比
文件大小
二.Linux GCC 常用命令
在这我们先创建一个新的test.c文件,源代码如下
#include <stdio.h>
int main(void) {
printf("Hello World!\n");
return 0;
}
这个程序,一步到位的编译指令是:
gcc test.c -o test
实质上,上述编译过程是分为四个阶段进行的,即预处理(也称预编译,Preprocessing)、编译 (Compilation)、汇编 (Assembly)和连接(Linking)。
1.预处理
gcc -E test.c -o test.i 或 gcc -E test.c
我们发现文件夹中多了个.i文件,gcc 的-E 选项,可以让编译器在预处理后停止,并输出预处理结果。在本例中,预处理结果就是将 stdio.h 文件中的内容插入到 test.c 中了。
2.编译为汇编代码
预处理之后,可直接对生成的 test.i 文件编译,生成汇编代码:
gcc -S test.i -o test.s
3.汇编
gcc -c test.s -o test.o
4.链接
gcc test.o -o test
nasm汇编编译器编译生成执行程序
文件大小对比
Linux 系统中终端程序最常用的光标库(curses)的主要函数功能
curses是一个在Linux/Unix下广泛应用的图形函数库,作用是可以在终端内绘制简单的图形用户界面。
curses使用两个数据结构映射终端屏幕,stdscr和curscr。
stdscr是“标准屏幕”(逻辑屏幕),在curses函数库产生输出时就刷新,是默认输出窗口(用户不会看到该内容)。
curscr是“当前屏幕”(物理屏幕),在调用refresh函数是,函数库会将curscr刷新为stdscr的样子。
月球游戏
总结
本次作业总的来说不是很难,但是比较繁琐,很多代码指令都还不熟悉,还需要多练。