常用指令
直接编译为可执行
gcc main.c -o main
多个程序文件的编译
gcc main1.c main2.c -o main
加入调试选项 -g -ggdb(gdb调试专用)
gcc -ggdb main.c -o main
预处理
gcc -E main.c -o main.i
gcc的-E选项,可以让编译器在预处理后停止,并输出预处理结果。
编译为汇编代码
预处理之后,可直接对生成的test.i文件编译,生成汇编代码:
gcc -S main.i -o main.s
gcc的-S选项,表示在程序编译期间,在生成汇编代码后,停止,-o输出汇编代码文件。
汇编
对于上文中生成的汇编代码文件test.s,gas汇编器负责将其编译为目标文件,如下:
gcc -c main.s -o main.o
连接
gcc连接器是gas提供的,负责将程序的目标文件与所需的所有附加的目标文件连接起来,最终生成可执行文件。附加的目标文件包括静态连接库和动态连接库。
对于上面生成的main.o,将其与C标准输入输出库进行连接,最终生成可执行程序main。
gcc main.0 -0 main
检错
参数-Wall,使用它能够使GCC产生尽可能多的警告信息。
gcc -Wall main.c -o main
在编译程序时带上-Werror选项,那么GCC会在所有产生警告的地方停止编译,迫使程序员对自己的代码进行修改,如下:
gcc -Werrormain.c -o main
创建动态链接库
生成o文件
gcc -c -fPIC add.c //这里一定要加上-fPIC选项,目的使库不必关心文件内函数位置
再编译
gcc -shared -fPIC -o libadd.so add.o
库文件连接
开发软件时,完全不使用第三方函数库的情况是比较少见的,通常来讲都需要借助许多函数库的支持才能够完成相应的功能。从程序员的角度看,函数库实际上就是一些头文件(.h)和库文件(so、或lib、dll)的集合。虽然Linux下的大多数函数都默认将头文件放到/usr/include/目录下,而库文件则放到/usr/lib/目录下;但也有的时候,我们要用的库不在这些目录下,所以GCC在编译时必须用自己的办法来查找所需要的头文件和库文件。
额外补充:Linux需要连接so库文件(带软连接),可以完完整整的复制到/usr/include/或/usr/lib/目录下,使用 cp -d * /usr/lib/ 命令,然后别忘记再运行 ldconfig。
其中inclulde文件夹的路径是/home/test/include,lib文件夹是/home/test/lib,lib文件夹中里面包含二进制so文件libtest.so
首先要进行编译main.c为目标文件,这个时候需要执行:
gcc –c –I /home/test/include main.c –o main.o
最后把所有目标文件链接成可执行文件:
gcc –L /home/test/lib -ltest main.o –o main
默认情况下, GCC在链接时优先使用动态链接库,只有当动态链接库不存在时才考虑使用静态链接库,如果需要的话可以在编译时加上-static选项,强制使用静态链接库。
gcc –L /home/test/lib -static -ltest main.o –o main
静态库链接时搜索路径顺序:
- ld会去找GCC命令中的参数-L
- 再找gcc的环境变量LIBRARY_PATH
- 再找内定目录 /lib、 /usr/lib、 /usr/local/lib 这是当初compile gcc时写在程序内的
动态链接时、执行时搜索路径顺序:
- 编译目标代码时指定的动态库搜索路径
- 环境变量LD_LIBRARY_PATH指定的动态库搜索路径
- 配置文件/etc/ld.so.conf中指定的动态库搜索路径
- 默认的动态库搜索路径/lib
- 默认的动态库搜索路径/usr/lib
相关环境变量:
- LIBRARY_PATH环境变量:指定程序静态链接库文件搜索路径
- LD_LIBRARY_PATH环境变量:指定程序动态链接库文件搜索路径