当前位置 主页 > 服务器问题 > Linux/apache问题 >

    Linux里Makefile是什么?它是如何工作的?

    栏目:Linux/apache问题 时间:2019-12-28 14:07

    用这个方便的工具来更有效的运行和编译你的程序
    makefile是用于自动编译和链接的,一个工程有很多文件组成,每一个文件的改变都会导致工程的重新链接-----但是不是所有的文件都需要重新编译,makefile能够纪录文件的信息,决定在链接的时候需要重新编译哪些文件!

    当你需要在一些源文件改变后运行或更新一个任务时,通常会用到 make 工具。make 工具需要读取一个 Makefile(或 makefile)文件,在该文件中定义了一系列需要执行的任务。你可以使用 make 来将源代码编译为可执行程序。大部分开源项目会使用 make 来实现最终的二进制文件的编译,然后使用 make install 命令来执行安装。
    本文将通过一些基础和进阶的示例来展示 make 和 Makefile 的使用方法。在开始前,请确保你的系统中安装了 make。

    基础示例
    依然从打印 “Hello World” 开始。首先创建一个名字为 myproject 的目录,目录下新建 Makefile 文件,文件内容为:

    say_hello:
    echo "Hello World"

    在 myproject 目录下执行 make,会有如下输出:

    $ make
    echo "Hello World"
    Hello World

    在上面的例子中,“say_hello” 类似于其他编程语言中的函数名。这被称之为 目标(target)。在该目标之后的是预置条件或依赖。为了简单起见,我们在这个示例中没有定义预置条件。echo ‘Hello World' 命令被称为 步骤(recipe)。这些步骤基于预置条件来实现目标。目标、预置条件和步骤共同构成一个规则。

    总结一下,一个典型的规则的语法为:

    目标: 预置条件
    <TAB> 步骤

    作为示例,目标可以是一个基于预置条件(源代码)的二进制文件。另一方面,预置条件也可以是依赖其他预置条件的目标。

    final_target: sub_target final_target.c
    Recipe_to_create_final_target
    sub_target: sub_target.c
    Recipe_to_create_sub_target

    目标并不要求是一个文件,也可以只是步骤的名字,就如我们的例子中一样。我们称之为“伪目标”

    再回到上面的示例中,当 make 被执行时,整条指令 echo "Hello World" 都被显示出来,之后才是真正的执行结果。如果不希望指令本身被打印处理,需要在 echo 前添加 @

    say_hello:
    @echo "Hello World"
    
    

    重新运行 make,将会只有如下输出:

    $ make
    Hello World

    接下来在 Makefile 中添加如下伪目标:generate 和 clean:

    say_hello:
    @echo "Hello World"
    generate:
    @echo "Creating empty text files..."
    touch file-{1..10}.txt
    clean:
    @echo "Cleaning up..."
    rm *.txt
    
    

    随后当我们运行 make 时,只有 say_hello 这个目标被执行。这是因为Makefile 中的第一个目标为默认目标。通常情况下会调用默认目标,这就是你在大多数项目中看到 all 作为第一个目标而出现。all 负责来调用它他的目标。我们可以通过 .DEFAULT_GOAL 这个特殊的伪目标来覆盖掉默认的行为。

    在 Makefile 文件开头增加 .DEFAULT_GOAL:

    .DEFAULT_GOAL := generate

    make 会将 generate 作为默认目标:

    $ make
    Creating empty text files...
    touch file-{1..10}.txt
    
    

    顾名思义,.DEFAULT_GOAL 伪目标仅能定义一个目标。这就是为什么很多 Makefile 会包括 all 这个目标,这样可以调用多个目标。
    下面删除掉 .DEFAULT_GOAL,增加 all 目标:

    all: say_hello generate
    say_hello:
    @echo "Hello World"
    generate:
    @echo "Creating empty text files..."
    touch file-{1..10}.txt
    clean:
    @echo "Cleaning up..."
    rm *.txt