
在前一篇的GetStarted里,我们提到了Linux下的C编程离不开编译(Compile)、链接(Link),还有调试(Debug)。
现在我们重点来说一下,怎么在不依赖集成开发环境(IDE)的情况下,使用GCC编译器进行C编程。
Hello World的C语言源代码:
1 2 3 4 5 6 7 |
#include<stdio.h> int main() { printf("Hello World\n"); return 0; } |
GCC编译
1 |
gcc helloworld.c |
运行
1 2 3 4 |
$ ./a.out // “./”表示执行当前目录下的可执行文件或脚本程序 // gcc默认创建一个a.out文件 |
GCC编译器
GCC(GNU Compiler Collection,GNU编译器套装),是一套由GNU开发的编程语言编译器。它是一套以GPL及LGPL许可证所发行的自由软件,也是GNU计划的关键部分,亦是自由的类Unix及苹果计算机Mac OS X操作系统的标准编译器。GCC(特别是其中的C语言编译器)也常被认为是跨平台编译器的事实标准。
GCC 原名为GNU C语言编译器(GNU C Compiler),因为它原本只能处理C语言。GCC很快地扩展,变得可处理 C++。之后也变得可处理 Fortran、Pascal、Objective-C、Java, 以及 Ada 与其他语言。原本用C开发,后来因为LLVM、Clang的崛起,令GCC更快将开发语言转换为C++。
基本语法
1 2 |
gcc [options] [filenames] //options为编译选项,filenames为需要编译的文件名 |
GCC提供的编译选项超过100个,但只有少数几个会被频繁使用。
常用的编译命令
简单编译:
1 2 |
//一步到位的编译指令 gcc helloworld.c -o helloworld |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
//详细编译过程 //1.预处理 gcc -E helloworld.c -o helloworld.i //或 gcc -E helloworld.c //helloworld.i文件中存放着helloworld.c经预处理之后的代码。 //后面那条指令,是直接在命令行窗口中输出预处理后的代码. //gcc的-E选项,可以让编译器在预处理后停止,并输出预处理结果。 //2.编译为汇编代码(Compilation) gcc -S helloworld.i -o helloworld.s //预处理之后,可直接对生成的helloworld.i文件编译,生成汇编代码。 //gcc的-S选项,表示在程序编译期间,在生成汇编代码后,停止,-o输出汇编代码文件。 //3.汇编(Assembly) gcc -c helloworld.s -o helloworld.o //对于生成的汇编代码文件helloworld.s,gas汇编器负责将其编译为目标文件。 //4.连接(Linking) gcc helloworld.o -o helloworld //gcc连接器是gas提供的,负责将程序的目标文件与所需的所有附加的目标文件连接起来. //最终生成可执行文件。附加的目标文件包括静态连接库和动态连接库。 //对于上面生成的helloworld.o,将其与C标准输入输出库进行连接. //最终生成程序helloworld //5.运行(Run) $ ./helloworld.out //./表示执行当前目录下的可执行文件或脚本程序 |
1 2 3 4 5 6 7 8 9 10 11 12 |
//多个程序文件的编译 //通常整个程序是由多个源文件组成的,相应地也就形成了多个编译单元。 //使用GCC能够很好地管理这些编译单元。 //假设有一个由helloworld1.c和helloworld2.c两个源文件组成的程序。 //为了对它们进行编译,并最终生成可执行程序helloworld,可以使用下面这条命令: gcc helloworld1.c helloworld2.c -o helloworld //以上命令可以分解成 gcc -c helloworld1.c -o helloworld1.o gcc -c helloworld2.c -o helloworld2.o gcc helloworld1.o helloworld2.o -o helloworld |
检错
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
gcc -pedantic helloworld.c -o helloworld //-pedantic编译选项并不能保证被编译程序与ANSI/ISO C标准的完全兼容。 //它仅仅只能用来帮助Linux程序员离这个目标越来越近。 //或者换句话说,-pedantic选项能够帮助程序员发现一些不符合 ANSI/ISO C标准的代码。 //但不是全部,事实上只有ANSI/ISO C语言标准中要求进行编译器诊断的那些情况,才有可能被GCC发现并提出警告。 //除了-pedantic之外,GCC还有一些其它编译选项也能够产生有用的警告信息。 //这些选项大多以-W开头,其中最有价值的当数-Wall了,使用它能够使GCC产生尽可能多的警告信息。 gcc -Wall helloworld.c -o helloworld //GCC给出的警告信息虽然从严格意义上说不能算作错误,但却很可能成为错误的栖身之所。 //一个优秀的Linux程序员应该尽量避免产生警告信息,使自己的代码始终保持标准、健壮的特性。 //所以将警告信息当成编码错误来对待,是一种值得赞扬的行为! //在编译程序时带上-Werror选项,那么GCC会在所有产生警告的地方停止编译,迫使程序员对自己的代码进行修改。 gcc -Werror helloworld.c -o helloworld |
库文件连接
开发软件时,完全不使用第三方函数库的情况是比较少见的,通常来讲都需要借助许多函数库的支持才能够完成相应的功能。从程序员的角度看,函数库实际上就是一些头文件(.h)和库文件(so、或lib、dll)的集合。。虽然Linux下的大多数函数都默认将头文件放到/usr/include/目录下,而库文件则放到/usr/lib/目录下;Windows所使用的库文件主要放在Visual Stido的目录下的include和lib,以及系统文件夹下。但也有的时候,我们要用的库不再这些目录下,所以GCC在编译时必须用自己的办法来查找所需要的头文件和库文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
//例子: //我们的程序test.c是在linux上使用c连接mysql,这个时候我们需要去mysql官网下载 //MySQL Connectors的C库,下载下来解压之后,有一个include文件夹,里面包含 //mysql connectors的头文件,还有一个lib文件夹,里面包含二进制so文件libmysqlclient.so //其中inclulde文件夹的路径是/usr/dev/mysql/include //lib文件夹是/usr/dev/mysql/lib //1.编译成可执行文件,编译test.c为目标文件 gcc –c –I /usr/dev/mysql/include test.c –o test.o //2.链接把所有目标文件链接成可执行文件 gcc –L /usr/dev/mysql/lib –lmysqlclient test.o –o test //Linux下的库文件分为两大类分别是动态链接库(通常以.so结尾)和 //静态链接库(通常以.a结尾),二者的区别仅在于程序执行时所需的代码 //是在运行时动态加载的,还是在编译时静态加载的。 //3.强制链接时使用静态链接库 //默认情况下, GCC在链接时优先使用动态链接库,只有当动态链接库不存在时才考虑 //使用静态链接库,如果需要的话可以在编译时加上-static选项,强制使用静态链接库。 //在/usr/dev/mysql/lib目录下有链接时所需要的库文件libmysqlclient.so //和libmysqlclient.a,为了让GCC在链接时只用到静态链接库,可以使用下面的命令: gcc –L /usr/dev/mysql/lib –static –lmysqlclient test.o –o test //静态库链接时搜索路径顺序: //1. ld会去找GCC命令中的参数-L //2. 再找gcc的环境变量LIBRARY_PATH //3. 再找内定目录 /lib /usr/lib /usr/local/lib //这是当初compile gcc时写在程序内的 //动态链接时、执行时搜索路径顺序: //1. 编译目标代码时指定的动态库搜索路径 //2. 环境变量LD_LIBRARY_PATH指定的动态库搜索路径 //3. 配置文件/etc/ld.so.conf中指定的动态库搜索路径 //4. 默认的动态库搜索路径/lib //5. 默认的动态库搜索路径/usr/lib //有关环境变量: //LIBRARY_PATH环境变量:指定程序静态链接库文件搜索路径 //LD_LIBRARY_PATH环境变量:指定程序动态链接库文件搜索路径 |
参考资料
Linux GCC常用命令 – 博客园
Linux下的C编程实战 – ITEYE
本文链接地址: Linux Programming, Language C 1 – GCC
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
如果您愿意为文章的内容或想法提供支持,欢迎点击下边的捐赠按钮,资助作者创作更多高价值高品质的内容。