什么是编译器
C语言代码由固定的词汇按照固定的格式组织起来,简单直观,程序员容易识别和理解,但是对于CPU,C语言代码就是天书,根本不认识,CPU只认识几百个二进制形式的指令。这就需要一个工具,将C语言代码转换成CPU能够识别的二进制指令,也就是将代码加工成 .exe 程序;这个工具是一个特殊的软件,叫做编译器(Compiler)。
编译器能够识别代码中的词汇、句子以及各种特定的格式,并将他们转换成计算机能够识别的二进制形式,这个过程称为编译(Compile)。
C语言的编译器有很多种,不同的平台下有不同的编译器,例如:
- Windows 下常用的是微软编译器(cl.exr),它被集成在 Visual Studio 或 Visual C++ 中,一般不单独使用;
- Linux 下常用的是 GUN 组织开发的 GCC,很多 Linux 发行版都自带 GCC;
- Mac 下常用的是 LLVM/Clang,它被集成在 Xcode 中(Xcode 以前集成的是 GCC,后来由于 GCC 的不配合才改为 LLVM/Clang,LLVM/Clang 的性能比 GCC 更加强大)。
GCC 编译器
Linux 下使用最广泛的 C/C++ 编译器是 GCC,大多数的 Linux 发行版本都默认安装,不管是开发人员还是初学者,一般都将 GCC 作为 Linux 下首选的编译工具。本教程也毫不犹豫地使用 GCC 来编译C/C++语言程序。
GCC 仅仅是一个编译器,没有界面,必须在命令行模式下使用。通过gcc/g++命令就可以将源文件编译成可执行文件。
下图是 C/C++ 代码生成可执行文件的过程:
- 在C语言中,我们使用gcc命令来编译和链接C程序。
- 编译C++程序时,gcc命令也可以使用,不过要增加-lstdc++选项,否则会发生链接错误。不过 GCC 中还有一个g++命令,它专门用来编译 C++ 程序,广大 C++ 开发人员也都使用这个命令。
编写makefile
只有一个源文件时,直接命令行编译也可,但是工程比较复杂的时候考虑使用makefile或者CMakeLists.txt
理解make/makefile/cmake/qmake和Makefile编写规则)
1. $(wildcard ./dir/*.c), 来获取工作目录下的所有的.c文件列表。
2. $(patsubst %.c,%.o,$(wildcard *.c)),首先使用“wildcard”函数获取工作目录下的.c文件列表;
之后将列表中所有文件名的后缀.c替换为.o。这样我们就可以得到在当前目录可生成的.o文件列表。
3. $@ 表示目标文件
$^ 表示所有的依赖文件
$< 表示第一个依赖文件
$? 表示比目标还要新的依赖文件列表
4. .PHONY是一个伪目标,可以防止在Makefile中定义的只执行命令的目标和工作目录下的实际文件出现名字冲突,
另一种是提交执行makefile时的效率, 可以使用make clean清除文件
5. 优化等级-O设置一共有五种:-O0、-O1、-O2、-O3和-Os。
让我们来逐一考察各个优化等级:
-O0:这个等级(字母“O”后面跟个零)关闭所有优化选项,也是CFLAGS或CXXFLAGS中没有设置-O等级时的默认等级。这样就不会优化代码,这通常不是我们想要的。
-O1:这是最基本的优化等级。编译器会在不花费太多编译时间的同时试图生成更快更小的代码。这些优化是非常基础的,但一般这些任务肯定能顺利完成。
-O2:-O1的进阶。这是推荐的优化等级,除非你有特殊的需求。-O2会比-O1启用多一些标记。设置了-O2后,编译器会试图提高代码性能而不会增大体积和大量占用的编译时间。
-O3:这是最高最危险的优化等级。用这个选项会延长编译代码的时间,并且在使用gcc4.x的系统里不应全局启用。自从3.x版本以来gcc的行为已经有了极大地改变。在3.x,-O3生成的代码也只是比-O2快一点点而已,而gcc4.x中还未必更快。用-O3来编译所有的软件包将产生更大体积更耗内存的二进制文件,大大增加编译失败的机会或不可预知的程序行为(包括错误)。这样做将得不偿失,记住过犹不及。在gcc 4.x.中使用-O3是不推荐的。
makefile编写比较好的文章
1. 几个Makefile通用模板分享!
2. 一个适用各类场合的Makefile模板
3. 通用MAKEFILE的编写和在项目工程中使用MAKEFILE(包括动态库、静态库的链接、整个工程联合编译)