Make要素

  • 基本语法单元
target: sources
    program source target # 必须tab键起始,记录数据处理的流程
  • target和sources都应对应于当前路径下的文件名
    • 当source存在时可以通过program source target来生成target

变量

1. 变量取值

a:=1 # eager evaluation(= 是lazy evaluation)
$(info $(a))
  • 调用时使用()()、(info TEXT) 输出TEXT
  • 特殊变量:$^表示输出数据,$@表示输出数据
target: source
    program $^ $@
target: source1 source2 source3
    program $< --reference $(word 2,$^) --location $(word 3,$^) -o $@

2. make的函数

  • 函数调用$(function arg1 arg2 ···)
    • word函数:返回第n个参数$(word N,TEXT)
        $(word 2,make.c use.c high.c) # 输出make.c
    
    • patsubst函数:替换符合条件的字符串$(patsubst pattern,replacement,text)
        $(patsubst %.c,%.o,make.c use.c high.c) # 输出make.o use.o high.o
    
    • foreach函数:遍历参数$(foreach var,list,text)
        $(foreach var,a b c,$(var) $(var)) # 输出a a b b c c
    
    • if函数:条件判断$(if condition,true_part,false_part)
        $(if $(findstring a,abc),yes,no) # 输出yes
    
    • call函数:调用其他Makefile文件$(call function,arg1,arg2,···)
        $(call my_function,arg1,arg2)
    

通配符与替换

1. 一般匹配关系pattern

  • %:匹配任何字符串,包括空字符串
  • *:匹配零个或多个字符
  • ?:匹配零个或一个字符
例子
filelist:=x.h5 y.h5 z.h5
.PTHNY: all
all: $(filelist:.h5=.png)

%.png: %.h5
    ./plot_celestial.py $^ -0 $@
  • $(filelist:.h5=.png):替换.h5.png
    • 也可以用$(patsubst %.h5,%.png,$(filelist))来实现
    • 有共同前缀时可以进一步简写:$(filelist:.h5=.png)
  • all是一个总括目标
特殊目标
  • .PHONY:代表无对应文件的目标,用于声明 all 是一个​​伪目标(Phony Target)
    • all 通常是 Makefile 的第一个目标,直接运行 make 时会自动执行它。声明为伪目标可确保其可靠性。
  • DELETE_ON_ERROR:如果出错就把坏文件删掉
  • .SECONDARY保留中间结果
新工具:guile
  • 动态生成依赖关系:传统 Makefile 需手动维护依赖,而 Scheme 可自动扫描源码头文件生成依赖树:
%.o: %.c
    $(guile (generate-deps $<))  # 调用 Scheme 函数动态生成依赖
    gcc -c $< -o $@
  • 独立脚本开发
#!/usr/bin/guile -s
!#
(define (factorial n)
  (if (<= n 1) 1 (* n (factorial (- n 1)))))
(display (factorial 5))  ; 输出 120
函数式编程:把目标描述清楚
  • Makefile 是函数式编程Functional Programming的语言
# 生成 numbers-N.csx 包含N*100+1 到 (N+1)*100 的数字
numbers-%.csv:
    seq $(guile (+ 1 (* $* 100))) $(guile (* 100 (+ $* 1))) > $@

total-%: numbers-%.csv
    paste -s -d + < $^ | bc > $@

# 求积
prod: total-0 total-1 total-2
    paste -s -d* < $^ | bc > $@

Make机理

1. 调试

  • 使用remake
  • 机理见讲义

简化语句

  • Makefile 中可以调用shell命令将其标准输出作为值
sequence:=$(shell seq -w 00 99)
filelist:=$(shell find . -name "*.h5")
  • 构造total-N目标
seqs:=$(shell seq 0 2)
totals:=$(seqs:%=total-%)

#另一种方法
totals:=$(addprefix total-,$(seqs))

替换语法

语法示例作用适用场景
$(var:%=prefix-%)$(seqs:%=total-%)为每个元素添加固定前缀批量生成新目标名
$(var:suffix=)$(files:.o=.c)替换后缀(需精确匹配)源文件与目标文件转换
$(patsubst pat,rep,$(var))$(patsubst %,total-%,$(seqs))通用模式替换(功能同示例)复杂模式匹配

Makefile脚本

1. 选择结构

a:=$(if CONDITION,THEN-PART[,ELSE-PART])

$(or CONDITON1 CONDITION2),and COND1 COND2用于逻辑运算

2. 循环结构与自定义函数

  • 数据本身可以构造一重循环,当循环多于一重时,使用(foreachvar,list,text)makefilerl:=(foreach var,list,text)
profile:=<data class="katex-src" value="(foreach d,x y z,"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>f</mi><mi>o</mi><mi>r</mi><mi>e</mi><mi>a</mi><mi>c</mi><mi>h</mi><mi>d</mi><mo separator="true">,</mo><mi>x</mi><mi>y</mi><mi>z</mi><mo separator="true">,</mo></mrow><annotation encoding="application/x-tex">(foreach d,x y z,</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">ore</span><span class="mord mathnormal">a</span><span class="mord mathnormal">c</span><span class="mord mathnormal">h</span><span class="mord mathnormal">d</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mord mathnormal" style="margin-right:0.04398em;">yz</span><span class="mpunct">,</span></span></span></span></data>(rl:%=1t_+%_<data class="katex-src" value="(d).h5))
&#10;"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>d</mi><mo stretchy="false">)</mo><mi mathvariant="normal">.</mi><mi>h</mi><mn>5</mn><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(d).h5))
 </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">d</span><span class="mclose">)</span><span class="mord">.</span><span class="mord mathnormal">h</span><span class="mord">5</span><span class="mclose">))</span></span></span></span></data>(info <data class="katex-src" value="(profile))
&#10;```
&#10;
&#10;- Makefile模板,起到函数作用
&#10;```makefile
&#10;define video
&#10;"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>p</mi><mi>r</mi><mi>o</mi><mi>f</mi><mi>i</mi><mi>l</mi><mi>e</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mi mathvariant="normal">‘</mi><mi mathvariant="normal">‘</mi><mi mathvariant="normal">‘</mi><mo>−</mo><mi>M</mi><mi>a</mi><mi>k</mi><mi>e</mi><mi>f</mi><mi>i</mi><mi>l</mi><mi>e</mi><mtext>模板,起到函数作用</mtext><mi mathvariant="normal">‘</mi><mi mathvariant="normal">‘</mi><mi mathvariant="normal">‘</mi><mi>m</mi><mi>a</mi><mi>k</mi><mi>e</mi><mi>f</mi><mi>i</mi><mi>l</mi><mi>e</mi><mi>d</mi><mi>e</mi><mi>f</mi><mi>i</mi><mi>n</mi><mi>e</mi><mi>v</mi><mi>i</mi><mi>d</mi><mi>e</mi><mi>o</mi></mrow><annotation encoding="application/x-tex">(profile))
 ```
 
 - Makefile模板,起到函数作用
 ```makefile
 define video
 </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">p</span><span class="mord mathnormal">ro</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">e</span><span class="mclose">))</span><span class="mord">‘‘‘</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord mathnormal" style="margin-right:0.03148em;">ak</span><span class="mord mathnormal">e</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">e</span><span class="mord cjk_fallback">模板,起到函数作用</span><span class="mord">‘‘‘</span><span class="mord mathnormal" style="margin-right:0.03148em;">mak</span><span class="mord mathnormal">e</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">e</span><span class="mord mathnormal">d</span><span class="mord mathnormal">e</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">in</span><span class="mord mathnormal">e</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mord mathnormal">i</span><span class="mord mathnormal">d</span><span class="mord mathnormal">eo</span></span></span></span></data>(1)/%.avi: <data class="katex-src" value="(1)/%.mp4
&#10;    ffmpeg -i "><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo><mi mathvariant="normal">/</mi><mi>f</mi><mi>f</mi><mi>m</mi><mi>p</mi><mi>e</mi><mi>g</mi><mo>−</mo><mi>i</mi></mrow><annotation encoding="application/x-tex">(1)/%.mp4
     ffmpeg -i </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.10764em;">ff</span><span class="mord mathnormal">m</span><span class="mord mathnormal">p</span><span class="mord mathnormal">e</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6595em;"></span><span class="mord mathnormal">i</span></span></span></span></data>$^ $<data class="katex-src" value="@
&#10;endef
&#10;
&#10;"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">@</mi><mi>e</mi><mi>n</mi><mi>d</mi><mi>e</mi><mi>f</mi></mrow><annotation encoding="application/x-tex">@
 endef
 
 </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord">@</span><span class="mord mathnormal">e</span><span class="mord mathnormal">n</span><span class="mord mathnormal">d</span><span class="mord mathnormal">e</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span></span></span></span></data>(eval  <data class="katex-src" value="(foreach d,up down transverse,"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>f</mi><mi>o</mi><mi>r</mi><mi>e</mi><mi>a</mi><mi>c</mi><mi>h</mi><mi>d</mi><mo separator="true">,</mo><mi>u</mi><mi>p</mi><mi>d</mi><mi>o</mi><mi>w</mi><mi>n</mi><mi>t</mi><mi>r</mi><mi>a</mi><mi>n</mi><mi>s</mi><mi>v</mi><mi>e</mi><mi>r</mi><mi>s</mi><mi>e</mi><mo separator="true">,</mo></mrow><annotation encoding="application/x-tex">(foreach d,up down transverse,</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">ore</span><span class="mord mathnormal">a</span><span class="mord mathnormal">c</span><span class="mord mathnormal">h</span><span class="mord mathnormal">d</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">u</span><span class="mord mathnormal">p</span><span class="mord mathnormal">d</span><span class="mord mathnormal">o</span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mord mathnormal">n</span><span class="mord mathnormal">t</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mord mathnormal">an</span><span class="mord mathnormal">s</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mord mathnormal">erse</span><span class="mpunct">,</span></span></span></span></data>(call video,$(d))))