准备工作
Xshell(支持SSH协议,远程控制终端)
gcc
GCC原名为 GNU C Complier
GNU C Collection GUN编译套件,包括了多种语言前端和相关语言的库
-
关于gcc和g++
在编译阶段,g++会调用gcc,其实对于c++程序,两者等价,但是gcc命令不能自动和c++程序使用的库链接,所以为了统一,编译/链接都用g++。所以cpp程序也是可以用g++的。
-
例:比如运行 gcc -S main.c -o main.s,相当于同时进行了预处理、编译两步
不带参数: gcc main.c -o test 进行预处理、编译、汇编、链接。 -
gcc不能自动和c++程序用的库链接,通常用g++链接,统一起见,编译+链接都用g++。
-
gcc -D 可以指定宏,可以用来打断点调试比如以下代码
#include <stdio.h>
int main() {
printf("HELLO WORLD\n");
#ifdef DEBUG
printf("debug1\n");
#endif
return 0;
}
gcc main.c -o test -D DEBUG
会输出debug1
- gcc -I(大写的i,制定头文件的位置) -l(小写的L,制定库 的名字,注意不是库文件的名字,是库名字) -L(指定库文件的位置)
静态库制作
- linux下静态库命名规则:libxxx.a
lib:前缀
xxx:库的名字,自己起
.a : 固定后缀
实现:
(1)gcc -c 编译生成.o可执行文件
(2)用archive工具打包成库,注意linux下库名字固定为libxxx.a,其中xxx是库名字。
然后可以编译main.c了,注意必须指定库的位置(-L)和名字(-l)
gcc main.c -o app -L ./ -l calc
注意,gcc默认再当前的目录下自动去找.h头文件,若不在当前目录需要-I指定位置。另外不需要显示的把头文件放到命令中,如gcc main.c head.n div.c -o app.有文件是在预编译中根据路径自动替换的。
动态库制作
- 与静态库的区别,GCC进行链接时,会把静态库代码打包到可执行程序中。但是对于动态库,链接时动态库代码不会被打包到可执行程序,只是加载相关信息,程序启动后,动态库会被动态加载到内存中。系统加载可执行程序时,由ld-linux.so获取动态库绝对路径,会到环境变量中去找,找到后,再加载到内存去。
系统加载共享库需要知道绝对路径,还需要将动态库相关位置信息加入环境变量
方法:将动态库所在路径加入LD_LIBRARY_PATH环境变量
冒号是拼接符
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/xdy/linux/lesson06/library/lib
在使用 echo $LD_LIBRARY_PATH 就能查看已经把环境变量加入。
ok,接下来试一下
gcc main.c -o app -I ./include/ -l calc -L ./lib/
这样就生成可执行文件app了
makefile
指定那些先编译、哪些后编译、重新编译等,自动化编译。
app:main.c,sub.c
gcc main.c sub.c -o app
其他的规则都是为第一条服务,以上等同于
app:main.c a.c b.c
$(CC) -c $^ -o $@
或者
app:main.o,sub.o
gcc main.o,sub.o
main.o:main.c
gcc -c main.c -o main.o
sub.o:sub.c
gcc -c main.c -o sub.o
或者
#定义变量
src = $(wildcard ./*.o)
target = app
$(target):$(src)
$(CC) $(src) -o $(target)
%.o:%.c
$(CC) -c $< -o $@
后者效率更高,因为若有main.c 或者 sub.c 单独更新,makefile单独编译相关的文件即可,不用像前者需要重新把两个文件都编译一遍。这个是通过makefile时间检测原理实现:若依赖时间晚于目标时间,需要重新生成目标。
gdb
gcc -g -Wall program.c -0 program
-g的作用主要是在可执行文件中加入源代码相关信息,比如可执行文件第几条机器指令对应源代码第几行,调试时需要gdb能找到源文件。
- 打断点