• Makefile语法


    1. 批注:以 # 开头的即为批注。
    2.变量宣告:(有人称之为宏)
    注意在,在变量=前后必须要加上空白,而变量名称为大小写相异。利用 MACRO = 来取消该变数。

    3 := 语法

    注意到,make 会将整个 Makefile 展开后,再决定变数的值。也就是说,变量的值将会是整个 Mackfile 中最后被指定的值。例:

    x = foo
    y = $(x) bar
    x = xyz
    # y 的值为 xyz bar

    在上例中,y 的值将会是 xyz bar,而不是 foo bar。

    您可以利用 := 来避开这个问题。:= 表示变量的值决定于它在 Makefile 中的位置,而不是整个 Makefile 展开后最终的值。

    一些常见的自动化变量说明如下:
    (1) $@ ——目标文件的名称;
    (2) $^ ——所有的依赖文件,以空格分开,不包含重复的依赖文件;
    (3) $< ——第一个依赖文件的名称。

    (4)$* :代表 tragets 所指定的档案,但不包含扩展名。



    示例:
    main:main.c sort.o
    gcc main.c sort.o -o main
    表示为简洁的就是:
    main:main.c sort.o
    gcc $^ -o $@

     

    子目录:

    如果该项目有多个目录,且每一个目录中都有 Makefile,则利用以下指令来进入子目录并进行编译:

    cd dir;$(MAKE)

    例:

    SUBDIRS = dir1 dir2 dir3
    all:
            for i in $(SUBDIRS); do
                    (cd $$i; make);
            done
    clean:
            for i in $(SUBDIRS); do
                    (cd $$i; make clean);
            done
    install:
            for i in $(SUBDIRS); do
                    (cd $$i; make install);
            done

    特别字符:

    @:不要显示执行的指令。

    -:表示即使该行指令出错,也不会中断执行。

    例:

    .PHONY: clean
    clean:
        @echo "Clean..."
        -rm *.o

    因为 make 会一行一行将正在执行的 Commands 显示在屏幕上,但您可以利用 @ 来暂时关闭这个功能。

    而 make 只要遇到任何错误就会中断执行。但像是在进行 clean 时,也许根本没有任何档案可以 clean,因而 rm 会传回错误值,因而导致 make 中断执行。我们可以利用 - 来关闭错误中断功能,让 make 不会因而中断。

    规则:(Rule)

    指示 make 如何进行编译。

    主要语法:

    target: dependencies
    <Tab>Commands

    target: dependencies; Commands
    <Tab>Commands

    Rule 指示了 make 如何建立 target;及何时要重新建立 target。

    target:所要建立的档案
    dependencies:相依项目。make 会据此决定是否要重新编译 target。
    Commands:建立 target 的指令。

    在 Makefile 里并没有限定 Rule 的先后顺序。但默认上,make 会参考 all 这个目标项目,并依据它的 dependencies 来决定要建立哪些项目。若没有 all 项目,则会采用 Makefile 里的第一个项目。

    target:(目标项目)

    这个项目所要建立的档案,必须以 : 结尾。例:

    foo.o: common.h
        gcc -c foo.c

    其中,foo.o 是这个项目要建立的档案;common.h 是相依性的项目/档案;而 gcc -c foo.c 则为要产生这个项目所要执行的指令。
    make 在编译时,若发现 target 比较新,也就是 dependencies 都比 target 旧,那么将不会重新建立 target,如此可以避免不必要的编译动作。
    若该项目并非档案,则为 fake 项目。如此一来将不会建立 target 档案。但为了避免 make 有时会无去判断 target 是否为档案或 fake 项目,建议利用 .PHONY 来指定该项目为 fake 项目。例:

    .PHONY: clean
    clean:
        rm *.o

    在上例中,若不使用 .PHONY 来指定 clean 为 fake 项目的话,若目录中同时存在了一个名为 clean 的档案,则 clean 这个项目将被视为要建立 clean 这个档案,但 clean 这个项目却又没有任何的 dependencies,也因此,clean 项目将永远被视为 up-to-date,永远不会被执行

    因为利用了 .PHONY 来指定 clean 为 fake 项目,所以 make 不会去检查目录中是否存在了一个名为 clean 的档案。如此也可以提升 make 的执行效率。

    其它类以 .PHONY 的语法请参考:

    GNU `make': 4.9 Special Built-in Target Names

    另外,如果某个非 fake 项目里的 dependencies 包含了 fake 项目的话,因为 make 一定会执行 fake 项目,这样一来,这个非 fake 项目一定也会被执行。这可能不是理想的做法。

    dependencies:(相依性项目,以空白间隔)

    dependencies 是指定在建立 target 之前,必须先检查的项目。可以不指定。例:

    foo.o: common.h
        gcc -c foo.c

    上例中是指:检查 common.h。如果它的建立日期比 foo.o 新,就执行 gcc -c foo.c 来重新产生 foo.o。也就是说,可以依需求建立 dependencies,即使它和 target 一点关系也没有。

    相依性项目可以是 Makefile 中其它的 target。也因此,在建立该 target 之前,它会先检查在 dependencies 里所指定的所有 target。

    Commands:(即为要执行的 Shell 指令)

    必须以 <Tab> 开头。使用 Shell Script 语法。在 Makefile 里,只要以 <Tab> 开头都将会被视为 Shell Script 执行。

    每条法则必须写在同一行。每条 Command 会启动一个新的 Shell,预设为 /bin/sh。若执行完某条 Command 但传回了错误值,make 就会中断执行。

    因为每条 Command 会启动一个新的 Shell,所以有时执行的指令必须写在同一行,像是使用 if 来进行条件判断,此时可以用 ; 来分隔指令。例:

    all:
        if [ -f foo ];
            then rm foo;
        fi

    而以下是错误示范:

    all:
        cd subdir; $(MAKE)

    这时因为 make 只会检查最后一个指令的传回值,所以在以上指令中,即使 subdir 不存在,但 make 并不会因而中断执行,并会继续执行 $(MAKE) 指令,而产生了不可预期的结果。
    为了避免这个问题,可以利用 && 来检查其中某个指令是否成功执行,再决定是否执行下个指令。例:

    all:
        cd subdir && $(MAKE)

  • 相关阅读:
    Codeforces-754D Fedor and coupons
    LightOJ
    LightOJ
    LightOJ
    LightOJ
    POJ
    HDU
    HDU
    HDU-2159
    方法的重写
  • 原文地址:https://www.cnblogs.com/cheng07045406/p/3521273.html
Copyright © 2020-2023  润新知