make是一条计算机指令,是在安装有GNU Make的计算机上的可执行指令。该指令是读入一个名为makefile[1]
的文件,然后执行这个文件中指定的指令。
有时make又指GNU Make,GNU Make 是一个用来控制可执行文件和其他一些从源文件来的非源代码文件版本的软件。
软件名称
Make(GNU Make)
开发商
Free Software Foundation, Inc.软件平台
linux,unix
软件语言
C
软件授权
免费
makeGNU Make
编辑
语音
make定义
GNU Make是一个用来控制可执行文件和其他一些从源文件来的非源代码文件版本的软件[2]
。
Make可以从一个名为makefile的文件中获得如何构建你所写程序的依赖关系,Makefile中列出了每个目标文件以及如何由其他文件来生成它。 当你编写一个程序时,你可以为它编写一个makefile文件,这样你就可以使用Make来编译和安装这个程序。
make功能
Make 使最终用户可以在不知道构建细节的情况下构建和安装你的软件,因为这些细节都记录在了你提供的Makefile中[2]
。
基于源文件的改动,Make可以自动知道那些文件需要更新;它也会自动决定文件更新的适当顺序,以避免要更新的文件依赖于另一个同样需要更新的文件。因此,在你修改了程序的源代码并且执行Make后,你不必重新完全编译你的所有文件,只需要重新编译那些直接或间接受到影响的文件就好了。
Make不限于任何一种特定的语言。对于程序中任何一种非源文件, makefile文件中可以指定shell指令去生成它。shell 指令可以执行编译器生成目标文件,执行链接器生成可执行文件,执行ar更新库文件,执行TeX(一个文本排版软件)或Makeinfo去格式化文档。
Make不限于用来生成软件包。你可以用make来控制安装和卸载软件包,或者用来生成标签表,以及其他的任何你想要做的,当然前提是你写好怎么做(╬▔皿▔)凸。
makeMake的规则和目标
Makefile告诉Make怎样执行一系列的指令去依靠源文件生成一个目标文件。Makefile中声明了一个依赖关系的列表,这个列表应当包含所有文件(无论是源文件或者目标)作为输入[2]
。
以下是个简单的规则示例:
target: dependencies ... commands ...
当你执行make的时候你可以指定特定的目标去更新,否则Make会更新Makefile目标列表中第一个目标。当然作为这个目标输入的其他目标会先更新。make 用makefile确定那些目标文件应该被更新,然后那些目标文件实际上需要更新。如果一个目标文件比他的所有依赖都新,这样他就是最新的了,不需要再去重新生成了。其他文件确实需要更新,要按照正确的顺序,在用来生成其他文件之前先更新自己。
makeMakefiles和约定
GNU制订了一些如何编写Makefiles的约定,所用的GNU软件包必须遵守。即使你不打算成为GNU软件,在你的程序中遵循这些约定也是一个好主意,这样用户就可以像其他许多软件包一样构建你的软件包,而且不需要学习任何特殊的东西[3]
。
这些约定可以在章节``Makefile conventions'' (147 k characters)和章节GNU Coding Standards (147 k characters)中看到。[4]
make安卓mk与makefile的关系
Android.mk和Application.mk是基于makefile装了一层封装,编写Android.mk和Application.mk之后可以通过ndk-build执行so的编译,Android.mk中新增了一些对固定文件 固定的环境变量的的读取
如APP_ABI := armeabi-v7a定义在Application.mk中然后执行ndk-build将只编译armeabi-v7a的so在 当前目录的上级目录。
具体参考[4]
make通俗点的解释
当你写一个简单的程序,只有一到两个源文件的时候,输入
% cc file1.c file2.c
就没什么问题,但如果有很多源文件就会很烦人──编译的时间也会很长。
一个方法就是使用目标文件,只在源文件有改变的情况下才重新编译源文件。因此你可以这样做:
% cc file1.o file2.o ... file37.c ...
上次编译后,file37.c 发生了改变,但其他文件没有。这样做可以让编译过程快很多,但是也不能解决累人的输入问题。
或者我们可以使用一个shell script来解决输入问题,但是也需要重新编译所有文件,在大型项目上很没有效率。
如果有成百上千的源文件的话怎么办?如果我们在与很多人合作写程序,别人对源文件进行了修改,又没有告诉你,该怎么办?
也许我们可以把以上两种方法结合,写一种像shellscript 一样的东西。这种文件包含某种技巧可以决定什么时候该对源文件进行编译。如今所有我们要的就是一个程序可以懂得这种技巧,因为要懂得这种技巧,shell 还没那么大的能耐。
这个程序就叫 make。它读入一个文件,叫makefile[1]
,这个文件决定了源文件之间的依赖关系。而且决定了源文件什么时候该编译什么时候不应该编译。例如,某个规则可以说 “ 如果 fromboz.o 比 fromboz.c 要旧,意思就是有人修改了 fromboz.c,因此我们需要重新编译这个文件。”这个makefile还有规则通知 make 该 怎么 重新编译源文件,因此 make 是一个强大得多的工具。
makefile通常和相关的源文件保存在同一个目录下,可以叫做 makefile,Makefile 或者 MAKEFILE。大多数程序员会使用 Makefile 这个名字,因为这样可以让这个文件被放在目录列 表的顶端,可以很容易得看见。
makemake命令
编辑
语音
这是一个非常简单的 make 文件:
foo: foo.c
cc -o foo foo.c
包含两行,一行是依赖关系,一行是执行动作。
依赖关系的那一行包含了程序的名字 (叫做 target),紧跟着一个冒号,然后是空格,最后是源文件的 名字。当 make读入这一行的时候,会检查 foo 是否存在;如果存在,就比较 foo 和 foo.c 最后的修改时间有什 么不同。如果 foo 不存在,或者比 foo.c 要旧,就检查执行动作那一行看看该怎么做。换句话 说,就是 foo.c 需要重新编译的时候该怎么办。
执行动作那一行以一个 tab (按下 tab) 开始,然后是你在命令行下产生 foo 所执行的命令。如果 foo 过期了,或者不存在,make 就会 执行这个命令来产生foo。换句话说,这就是重新编译 foo.c 的规则。
因此,当你输入 make 时,它会确定 foo 和 foo.c 在修改时间上是否同步。这个原则可以在 Makefile 里扩展到成百上千的目标文件上──实际上,在 FreeBSD 里,你只要在合适的目录下输入 make world 就可以编译整个操作系统!
makefile另一个有用的特点就是目标文件不一定就是程序。例如,我们可以 有这样的 make 文件。
foo: foo.c
cc -o foo foo.c
install:
cp foo /home/me
我们可以输入如下的命令告诉 make 该执行哪个目标:
% make target
make 会只执行这个目标而忽略其他的目标。例如,如果我们输入 make foo,就只有 foo 被执行,必要的情况下重新编译 foo 而不会继续执行 install 这个目标。
如果我们只是输入 make 这个命令,make 总会寻找第一个目标,并且在执行完以后就不管其他的目标了。例如,如果我们输入 make foo,make 就会转到 foo 这个目标,在必要的情况下重新编译 foo,而不会执行 install 目标, 然后就停止了。
一定要注意,install 这个目标不依赖任何其他的东西!这意味着我们一旦输入 make install,这个目标下的所有命令都将被执行。这种情况下,foo 将被安装到用户的家目录下。应用程序的makefile正是这样写的,以便程序在正确编译后可以被安装到正确的目录。
要尝试解释的话会比较容易让人混淆。如果你不太懂 make 是如何工作的,最好的办法就是先写一个简单的程序例如 “hello world” 以及和上面的例子相同的 make 文件再去实验。然后 再进一步,使用多个源文件,或者让你的源文件包含一个头文件。 touch 命令在这里就非常有用了──它能让在不改变文件内容的情况下改变文件的日期。
想进一步学习如何编写makefile请参考引用4[5]
.
参考资料
1.
Make
.Make李岩的博客.2013-06-07[引用日期2013-03-21]
2.
GNU Make Introduction
.GNU org[引用日期2017-12-04]
3.
GNU Make manual
.GUN org[引用日期2017-12-04]
5.
跟我一起写Makefile
.Ubuntu wiki[引用日期2017-12-04]