发现自己一年没更新博客了,掏出存货来刷一下存在感 ( ̄▽ ̄)“…
主要原因 是:① 忙于实习;② 懒于撰稿;③ 完美主义越来越强,note回看就修订觉得发不出手、过半个月回看又修订还是发不出手,结果懒得发了… ( ̄▽ ̄)”
先随手发;之后本地修订后,再回来改线上的吧~
make是GNU里的一个utility,可实现方便的自动化编译,在unix和linix都可以写;
首先要写一个文本叫 makefile,然后调用命令make
,terminal即会按makefile的内容对工程或源文件进行 re-compile or link;
makefile中写的内容,表示的是 how、when对什么文件进行remake,从而让我们后续可以方便的 “一键remake”。
windows下的make
一般默认make是Unix OS下;
若是windows下,得看IDE——Delphi是用make,VC++用nmake;
windows下要想make就得下载MinGW编译器了( ̄▽ ̄)".
makefile可以compile也可以link.
.obj
、UNIX是.o
);.lib
、UNIX是.a
Archive File);.exe
、UNIX无后缀);①用make
,会自动按顺序寻找文件 GNUmakefile、makefile、Makefile,若当前目录没有makefile,那会自动创建一个。
②手动指定执行makefile文件(很少用,一般直接make)
make -f <...makefile>
makefile和shell的区别
作用:shell是为了重用terminal内的命令服务的;makefile是用于工程compile/link用的;makefile内可调用shell脚本,如:+ ./xxx.sh
;
写法:
#!/bin/bash
,后缀名是.sh
;\
表同一行。*
;makefile内通配符:%
;{}
,命令串用 ()
;makefile中访问变量用 $()
或 ${}
都行;shell与cshell的区别
linux下提供了很多种shell: (简称sh)、C-Shelll(简称csh)、Korn Shell(简称ksh)和Bourne Again Shell (简称bash)。
.sh
,是Unix的默认shell,也是其他shell的基础;性能好,但用户交互低;.csh
,语法类似C,提供了 .sh
没有的用户交互功能——命令补全、命令别名等;与 .sh
不兼容;.ksh
,结合了 .sh
和 .csh
的优点,并向下兼容了 .sh
;.sh
、 .csh
、.ksh
的优点,并向下兼容了 .sh
;最强!目标target: 所需prerequisites
(TAB) command (任意的Shell命令)
label:
(TAB) command...
make
触发执行makefile后,make会检查 各prerequisite的更新日期,若比target新,就重新执行此句命令。make label
来单独执行。.o
文件与自身相关的 .h
、.c
文件的prerequisites可省略,因为会自动补充;clean
label,删除所有中间、执行文件,日后用 make clean
就能起到复位的作用;
clean
label内,务必用 rm -rf
而不是 rm
,不然报错一句,后续clean都不执行了!makefile的触发条件
① prerequisite比target要新;
② 或者 prerequisite不存在;
所以,若target的A不是实物,永远不会生成,则此语句每次make都 必会被调用。
B = ?
C = ?
# B和C是具体的文件,A只是抽象的程序tag无对应实体文件
A: B C
B -o C #和A没关系,A永远不会生成,故此语句必执行
也可以有多个抽象的程序块,如下:
all: do1 do2 do3
do1: A B C
...balabala...
do2: E F
...balabala...
do3:
...balabala...
makefile中 .PHONY
的学习
考虑以上makefile的case情况,若在倒霉的、在写完makefile后,忘了,本地出现了一个文件或文件夹的名称也叫做 A ! 那完犊子,按makefile的规则,A被检测到,且prerequisite B、C并不是比 A 要新的话,这个makefile就不会执行了!
总结:makefile中的无文件抽象target因本地同名文件/文件夹的存在,无法“抽象”,使得makefile无法如意愿执行。
Solution:在A前面加上 .PHONY
(类似关键字的感觉),声明此A是抽象的,别去检索是否存在同名文件啦!
即:(makefile目录下,有同名文件A,也会执行!)
B = ?
C = ?
.PHNONY: A #声明A是phony抽象的
A: B C
B -o C #和A没关系,A永远不会生成,故此语句必执行
.PHONY
只是一个声明,不会影响后续label的执行的。
target和prerequisite的数量
至少一个target:target是一个东西或事件、自定义函数名。最好加个注释说明一下是啥;
可以0~n个prerequisite:prerequisite是前置文件,可用通配符 *
;
行注释 用#
;
行续写,于行尾 用 /
, 表多行代码用一个进程执行;
makefile内写的程序默认一行一个进程执行,故需要将程序串行执行,得自己加 /
;
注:注释也可用 /
进行续写;使用 /
后会读取“空行”,故下一行别接注释!
宏定义 Macro define
=
, pi=3.14
, 可嵌套,大小敏感;$(宏名)
define
即多行版本的宏定义
define 宏名
...
...
endef
include
导入别的makefile(类似导入库),文件名语法可用正则表达和shell.
若多个导入的makefile库内,出现 target冲突,取最后一行定义为准
正则表达式,
如:通配符等—— *, [], ?,@
, @好像是让系统回话功能闭嘴,干净。
Reference