1 编译C程序
1.1 编译单个C文件
$ gcc -Wall hello.c -o hello
一定加上-Wall显示警告信息,并修改代码重复编译直到消除所有warning(C/C++是很不安全的)。
1.2 编译多个文件
$ gcc -Wall main.c hello_fn.c -o newhello
无需指定.h文件
1.3 分别编译
1.3.1 编译
$ gcc -Wall -c main.c
$ gcc -Wall -c hello_fn.c
此处不需加-o选项,会根据filename.c自动生成对应的filename.o文件
1.3.2 链接
$ gcc main.o hello_fn.o -o hello
链接时无需加-Wall选项
1.3.2 目标文件的链接顺序
传统编译器、链接器是从指定.o文件中从左到右搜索外部函数的。这要求定义函数的目标文件要出现在调用函数的目标文件之后
$ gcc main.o hello_fn.o -o hello (correct order)
$ cc hello_fn.o main.o -o hello (incorrect order)
main.o: In function ‘main’:
main.o(.text+0xf): undefined reference to ‘hello’
现在很多编译器没有顺序的约束,但为了保证可移植性,最好还是按照上述顺序写目标文件。
1.4 链接静态库文件
可以在编译时直接指定要链接的库文件
$ gcc -Wall calc.c /usr/lib/libm.a -o calc
可用如下简略形式避免输入长文件路径
$ gcc -Wall calc.c -lm -o calc
注意:链接外部库时也存在1.3.2中提到的顺序问题
1.5 设置搜索路径
1.5.1 搜索路径例子
默认情况gcc会从如下目录中顺序搜索头文件和库文件
/usr/local/include/
/usr/include/
/usr/local/lib/
/usr/lib/
当引用第三方库时,头文件和库文件常常不在以上目录中。此时需用如下方法指定搜索路径
$ gcc -Wall -I/opt/gdbm-1.8.3/include -L/opt/gdbm-1.8.3/lib dbmain.c -lgdbm
1.5.2 环境变量
可通过编辑.bash_profile在用户登录时自动设置环境变量
$ C_INCLUDE_PATH=$HOME/usr/include
$ export C_INCLUDE_PATH
$ CPLUS_INCLUDE_PATH=$HOME/usr/include
$ export CPLUS_INCLUDE_PATH
$ LIBRARY_PATH=$HOME/usr/lib
$ export LIBRARY_PATH
此时搜索顺序是:-I或-L指定的路径、环境变量中的路径、gcc默认搜索路径
1.5.3 指定多个搜索路径
通过设置环境变量
$ C_INCLUDE_PATH=.:/opt/gdbm-1.8.3/include:/net/include
$ LIBRARY_PATH=.:/opt/gdbm-1.8.3/lib:/net/lib
通过命令行
$ gcc -I. -I/opt/gdbm-1.8.3/include -I/net/include -L. -L/opt/gdbm-1.8.3/lib -L/net/lib .....
此时搜索顺序同1.5.2
1.6 链接动态库文件
大部分系统中gcc编译器默认使用动态库,当用-lNAME选项时,若libNAME.so与libNAME.a同时存在,gcc优先使用.so文件。
依赖于动态库的可执行文件执行时同样存在一个搜索路径的问题。一般系统默认从/usr/lib /usr/local/lib中搜索动态库,若找不到则会出现如下的类似错误
./a.out: error while loading shared libraries: libgdbm.so.3:
cannot open shared object file: No such file or directory
需要把动态库文件加到加载路径中,依赖于动态库的可执行文件才能运行,方法是修改环境变量LD_LIBRARY_PATH(mac下是DYLD_LIBRARY_PATH)
$ LD_LIBRARY_PATH=/opt/gdbm-1.8.3/lib
$ export LD_LIBRARY_PATH
同样可将此脚本加到.bash_profile中在用户登录时自动初始化该环境变量
系统管理员可通过修改/etc/profile来修改所有用户的环境变量,GNU系统中还可修改/etc/ld.so.conf
若要强制使用静态库,可通过gcc的-static选项实现
$ gcc -Wall -static -I/opt/gdbm-1.8.3/include/ -L/opt/gdbm-1.8.3/lib/ dbmain.c -lgdbm
也可通过直接给定库文件的完整路径、完整文件名来指定使用动态库还是静态库
$ gcc -Wall -I/opt/gdbm-1.8.3/include dbmain.c /opt/gdbm-1.8.3/lib/libgdbm.a<span style="white-space:pre"> </span>使用静态库
$ gcc -Wall -I/opt/gdbm-1.8.3/include dbmain.c /opt/gdbm-1.8.3/lib/libgdbm.so<span style="white-space:pre"> </span>使用动态库
参考资料: