我是靠谱客的博主 灵巧方盒,最近开发中收集的这篇文章主要介绍Makefile工具的工作原理,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

如果您想在更新某些文件时运行或更新任务,该make实用程序可以派上用场。该make实用程序需要一个文件,Makefile(或makefile),它定义了要执行的任务集。您可能习惯于make从源代码编译程序。大多数开源项目用于make编译最终的可执行二进制文件,然后可以使用make install.

在本文中,我们将探索makeMakefile使用基本和高级示例。在开始之前,请确保make已安装在您的系统中。

基本示例

让我们从在终端上打印经典的“Hello World”开始。myproject创建一个包含具有以下内容的文件的空目录Makefile

say_hello:
        echo "Hello World"

make现在通过在目录中键入来运行该文件myproject。输出将是:

make
echo "Hello World"
你好世界

在上面的示例中,say_hello与在任何编程语言中一样,它的行为类似于函数名称。这称为目标先决条件或依赖遵循目标。为了简单起见,我们没有在这个例子中定义任何先决条件。该命令echo "Hello World"称为配方。配方使用先决条件来制作目标。目标、先决条件和配方一起构成规则

总而言之,以下是典型规则的语法:

 
目标:先决条件
< TAB >配方

例如,目标可能是依赖于先决条件(源文件)的二进制文件。另一方面,先决条件也可以是依赖于其他依赖项的目标:

 
final_target: sub_target final_target.c
        Recipe_to_create_final_target

sub_target: sub_target.c
        配方_to_create_sub_target

目标不一定是文件;它可能只是食谱的名称,如我们的示例所示。我们称这些为“虚假目标”。

回到上面的例子,当被执行时,会显示make整个命令,然后是实际的命令输出。echo "Hello World"我们通常不希望这样。要抑制回显实际命令,我们需要echo从以下内容开始@

 
say_hello :
        @echo "Hello World"

现在尝试再次运行make。输出应该只显示这个:

 
$make
Hello World

让我们添加一些更多的虚假目标:generateclean添加到Makefile

 
say_hello:
        @echo Hello World" generate: @echo "Creating empty text files..." touch file- { .. 10 .txt clean : @echo "正在清理... rm * .txt


       
       


       
       

make如果我们尝试在更改后运行,则say_hello只会执行目标。那是因为只有 makefile 中的第一个目标是默认目标。通常称为默认目标all,这就是您在大多数项目中将其视为第一个目标的原因。all调用其他目标是责任。我们可以使用一个名为.DEFAULT_GOAL.

让我们将其包含在我们的 makefile 的开头:

 
 
 
 
.DEFAULT_GOAL := generate

generate这将默认运行目标:

 
make
创建空文本文件...
touch file- 1 .. 10 } .txt

顾名思义,假目标.DEFAULT_GOAL一次只能运行一个目标。这就是为什么大多数 makefile 包含all一个可以根据需要调用任意多个目标的目标。

让我们包含虚假目标all并删除.DEFAULT_GOAL

 
all: say_hello generate say_hello

:
        @echo "Hello World" generate: @echo "Creating empty text files..." touch file- 1 .. 10 } .txt clean: @echo "正在清理..." rm * .文本


       
       


       
       

在运行之前make,让我们包含另一个特殊的虚假目标,.PHONY我们在其中定义所有不是文件的目标。make将运行其配方,而不管具有该名称的文件是否存在或其最后修改时间是什么。这是完整的生成文件:

 
.PHONY: all say_hello generate clean all :

say_hello generate

say_hello:
        @echo "Hello World" generate: @echo " Creating empty text files..." touch file- { .. 10 .txt clean : @echo "清理中..." rm * .txt


       
       


       
       

应该make调用say_hellogenerate

 
make
Hello World
创建空文本文件...
touch file- 1 .. 10 } .txt

最好不要调用cleanall将其作为第一个目标。clean当需要清洁作为第一个参数时,应该手动调用make

 
make clean
正在清理...
rm * .txt

现在您已经了解了基本 makefile 的工作原理以及如何编写简单的 makefile,让我们看一些更高级的示例。

进阶范例

变量

跳到内容

在上面的   示例中,大多数目标值和先决条件值是硬编码的,但在实际项目中,这些值被替换为变量和模式。在 makefile 中定义变量的最简单方法是使用=运算符。例如,将命令分配gcc给变量CC

 
 
 
 
CC = gcc

这也称为递归扩展变量,它在如下所示的规则中使用:

 
你好:hello.c
    ${CC} hello.c -o你好

正如您可能已经猜到的那样,配方在传递到终端时展开如下:

gcc hello.c -o hello

${CC}都是$(CC)对 call 的有效引用gcc。但是,如果有人试图将一个变量重新分配给自己,则会导致无限循环。让我们验证一下:

 
CC = gcc
CC = ${CC}

all:
    @echo {CC}

运行make将导致:

 
make
Makefile: 8 : ***递归变量“CC”引用自身最终。停止。

为了避免这种情况,我们可以使用:=运算符(也称为简单扩展变量)。运行下面的 makefile 应该没有问题:

 
CC := gcc CC
:= ${CC}

all:
    @echo ${CC}

模式和功能

下面的 makefile 可以通过使用变量、模式和函数来编译所有 C 程序。让我们逐行探索它:

 
# Usage:
# make # compile all binary
# make clean # remove ALL binaries and objects

.PHONY = all clean

CC = gcc # 编译器使用

LINKERFLAG = -lm

SRCS := $(wildcard *.c)
BINS := $(SRCS :%.c=%)

all: ${BINS}

%: %.o
        @echo "Checking.."
        ${CC} ${LINKERFLAG} $< -o $@

%.o: %.c
        @echo "Creating对象.."
        ${CC} -c $<

clean:
        @echo "正在清理..."
        rm -rvf *.o ${BINS}
  • 以 开头的行#是注释。

  • .PHONY = all clean定义虚假目标allclean

  • 变量LINKERFLAG定义要在配方中使用的标志gcc

  • SRCS := $(wildcard *.c):是文件名的功能$(wildcard pattern)之一。在这种情况下,所有具有扩展名的文件都将存储在一个变量中。.cSRCS

  • BINS := $(SRCS:%.c=%):这称为替代参考。在这种情况下,如果SRCS有值'foo.c bar.c'BINS将有'foo bar'

  • all: ${BINS}:虚假目标all将值${BINS}作为单独的目标调用。

  • 规则:

     
      
    % : % .o
      echo "正在检查.."
      ${CC} ${LINKERFLAG} $ & lt; -o $ @

    让我们看一个例子来理解这个规则。假设foo是 中的值之一${BINS}。然后%将匹配foo%可以匹配任何目标名称)。以下是扩展形式的规则:

     
      
    foo: foo.o
      echo "正在检查.."
      gcc -lm foo.o -o foo

    如图所示,%被替换为foo$<替换为foo.o$<被模式化以匹配先决条件并$@匹配目标。将为中的每个值调用此规则${BINS}

  • 规则:

     
      
    % .o: % .c
      @echo "创建对象.." ${CC} -c $ lt ;
     

    先前规则中的每个先决条件都被视为此规则的目标。以下是扩展形式的规则:

     
      
    foo.o : foo.c
      @echo "Creating object.." gcc -c foo.c
     
  • 最后,我们删除 target 中的所有二进制文件和目标文件clean

下面是上面的 makefile 的重写,假设它被放置在具有单个文件的目录中foo.c:

 
# Usage:
# make # compile all binary
# make clean # remove ALL binaries and objects

.PHONY = all clean

CC = gcc # 编译器使用

LINKERFLAG = -lm

SRCS := foo.c
BINS := foo

all: foo foo

: foo .o
        @echo "正在检查.."
        gcc -lm foo.o -o foo

foo.o: foo.c
        @echo "正在创建对象.."
        gcc -c foo.c

clean:
        @echo "正在清理..."
        rm -rvf foo.o foo

有关 makefile 的更多信息,请参阅GNU Make 手册,其中提供了完整的参考和示例。

您还可以阅读我们的GNU Autotools 简介,了解如何为您的编码项目自动生成 makefile。

最后

以上就是灵巧方盒为你收集整理的Makefile工具的工作原理的全部内容,希望文章能够帮你解决Makefile工具的工作原理所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(42)

评论列表共有 0 条评论

立即
投稿
返回
顶部