zoukankan      html  css  js  c++  java
  • make命令语法学习

    基本概念

    • 需要得到什么就make什么,比如 make abc.txt 得到一个文本文件,make image 得到一个docker 镜像 , 等等。
    • 一般来说使用 make命令的目录下应该一个名为 Makefile的文件。 make -f <makefile> 使用自定义的文件名。
    • Makefile 是一组规则的集合,他们给出了得到目标(target)所需的所有步骤,好比做一道菜需要的所有原料和工艺流程。
    • 规则的基本语法为:
     <target>: <prerequisites...>
        <commands>
    

    其中 target 是必须的,prerequisites和commands非必需,但二者必有其一。

    • 如果只打 make,默认构建第一个目标。
    • make 默认会输出其将要执行的命令,如果不想看到这些输出,可以在命令前加@。
    • make命令列表中的每一行命令,都会在一个独立的shell中执行,因此上一行命令中设置的变量在下一行中不可用。
    • make 的赋值符号是 := 而不是 =

    make中的特殊变量,美元符号

    1. $@ 表示当前正在制作(make)的目标文件。比如 make foo, 那么 $@ 就是 foo。 助记:@表示argument。
    2. $< 表示一个输入文件(先决条件中的第一个)。 助记:< 是bash中的文件输入符。
    3. $^ 所有输入文件, 多次出现的文件在其中仅出现一次。 助记:< 竖起来就是 ^。
    4. $? 所有比target新的输入文件。 助记:? 好比一个问题:“你为什么做这个? 更改了哪些文件以使其必需?”。
    5. $$ 真正的美元符号。
    6. $* 规则中百分号%匹配的东西。 助记: 在make中,百分号%相当于shell中的星号*。
    7. $(@D) 和 $(@F) 分别匹配$@ 的路径部分和文件部分。以上其他变量同理,比如$(<D) 和 $(<F)。
    8. 使用make特殊变量的例子:
      之前:
    result.txt: source.txt
    	@echo "building result.txt from source.txt"
    	cp source.txt result.txt
    source.txt:
    	@echo "building source.txt"
    	echo "this is the source" > source.txt
    

    终端输出:

    building source.txt
    echo "this is the source" > source.txt
    building result.txt from source.txt
    cp source.txt result.txt
    

    现在:

    result-using-var.txt: source.txt
    	@echo "buildling result-using-var.txt using the $$< and $$@ vars"
    	cp $< $@
    

    终端输出:

    buildling result-using-var.txt using the $< and  vars
    cp source.txt result-using-var.txt
    

    使用通配符%批量生成文件

    src/%.txt:
    	@# First things first, create the dir if it doesn't exist.
    	@# Prepend with @ because srsly who cares about dir creation
    	@[ -d src ] || mkdir src
    	@# then, we just echo some data into the file
    	@# The $* expands to the "stem" bit matched by %
    	@# So, we get a bunch of files with numeric names, containing their number
    	echo $* > $@
    

    在终端输入: make src/01.txt 终端输出: echo 01 > src/01.txt 。 src目录下生成 01.txt 文件, 内容为:01。
    这样只能一个个文件依次生成。现在添加下面几行:

    srcfiles := $(shell echo src/{00..99}.txt)
    source: $(srcfiles)
    

    在终端输入: make source , 此时批量生成了100个文件。

    echo 0 > src/0.txt
    echo 1 > src/1.txt
    echo 2 > src/2.txt
    echo 3 > src/3.txt
    echo 4 > src/4.txt
    echo 5 > src/5.txt
    echo 6 > src/6.txt
    echo 7 > src/7.txt
    echo 8 > src/8.txt
    echo 9 > src/9.txt
    echo 10 > src/10.txt
    echo 11 > src/11.txt
    echo 12 > src/12.txt
    echo 13 > src/13.txt
    echo 14 > src/14.txt
    echo 15 > src/15.txt
    echo 16 > src/16.txt
    echo 17 > src/17.txt
    echo 18 > src/18.txt
    echo 19 > src/19.txt
    echo 20 > src/20.txt
    echo 21 > src/21.txt
    echo 22 > src/22.txt
    echo 23 > src/23.txt
    echo 24 > src/24.txt
    echo 25 > src/25.txt
    echo 26 > src/26.txt
    echo 27 > src/27.txt
    echo 28 > src/28.txt
    echo 29 > src/29.txt
    echo 30 > src/30.txt
    echo 31 > src/31.txt
    echo 32 > src/32.txt
    echo 33 > src/33.txt
    echo 34 > src/34.txt
    echo 35 > src/35.txt
    echo 36 > src/36.txt
    echo 37 > src/37.txt
    echo 38 > src/38.txt
    echo 39 > src/39.txt
    echo 40 > src/40.txt
    echo 41 > src/41.txt
    echo 42 > src/42.txt
    echo 43 > src/43.txt
    echo 44 > src/44.txt
    echo 45 > src/45.txt
    echo 46 > src/46.txt
    echo 47 > src/47.txt
    echo 48 > src/48.txt
    echo 49 > src/49.txt
    echo 50 > src/50.txt
    echo 51 > src/51.txt
    echo 52 > src/52.txt
    echo 53 > src/53.txt
    echo 54 > src/54.txt
    echo 55 > src/55.txt
    echo 56 > src/56.txt
    echo 57 > src/57.txt
    echo 58 > src/58.txt
    echo 59 > src/59.txt
    echo 60 > src/60.txt
    echo 61 > src/61.txt
    echo 62 > src/62.txt
    echo 63 > src/63.txt
    echo 64 > src/64.txt
    echo 65 > src/65.txt
    echo 66 > src/66.txt
    echo 67 > src/67.txt
    echo 68 > src/68.txt
    echo 69 > src/69.txt
    echo 70 > src/70.txt
    echo 71 > src/71.txt
    echo 72 > src/72.txt
    echo 73 > src/73.txt
    echo 74 > src/74.txt
    echo 75 > src/75.txt
    echo 76 > src/76.txt
    echo 77 > src/77.txt
    echo 78 > src/78.txt
    echo 79 > src/79.txt
    echo 80 > src/80.txt
    echo 81 > src/81.txt
    echo 82 > src/82.txt
    echo 83 > src/83.txt
    echo 84 > src/84.txt
    echo 85 > src/85.txt
    echo 86 > src/86.txt
    echo 87 > src/87.txt
    echo 88 > src/88.txt
    echo 89 > src/89.txt
    echo 90 > src/90.txt
    echo 91 > src/91.txt
    echo 92 > src/92.txt
    echo 93 > src/93.txt
    echo 94 > src/94.txt
    echo 95 > src/95.txt
    echo 96 > src/96.txt
    echo 97 > src/97.txt
    echo 98 > src/98.txt
    echo 99 > src/99.txt
    

    养成添加伪目标(phony)的好习惯

    伪目标是为了防止这样一种情况出现: 比如上文出现的source,其本身并不是为了生成什么文件,只是执行一条命令或操作,此时假设当前目录下恰好有一个文件名为source,那么这条make命令就不会被执行,因为make认为需要生成的目标已经存在。
    添加伪目标: .PHONY: source, 使得无论什么情况下输入 make source, make都会执行source下的操作。

    生成目标文件

    添加以下内容:

    dest/%.txt: src/%.txt
    	@[ -d dest ] || mkdir dest
    	cp $< $@
    

    此时输入 make dest/02.txt, 终端输出:

    echo 02 > src/02.txt
    cp src/02.txt dest/02.txt
    rm src/02.txt
    

    src目录下无文件, dest目录下有一个文件 02.txt
    但是现在这样只能一次生成一个目标文件,如何批量生成呢?
    加入以下内容:

    .PHONY: destination
    destfiles := $(patsubst src/%.txt,dest/%.txt,$(srcfiles))
    destination: $(destfiles)
    

    输入 make destination, 终端输出

    echo 0 > src/0.txt
    cp src/0.txt dest/0.txt
    echo 1 > src/1.txt
    cp src/1.txt dest/1.txt
    echo 2 > src/2.txt
    cp src/2.txt dest/2.txt
    echo 3 > src/3.txt
    cp src/3.txt dest/3.txt
    echo 4 > src/4.txt
    cp src/4.txt dest/4.txt
    echo 5 > src/5.txt
    cp src/5.txt dest/5.txt
    echo 6 > src/6.txt
    cp src/6.txt dest/6.txt
    echo 7 > src/7.txt
    cp src/7.txt dest/7.txt
    echo 8 > src/8.txt
    cp src/8.txt dest/8.txt
    echo 9 > src/9.txt
    cp src/9.txt dest/9.txt
    echo 10 > src/10.txt
    cp src/10.txt dest/10.txt
    echo 11 > src/11.txt
    cp src/11.txt dest/11.txt
    echo 12 > src/12.txt
    cp src/12.txt dest/12.txt
    echo 13 > src/13.txt
    cp src/13.txt dest/13.txt
    echo 14 > src/14.txt
    cp src/14.txt dest/14.txt
    echo 15 > src/15.txt
    cp src/15.txt dest/15.txt
    echo 16 > src/16.txt
    cp src/16.txt dest/16.txt
    echo 17 > src/17.txt
    cp src/17.txt dest/17.txt
    echo 18 > src/18.txt
    cp src/18.txt dest/18.txt
    echo 19 > src/19.txt
    cp src/19.txt dest/19.txt
    echo 20 > src/20.txt
    cp src/20.txt dest/20.txt
    echo 21 > src/21.txt
    cp src/21.txt dest/21.txt
    echo 22 > src/22.txt
    cp src/22.txt dest/22.txt
    echo 23 > src/23.txt
    cp src/23.txt dest/23.txt
    echo 24 > src/24.txt
    cp src/24.txt dest/24.txt
    echo 25 > src/25.txt
    cp src/25.txt dest/25.txt
    echo 26 > src/26.txt
    cp src/26.txt dest/26.txt
    echo 27 > src/27.txt
    cp src/27.txt dest/27.txt
    echo 28 > src/28.txt
    cp src/28.txt dest/28.txt
    echo 29 > src/29.txt
    cp src/29.txt dest/29.txt
    echo 30 > src/30.txt
    cp src/30.txt dest/30.txt
    echo 31 > src/31.txt
    cp src/31.txt dest/31.txt
    echo 32 > src/32.txt
    cp src/32.txt dest/32.txt
    echo 33 > src/33.txt
    cp src/33.txt dest/33.txt
    echo 34 > src/34.txt
    cp src/34.txt dest/34.txt
    echo 35 > src/35.txt
    cp src/35.txt dest/35.txt
    echo 36 > src/36.txt
    cp src/36.txt dest/36.txt
    echo 37 > src/37.txt
    cp src/37.txt dest/37.txt
    echo 38 > src/38.txt
    cp src/38.txt dest/38.txt
    echo 39 > src/39.txt
    cp src/39.txt dest/39.txt
    echo 40 > src/40.txt
    cp src/40.txt dest/40.txt
    echo 41 > src/41.txt
    cp src/41.txt dest/41.txt
    echo 42 > src/42.txt
    cp src/42.txt dest/42.txt
    echo 43 > src/43.txt
    cp src/43.txt dest/43.txt
    echo 44 > src/44.txt
    cp src/44.txt dest/44.txt
    echo 45 > src/45.txt
    cp src/45.txt dest/45.txt
    echo 46 > src/46.txt
    cp src/46.txt dest/46.txt
    echo 47 > src/47.txt
    cp src/47.txt dest/47.txt
    echo 48 > src/48.txt
    cp src/48.txt dest/48.txt
    echo 49 > src/49.txt
    cp src/49.txt dest/49.txt
    echo 50 > src/50.txt
    cp src/50.txt dest/50.txt
    echo 51 > src/51.txt
    cp src/51.txt dest/51.txt
    echo 52 > src/52.txt
    cp src/52.txt dest/52.txt
    echo 53 > src/53.txt
    cp src/53.txt dest/53.txt
    echo 54 > src/54.txt
    cp src/54.txt dest/54.txt
    echo 55 > src/55.txt
    cp src/55.txt dest/55.txt
    echo 56 > src/56.txt
    cp src/56.txt dest/56.txt
    echo 57 > src/57.txt
    cp src/57.txt dest/57.txt
    echo 58 > src/58.txt
    cp src/58.txt dest/58.txt
    echo 59 > src/59.txt
    cp src/59.txt dest/59.txt
    echo 60 > src/60.txt
    cp src/60.txt dest/60.txt
    echo 61 > src/61.txt
    cp src/61.txt dest/61.txt
    echo 62 > src/62.txt
    cp src/62.txt dest/62.txt
    echo 63 > src/63.txt
    cp src/63.txt dest/63.txt
    echo 64 > src/64.txt
    cp src/64.txt dest/64.txt
    echo 65 > src/65.txt
    cp src/65.txt dest/65.txt
    echo 66 > src/66.txt
    cp src/66.txt dest/66.txt
    echo 67 > src/67.txt
    cp src/67.txt dest/67.txt
    echo 68 > src/68.txt
    cp src/68.txt dest/68.txt
    echo 69 > src/69.txt
    cp src/69.txt dest/69.txt
    echo 70 > src/70.txt
    cp src/70.txt dest/70.txt
    echo 71 > src/71.txt
    cp src/71.txt dest/71.txt
    echo 72 > src/72.txt
    cp src/72.txt dest/72.txt
    echo 73 > src/73.txt
    cp src/73.txt dest/73.txt
    echo 74 > src/74.txt
    cp src/74.txt dest/74.txt
    echo 75 > src/75.txt
    cp src/75.txt dest/75.txt
    echo 76 > src/76.txt
    cp src/76.txt dest/76.txt
    echo 77 > src/77.txt
    cp src/77.txt dest/77.txt
    echo 78 > src/78.txt
    cp src/78.txt dest/78.txt
    echo 79 > src/79.txt
    cp src/79.txt dest/79.txt
    echo 80 > src/80.txt
    cp src/80.txt dest/80.txt
    echo 81 > src/81.txt
    cp src/81.txt dest/81.txt
    echo 82 > src/82.txt
    cp src/82.txt dest/82.txt
    echo 83 > src/83.txt
    cp src/83.txt dest/83.txt
    echo 84 > src/84.txt
    cp src/84.txt dest/84.txt
    echo 85 > src/85.txt
    cp src/85.txt dest/85.txt
    echo 86 > src/86.txt
    cp src/86.txt dest/86.txt
    echo 87 > src/87.txt
    cp src/87.txt dest/87.txt
    echo 88 > src/88.txt
    cp src/88.txt dest/88.txt
    echo 89 > src/89.txt
    cp src/89.txt dest/89.txt
    echo 90 > src/90.txt
    cp src/90.txt dest/90.txt
    echo 91 > src/91.txt
    cp src/91.txt dest/91.txt
    echo 92 > src/92.txt
    cp src/92.txt dest/92.txt
    echo 93 > src/93.txt
    cp src/93.txt dest/93.txt
    echo 94 > src/94.txt
    cp src/94.txt dest/94.txt
    echo 95 > src/95.txt
    cp src/95.txt dest/95.txt
    echo 96 > src/96.txt
    cp src/96.txt dest/96.txt
    echo 97 > src/97.txt
    cp src/97.txt dest/97.txt
    echo 98 > src/98.txt
    cp src/98.txt dest/98.txt
    echo 99 > src/99.txt
    cp src/99.txt dest/99.txt
    

    体验make的美好

    假设现在需要一个最终的目标程序,其将所有这些文件的内容合在一起输出到一个名为kitty的文件中:

    kitty: $(destfiles)
    	@# Remember, $< is the input file, but $^ is ALL the input files.
    	@# Cat them into the kitty.
    	cat $^ > kitty
    

    输入make kitty cat kitty, 终端输出:

    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    

    修改其中一个源文件: vi src/25.txt, 将其内容改成: file 25.txt is changed!
    再次执行 make kitty cat kitty, 发现终端输出的 25 变成了 file 25.txt is changed!
    make的妙处就在于,其不会每次重新生成所有源文件,而只会重新构建源文件发生变化的那个目标文件。

    通行做法:用于测试的目标 test

    test: kitty
    	@echo "miao" && echo "tests all pass!"
    

    通常都会在makefile中加入test。此处将kitty作为先决条件,也就是kitty必须存在才能通过测试。

    通行做法:用于清理的目标 clean

    clean:
    	rm -rf *.txt src dest kitty
    

    将make生成的所有东西删除。

    make 发生错误

    make中只要有一条命令返回非零值,就会停止执行。加入以下内容:

    .PHONY: badkitty
    badkitty:
    	$(MAKE) kitty # The special var $(MAKE) means "the make currently in use"
    	false # <-- this will fail
    	echo "should not get here"
    

    输入:make badkitty, 终端输出:

    /Library/Developer/CommandLineTools/usr/bin/make kitty # The special var /Library/Developer/CommandLineTools/usr/bin/make means "the make currently in use"
    cat dest/0.txt dest/1.txt dest/2.txt dest/3.txt dest/4.txt dest/5.txt dest/6.txt dest/7.txt dest/8.txt dest/9.txt dest/10.txt dest/11.txt dest/12.txt dest/13.txt dest/14.txt dest/15.txt dest/16.txt dest/17.txt dest/18.txt dest/19.txt dest/20.txt dest/21.txt dest/22.txt dest/23.txt dest/24.txt dest/25.txt dest/26.txt dest/27.txt dest/28.txt dest/29.txt dest/30.txt dest/31.txt dest/32.txt dest/33.txt dest/34.txt dest/35.txt dest/36.txt dest/37.txt dest/38.txt dest/39.txt dest/40.txt dest/41.txt dest/42.txt dest/43.txt dest/44.txt dest/45.txt dest/46.txt dest/47.txt dest/48.txt dest/49.txt dest/50.txt dest/51.txt dest/52.txt dest/53.txt dest/54.txt dest/55.txt dest/56.txt dest/57.txt dest/58.txt dest/59.txt dest/60.txt dest/61.txt dest/62.txt dest/63.txt dest/64.txt dest/65.txt dest/66.txt dest/67.txt dest/68.txt dest/69.txt dest/70.txt dest/71.txt dest/72.txt dest/73.txt dest/74.txt dest/75.txt dest/76.txt dest/77.txt dest/78.txt dest/79.txt dest/80.txt dest/81.txt dest/82.txt dest/83.txt dest/84.txt dest/85.txt dest/86.txt dest/87.txt dest/88.txt dest/89.txt dest/90.txt dest/91.txt dest/92.txt dest/93.txt dest/94.txt dest/95.txt dest/96.txt dest/97.txt dest/98.txt dest/99.txt > kitty
    false # <-- this will fail
    make: *** [badkitty] Error 1
    

    参考资料

    Makefile

  • 相关阅读:
    10. Regular Expression Matching
    9. Palindrome Number (考虑负数的情况)
    8. String to Integer (整数的溢出)
    7. Reverse Integer (整数的溢出)
    LeetCode Minimum Size Subarray Sum
    LeetCode Course Schedule II
    Linux 文件缓存 (一)
    LeetCode Tries Prefix Tree
    Linux : lsof 命令
    LeetCode Binary Tree Right Side View
  • 原文地址:https://www.cnblogs.com/mrlonely2018/p/15485488.html
Copyright © 2011-2022 走看看