打代码的过程就是编辑的过程。编辑完程序后,需要两个步骤:编译和链接,把程序变成我们需要的可执行程序。
编译过程(包括预处理、编译和汇编(test.s到test.o))最终生成。o文件在linux系统和。windows系统上的obj文件。该过程将添加包含在。cpp文件添加到。cpp文件,大概意思是用头文件中的具体内容替换include,但是不需要具体的实现内容。
形如:include<>,是在系统指定目录中查找头文件,在linux系统中指定的默认目录包括:usr/include;usr/local/include;
/usr/aarch64-linux-gnu/include
形如:include””,是在引号里面的目录中查找头文件,如果寻找不到的话在去默认目录中查询。
该过程的实现:例如有三个文件,main.cpp,test1.cpp,test1.hpp在同一个文件夹下,具体内容如下:
上面三个文档位于同一个文件夹下面,则使用g++的编译方式为:
g++ -c main.cpp
g++ -c test1.cpp
上面看似没有用到test1.hpp,如果把test1.hpp去除,则编译部分无法完成,而去除test1.cpp对main的编译没有没有影响。按照上面所说,也可以把test1.hpp移动到系统默认文件中。
3. 链接就是把目标文件、目标文件所需要的库文件,其他目标代码(指所依赖的其他.o文件—可以是编译中生成的,不是源文件)等进行组织,生成可执行文件的过程,在linux系统上生成没有后缀的可执行文件,在windows系统中生成.exe文件。
资料领取直通车:大厂面试题锦集+视频教程https://link.zhihu.com/?target=https%3A//docs.qq.com/doc/DTlhVekRrZUdDUEpy
免费学习网站:C/C++Linux服务器开发/后台架构师https://link.zhihu.com/?target=https%3A//ke.qq.com/course/417774%3FflowToken%3D1028592
该过程的实现:在2中生成了main.o和test1.o两个目标文件,这里需要进行链接,按照定义,就是主要的目标文件(mian.o)和其他目标文件(test1.o)进行链接,如果main.o用到的库的文件,这里也会自动链接到库中。
使用g++的链接方式为:
g++ main.o test1.o -o main
或者是
g++ -o main main.o test1.o
注意:.o后面跟着的是生成的文件名称。
前面说过,链接过程需要用到库,这里的库其实就是函数库。linux系统下静态函数库的后缀是。而动态库是。所以。静态库和动态库的区别在于:
静态库由一系列。o文件。在链接过程中,这些。o文件是和主目标文件一起生成的,这些。o文件生成后不需要;
动态库在链接过程中不使用特定的函数,而是在程序运行过程中动态调用。在windows系统中,我们可以看到。exe文件夹包含各种。dll文件(windows下的动态库)。当然,一些必需的。dll文件位于系统的默认路径中。
编译过程的预处理、编译、汇编的步骤也可以通过g++的命令实现,但是基本无用。
编译和链接的两个命令如一中所使用
g++也可以直接生成可执行程序,一中的编译链接可以通过如下命令一步完成:
g++ main.cpp test1.cpp -o main
也会常常遇到头文件和库文件不在指定目录和当前目录下的情况:这种情况可以通过以下命令指定所需要的目录路径来实现:
g++ main.cpp -o main -I -L -l
-I表示include,main.cpp包含的头文件地址,-L表示lib库表示所需要的库的地址,-l(小写的L)表示lib,为具体的-L下路径中的所需要的库的名称。
第三部分,如果项目包含的头文件和库太多,g++编译链接命令会很长,如果各种依赖非常复杂,g++命令会非常繁琐。因此,有必要使用一种方式来组织这些命令。当一个程序想要编译链接的时候,只需要一步。
实现这种方式的工具是cmake工具,这是一个跨平台的工具。可以编写Cmakelists.txt文件来完成上述操作,cmakelists.txt也是跨平台文件。在不同平台使用cmake命令会将Cmakelists.txt生成到不同的文件中,而makefile就是在linux系统中生成的文件。要生成makefile文件,需要执行make命令来完成程序的编译和链接。Makefile可以直接在linux系统中编写。
简单的makefile的书写
仍然以前面的main.cpp,test1.cpp,test1.hpp为例。编写的makefile文件如下:
另外一种更加常用的写法是:
先大致浏览一下上面的makefile文件,可以看出,makefile的规则格式是:
这是makefile的核心规则,它是多种这样的命令格式的组合。对比example1.example2可以看出,这个makefile其实就是之前编译链接的步骤,只不过需要符合一定的格式。
这里要生成的目标其实只是一个名字,可以任意取,但是不知道为什么我看到的很多程序都是用example2的方式写的。可能感觉比较规范吧。补充也是很常见的。h依赖于生成的命令。o文件,如:
test1.o:test1.hpp
g++ -c test1.cpp
其实这个也是没有必要的,因为在test1.cpp中会根据自己的include自动添加.hpp文件。
一个简单的makefile是如何运行的?
A.在终端输入make命令,会自动搜索到当前路径下的makefile或Makefile。
B.开始执行第一行命令,根据第一行命令找到你要依赖的main.o和test1.o文件。如果搜索路径(当前路径和默认路径)中没有main.o和test1.o,或者main.c和test1.cpp被修改,开始执行下面的命令并生成所需的。o文件。否则,直接执行以下语句。
C.根据例2中makefile的编写,在执行make命令后,可以看到程序执行下面的命令,最后执行启动命令。
d.在具体要执行的命令行之前加上@符号命令可以不在终端中显示。
e.可以通过在makefile文件中添加一些指令,达到与在终端中运行命令相同的效果,这个被称之为伪指令。在makefile中用来清理产生的文件。
example3:
在终端中输入 make clean就可以清理产生的main.o ,test1.o和test1文件,与在终端中输入
rm main.o test1.o test1有一样的效果。
makefile的简化操作
a.字符变量的使用
example4:
由例子可以知道:可以=号给多个变量赋值到一个字符变量中,然后通过$(字符变量)的方式代替多个变量。
ATTENTION:除此之外:还有?=, :=, +=等赋值符号
?=表示如果字符变量已经赋值过了,则不在进行赋值
+=表示追加赋值
b.使用自动推导简化makefile文件
在例子中,当第一行命令确定需要使用main.o和test1.o文件时,可以自动推导出g++ -c命令,不需要自己在写。例如:
example5:
进一步简化
example6:
把变量添加进去,进一步简化
example7: