一、什么是Makefile?
我们写大型项目时,会用到很多源文件,源文件在不同目录中的文件夹里包含着,一个一个编译起来很麻烦,makefile就能够方便我们编译链接。
使用makefile进行编译连接时会用到make命令,Makefile的会在执行make命令时指定编译和链接的规则,包括源代码文件之间的链接关系、依赖关系等。它关系到整个项目工程的编译规则:哪些文件需要先编译,哪些要后编译,哪些需要重新编译等复杂的操作。
另外,Makefile每次只会编译修改的和依赖于修改的那些文件,提高了编译效率。
二、编译链接过程
对于程序的编译,首先都需要将源代码文件编译成中间代码(Win下.ob文件,UNIXLINUX下. a文件),即Object文件,然后再将大量的Object文件链接在一起执行。
在编译时,编译器检查程序代码中语法的正确性,函数以及变量的声明是否正确,以及进行预处理(例如头文件的所在位置以及宏替换等),此步骤只要语法没有问题,编译就不会出错,便可以生成中间目标文件。
在链接时,主要是链接函数与全局变量,链接器不用管函数在哪一个源文件当中,它关心的是函数所在的中间目标文件。大多数情况下,编译生成的中间目标文件比较多,在链接时需要明确地指出中间目标名,这对于编译很不方便,解决方法是给中间目标文件打包生成一个库文件(Win下是.lib,UNIX/LINUX是.a)。
综上,编译链接的过程是:
- 首先源文件会讲过编译阶段生成中间目标文件,再由中间目标文件生成执行文件。
- 编译时编译器只检测程序的语法、函数,变量是否声明以及一些预处理。如果函数只是声明但是未实现则编译器只会警告(不是所有的编译器都是这样),仍然可以生成中间目标文件。
- 在链接程序时,链接器会在所有的中间目标文件中寻找函数的实现,如果找不到,那就会提示链接错误。
三、实现简单的Makefile(生成单个可执行文件)
把你需要的目标文件,.o文件,.c文件如何实现的规则(指令)按照格式写进去就可以。
Makefile 赋值操作
:=是一种赋值操作符,称为“简单赋值”。它与其他赋值操作符(如=)不同的是,:=操作符用于在变量定义时立即展开右侧的内容,并将结果赋给左侧的变量。这样做可以确保变量在后续引用时具有确定的值,而不会受到后续环境变化的影响。
Makefile 内置函数 $(shell …)
App_SRC_Files := $(shell find app/ -type f -name '*.rs') $(shell find app/ -type f -name 'Cargo.toml')
这个函数的作用是在 Makefile 中执行 shell 命令,并将其输出作为函数的返回值。
find 命令:查找指定目录 (app/) 下的文件路径
-type 参数:f 表示只查找普通文件
-name 参数:分别指定了要查找的文件名模式为以 .rs 结尾的 Rust 源文件和名称为 Cargo.toml 的文件。
Makefile -I 指定包含路径
App_Include_Paths := -I ./app -I$(SGX_SDK)/include -I$(CUSTOM_EDL_PATH)
-I:指定包含路径(include,"包含路径"通常是指在编译程序时,编译器用于查找头文件的路径。在Makefile中设置正确的包含路径可以确保编译器能够找到所需的头文件,从而成功编译源代码。)
-I ./app 表示将当前目录下的 app 目录添加到包含路径中。
-I$(SGX_SDK)/include 表示将环境变量 SGX_SDK 指定的 SGX SDK 安装目录下的 include 目录添加到包含路径中。
-I$(CUSTOM_EDL_PATH) 表示将自定义环境变量 CUSTOM_EDL_PATH 指定的路径添加到包含路径中。
参考链接:
- http://t.csdnimg.cn/DCVBe