1. 实验记录
实验任务1
使用上述三种编译方法,对/notebooks/workspace目录下的bubbleSort.c, insertSort.c, selectSort.c, sort.c, sort.h进行编译(其中,sort.c是主程序,sort.h是头文件,其他的三个c程序分别实现了主程序需要用到的3个函数),写出步骤和结果。
第一种方法:直接使用如下命令行一次完成编译、链接过程
cd /notebooks/workspace
gcc bubbleSort.c insertSort.c selectSort.c sort.c -o sort
bubbleSort.c、insertSort.c、selectSort.c和sort.c的后缀名(.c)指明了调用c编译器,gcc是GCC的众多编译器的统一入口,gcc靠后缀名决定调用什么编译器,-o 参数指定了可执行文件的文件名为sort。
用ls检查一下生成的可执行文件:
ls
运行可执行程序:./sort
为了避免跟下一种方法混淆,使用rm命令删除这种方法生成的可执行文件:rm sort。
第二种方法:编译bubbleSort.c、insertSort.c、selectSort.c为静态库,编译sort.c时指定静态库的位置。
步骤一:需要将bubbleSort.c、insertSort.c、selectSort.c编译成中间文件bubbleSort.o、insertSort.o、selectSort.o,使用如下命令行:
gcc -c bubbleSort.c insertSort.c selectSort.c
ls
可以看到已经生成了bubbleSort.o、insertSort.o、selectSort.o文件
步骤二:生成静态库文件,添加 bubbleSort.o、insertSort.o和selectSort.o到静态库中,使用如下命令行:
ar -r libsort.a bubbleSort.o insertSort.o selectSort.o
ls
可见,bubbleSort.o、insertSort.o和selectSort.o已生成。
命令行中,-r libsort.a参数表示建立静态库,名字为libsort.a。
步骤三:使用如下命令行生成可执行程序
gcc sort.c libcalc.a -o sort
ls
生成了可执行文件sort。使用rm命令删除静态库libsort.a和可执行文件sort。
第三种方法:建立共享库,编译时指定共享库。
步骤一:使用如下命令编译bubbleSort.c、insertSort.c和selectSort.c为bubbleSort.o、insertSort.o和selectSort.o:
gcc -c -fpic bubbleSort.c insertSort.c selectSort.c
ls
命令行中,-fpic指定bubbleSort.o、insertSort.o和selectSort.o为可重分配地址属性,pic是position independence code的缩写。
步骤二:使用bubbleSort.o、insertSort.o和selectSort.o生成共享库sort.so,命令如下:
gcc -shared bubbleSort.o insertSort.o selectSort.o -o sort.so
步骤三:编译sort.c,链接生成的共享库,使用命令如下:
gcc sort.c sort.so -o sort
在命令行窗口中运行新生成的该程序(sort)会发生错误,提示为:
.sort:error while loading shared libraries: sort.so: cannot open shared object file: No such file or directory。
原因是:共享库编译的sort程序执行时需要加载共享库sort.so,而步骤一和步骤二生成的共享库sort.so不在系统默认的共享库搜索路径中,所以错误提示为共享库sort.so不存在。
通过如下命令指明共享库的搜索路径为sort.so所在的当前目录:
export LD_LIBRARY_PATH=`pwd`
再次运行新生成的该程序sort,则可以正常运行。
实验任务3
请根据7.3讲述的Makefile的写法,为/notebooks/workspace目录下的bubbleSort.c, insertSort.c, selectSort.c, sort.c, sort.h编写Makefile文件,要求至少包括all和clean目标。
1、先编辑Makefile文件,命令如下:
all:sortapp #我们使用的是sort文件,不是main,所以用的是sortapp
sortapp:sort.o bubbleSort.o insertSort.o selectSort.o
gcc -o [email protected] $^
sort.o:sort.c bubbleSort.h insertSort.h selectSort.h
gcc -c $<
bubbleSort.o:bubbleSort.c bubbleSort.h
gcc -c $<
insertSort.o:insertSort.c insertSort.h
gcc -c $<
selectSort.o:selectSort.c selectSort.h
gcc -c $<
clean:
rm sortapp sort.o bubbleSort.o insertSort.o selectSort.o 3>/dev/null
为了简化Makefile,可以使用特定的变量[email protected],$^,$<,它们的含义为:
[email protected] 目标文件
$^ 所有的依赖文件
$< 第一个依赖文件
2、再编辑头文件bubbleSort.h、insertSort.h和selectSort.h,命令如下:(下面的分号是写在文件中的,不是分行)
void BubbleSort(int A[],int N);
void InsertionSort(int A[],int N);
void SelectSort(int A[],int N); #使用cat bubbleSort.c来查看函数
编辑文件如下:
3、直接使用make -f Makefile
4、使用make -f Makefile clean删除所有目标文件。因为all目标依赖对象是sortapp,所以执行该目标可以完成编译.
2. 思考题回答
源代码级别的调试和二进制级别的调试有什么区别?
(写错了)
3. 实验体会
通过实验任务1,知道有三种使用gcc编译的方法:(以实验为例)
一:直接使用如下命令行一次完成编译、链接过程:
cd /notebooks/workspace #先切换到文件所在目录
gcc bubbleSort.c insertSort.c selectSort.c sort.c -o sort #直接将.c文件改成.o文件,并放入sort中
二:编译bubbleSort.c、insertSort.c、selectSort.c为静态库,编译sort.c时指定静态库的位置。
(1)使用如下命令行:
gcc -c bubbleSort.c insertSort.c selectSort.c
将bubbleSort.c、insertSort.c、selectSort.c编译成中间文件 bubbleSort.o、insertSort.o、selectSort.o。
(2)使用如下命令行:
ar -r libsort.a bubbleSort.o insertSort.o selectSort.o
生成静态库文件libsort.a,同时添加 bubbleSort.o、insertSort.o和selectSort.o到静态库中。
(3)使用命令行gcc sort.c libcalc.a -o sort生成可执行程序。
三、建立共享库,编译时指定共享库。
(1)使用如下命令:
gcc -c -fpic bubbleSort.c insertSort.c selectSort.c。
编译bubbleSort.c、insertSort.c和selectSort.c为bubbleSort.o、insertSort.o和selectSort.o。
(2)使用如下命令:
gcc -shared bubbleSort.o insertSort.o selectSort.o -o sort.so
生成共享库sort.so。
(3)使用命令如下:gcc sort.c sort.so -o sort,编译sort.c,链接生成的共享库。
共享库编译的sort程序执行时需要加载共享库sort.so,而(1)和(2)生成的共享库sort.so不在系统默认的共享库搜索路径中,所以错误提示为共享库sort.so不存在。
通过如下命令指明共享库的搜索路径为sort.so所在的当前目录即可:
export LD_LIBRARY_PATH=`pwd`
通过实验任务3,知道怎么编写Makefile文件使其自动编译。先查看目录下所要编写的文件有哪些,没有头文件还需要根据.c文件中函数的函数名编辑头文件。
Makefile文件由“依赖关系+规则”部分组成(即首字母靠行起始对齐的部分,“规则”部分根据情况可不写)。如下:
sortapp:sort.o bubbleSort.o insertSort.o selectSort.o
gcc -o sortapp sort.o bubbleSort.o insertSort.o selectSort.o
该部分中,“依赖关系”为“sortapp:sort.o bubbleSort.o insertSort.o selectSort.o”,即目标为“sortapp”,依赖对象为sort.o bubbleSort.o insertSort.o和selectSort.o,目标对象和依赖对象均为文件,表明当依赖对象sort.o bubbleSort.o insertSort.o和selectSort.o比目标文件sortapp新的时候(即依赖对象发生改变),执行紧接着的“规则”的命令,也就是“gcc -c [email protected] $^”,注意:“规则”前面有一个TAB间隔。
为了简化Makefile,可以使用特定的变量[email protected],$^,$<,它们的含义为:新的时候
[email protected] 目标文件
$^ 所有的依赖文件
$< 第一个依赖文件
也知道了使用make -f Makefile clean会删除所有目标文件,但因为all目标依赖对象是sortapp,所以执行该目标仍可以完成编译。