博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
makefile 无法工作_什么是Makefile,它如何工作?
阅读量:2524 次
发布时间:2019-05-11

本文共 7258 字,大约阅读时间需要 24 分钟。

makefile 无法工作

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

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

基本例子

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

say_hello:     
       
echo
"Hello World"

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

$      
make
echo
"Hello World"
Hello World

在上面的示例中,在任何编程语言中, say_hello行为都类似于函数名。 这称为目标先决条件依赖项遵循目标。 为了简单起见,在此示例中我们没有定义任何先决条件。 命令echo "Hello World"称为配方配方使用先决条件作为目标 。 目标,先决条件和配方共同构成了规则

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

target: prerequisites     
< TAB
> recipe

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

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

让我们添加更多伪造目标: generateclean Makefile

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 := generate

这将默认运行目标generate

$      
make
Creating empty text files...
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
"Cleaning up..."
       
rm
* .txt

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

.PHONY: all say_hello generate clean     
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

make应该调用say_hellogenerate

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

这是一个很好的做法不叫cleanall或把它作为第一目标。 clean应首先手动调用clean来作为make的第一个参数:

$      
make clean
Cleaning up...
rm
* .txt

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

进阶范例

变数

在makefile中定义变量的最简单方法是使用=运算符。 例如,将命令gcc分配给变量CC

CC = gcc

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

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

您可能已经猜到了,配方在传递到终端时会如下扩展:

gcc hello.c -o hello

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

CC =      
gcc
CC =
${CC}
all:
   
@
echo
${CC}

运行make将导致:

$      
make
Makefile:
8 :
*** Recursive variable
'CC' references itself
( eventually
) .  Stop.

为了避免这种情况,我们可以使用:=运算符(也称为简单扩展变量 )。 运行下面的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                        # compiler to use
LINKERFLAG = -lm
SRCS := $(wildcard *.c)
BINS := $(SRCS:%.c=%)
all: ${BINS}
%: %.o
        @echo "Checking.."
        ${CC} ${LINKERFLAG} $< -o $@
%.o: %.c
        @echo "Creating object.."
        ${CC} -c $<
clean:
        @echo "Cleaning up..."
        rm -rvf *.o ${BINS}
  • #开头的行是注释。

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

  • 变量LINKERFLAG定义在配方中与gcc一起使用的标志。

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

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

  • all: ${BINS} :假目标将${BINS} all呼叫值作为单个目标。

  • 规则:

    % :        
    % .o
     
    @
    echo
    "Checking.."
     
    ${CC}
    ${LINKERFLAG} $
    & lt;
    -o $
    @

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

    foo: foo.o       
     
    @
    echo
    "Checking.."
     
    gcc
    -lm foo.o
    -o foo

    如图所示, %foo代替。 $<foo.o替换。 $<被图案化以匹配先决条件,而$@匹配目标。 ${BINS}每个值都将调用此规则

  • 规则:

    % .o:        
    % .c
     
    @
    echo
    "Creating object.."
     
    ${CC}
    -c $
    & lt;

    上一条规则中的每个前提条件都被视为该规则的目标。 以下是展开形式的规则:

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

下面是上述makefile的重写,假设它位于具有单个文件foo.c:的目录中foo.c:

# Usage:     
# make        # compile all binary
# make clean  # remove ALL binaries and objects
.PHONY = all clean
CC = gcc                        # compiler to use
LINKERFLAG = -lm
SRCS := foo.c
BINS := foo
all: foo
foo: foo.o
        @echo "Checking.."
        gcc -lm foo.o -o foo
foo.o: foo.c
        @echo "Creating object.."
        gcc -c foo.c
clean:
        @echo "Cleaning up..."
        rm -rvf foo.o foo

有关makefile的更多信息,请参考 ,其中提供了完整的参考资料和示例。

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

翻译自:

makefile 无法工作

转载地址:http://pqdzd.baihongyu.com/

你可能感兴趣的文章
Git报错:insufficient permission for adding an object to repository database .git/objects
查看>>
ajax跨域,携带cookie
查看>>
BZOJ 1600: [Usaco2008 Oct]建造栅栏( dp )
查看>>
洛谷 CF937A Olympiad
查看>>
Codeforces Round #445 C. Petya and Catacombs【思维/题意】
查看>>
用MATLAB同时作多幅图
查看>>
python中map的排序以及取出map中取最大最小值
查看>>
ROR 第一章 从零到部署--第一个程序
查看>>
<form>标签
查看>>
vue去掉地址栏# 方法
查看>>
Lambda03 方法引用、类型判断、变量引用
查看>>
was集群下基于接口分布式架构和开发经验谈
查看>>
MySQL学习——MySQL数据库概述与基础
查看>>
ES索引模板
查看>>
HDU2112 HDU Today 最短路+字符串哈希
查看>>
JPanel重绘
查看>>
图片放大器——wpf
查看>>
SCALA STEP BY STEP
查看>>
cocos2d-x学习笔记
查看>>
MySql中的变量定义
查看>>