IDC资讯

质量为本、客户为根、勇于拼搏、务实创新

< 返回IDC资讯列表

Linux中Makefile作用在哪里

发布时间:2022-06-27

桂哥网络将与你分享在Linux中使用Makefile。相信大部分人都不太了解,分享这篇文章,供大家参考。希望你看完这篇文章后收获很大。我们一起来看看。

用这个方便的工具来更有效的运行和编译你的程序

Makefile用于自动编译和链接。一个项目由许多文件组成,每个文件的改变都会导致项目的重新链接,但不是所有的文件都需要重新编译。makefile可以记录文件信息,并决定哪些文件需要在链接时重新编译!

Make工具通常在某些源文件更改后需要运行或更新任务时使用。Make工具需要读取一个makefile(或Makefile),其中定义了一系列需要执行的任务。您可以使用make将源代码编译成可执行程序。大多数开源项目将使用make来编译最终的二进制文件,然后使用make install命令来执行安装。

本文将通过一些基本和高级的例子展示如何使用make和Makefile。开始之前,请确保您的系统上安装了。

基本示例

还是从印《Hello World》开始吧。首先,创建一个名为myproject的目录,并在该目录下创建一个新的Makefile。文件内容是:

say_hello:

Echo'HelloWorld '在myproject目录中执行make,输出如下:

$make

回声' HelloWorld '

HelloWorld在上面的例子中,“say_hello”类似于其他编程语言中的函数名。这叫目标。跟随这个目标的是预设的条件或依赖。为简单起见,我们没有在本例中定义预设条件。回声“你好,世界”命令被称为食谱。这些步骤是基于预设条件实现目标的。目标、预设条件、步骤共同构成一个规则。

总而言之,一个典型规则的语法是:

目标:预设条件

制表符步骤

例如,目标可以是基于预设条件的二进制文件(源代码)。另一方面,预设条件也可以是取决于其他预设条件的目标。

final _ target : sub _ target final _ target . c

配方_至_创建_最终_目标

sub_target:sub_target.c

Recipe_to_create_sub_target不是一个文件,而只是步骤的名称,如我们的示例所示。我们称之为“伪目标”

回到上面的例子,在执行make的时候,会显示整个指令echo‘Hello World’,然后就达到了真正的执行结果。如果您不想打印指令本身,您需要在echo之前添加@符号

say_hello:

@echo'HelloWorld '重新运行make,它将只有以下输出:

$make

HelloWorld然后将以下伪目标添加到Makefile:生成并清除:

say_hello:

@echo'HelloWorld '

generate:

@ echo 'Creatingemptytextfiles.'

touchfile-{1.10}.文本文件(textfile)

clean:

@echo'Cleaningup.'

Rm*。然后当我们运行make时,只有say_hello的目标被执行。这是因为Makefile中的第一个目标是默认目标。通常会调用默认目标,这意味着在大多数项目中,您会将所有目标视为第一个目标。所有人都有责任称之为他的目标。我们可以通过使用.DEFAULT_GOAL 作为特殊的伪目标来覆盖默认行为。

补充。Makefile开头的DEFAULT_GOAL:默认_目标:=生成

Make将使用生成作为默认目标:

$make

创建空文本文件.

触摸文件-{1.10}.txt顾名思义。默认目标伪目标只能定义一个目标。这就是为啥很多Makefile都包含了目标all,这样就可以调用多个目标。

删除。默认_转到下面

AL,增加 all 目标:

all:say_hellogenerate
say_hello:
@echo"HelloWorld"
generate:
@echo"Creatingemptytextfiles..."
touchfile-{1..10}.txt
clean:
@echo"Cleaningup..."
rm*.txt

运行之前,我们再增加一些特殊的伪目标。.PHONY 用来定义这些不是文件的目标。make 会默认调用这些伪目标下的步骤,而不去检查文件名是不是存在或最后修改日期。完整的 Makefile 如下:

.PHONY:allsay_hellogenerateclean
all:say_hellogenerate
say_hello:
@echo"HelloWorld"
generate:
@echo"Creatingemptytextfiles..."
touchfile-{1..10}.txt
clean:
@echo"Cleaningup..."
rm*.txt

make 命令会调用 say_hello 和 generate:

$make
HelloWorld
Creatingemptytextfiles...
touchfile-{1..10}.txt

clean 不应该被放入 all 中,或者被放入第一个目标中。clean 应当在需要清理时手动调用,调用方法为 make clean

$makeclean
Cleaningup...
rm*.txt

现在你应该已经对 Makefile 有了基础的了解,接下来我们看一些进阶的示例。

进阶示例
变量
在之前的实例中,大部分目标和预置条件是已经固定了的,但在实际项目中,它们通常用变量和模式来代替。

定义变量最简单的方式是使用 = 操作符。例如,将命令 gcc 赋值给变量 CC:

CC=gcc

这被称为递归扩展变量,用于如下所示的规则中:

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

你可能已经想到了,这些步骤将会在传递给终端时展开为:

gcc hello.c -o hello

${CC} 和 $(CC) 都能对 gcc 进行引用。但如果一个变量尝试将它本身赋值给自己,将会造成死循环。让我们验证一下:

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

此时运行 make 会导致:

$make
Makefile:8:***Recursivevariable'CC'referencesitself(eventually).Stop.

为了避免这种情况发生,可以使用 := 操作符(这被称为简单扩展变量)。以下代码不会造成上述问题:

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

模式和函数
下面的 Makefile 使用了变量、模式和函数来实现所有 C 代码的编译。我们来逐行分析下:

#Usage:
#make#compileallbinary
#makeclean#removeALLbinariesandobjects
.PHONY=allclean
CC=gcc#compilertouse
LINKERFLAG=-lm
SRCS:=$(wildcard*.c)
BINS:=$(SRCS:%.c=%)
all:${BINS}
%:%.o
@echo"Checking.."
${CC}${LINKERFLAG}$<-o$@
%.o:%.c
@echo"Creatingobject.."
${CC}-c$<
clean:
@echo"Cleaningup..."
rm-rvf*.o${BINS}

以 # 开头的行是评论
.PHONY = all clean 行定义了 all 和 clean 两个伪目标。
变量 LINKERFLAG 定义了在步骤中 gcc 命令需要用到的参数。
SRCS := $(wildcard *.c):$(wildcard pattern) 是与文件名相关的一个函数。在本示例中,所有 “.c”后缀的文件会被存入 SRCS 变量。
BINS := $(SRCS:%.c=%):这被称为替代引用。本例中,如果 SRCS 的值为 'foo.c bar.c',则 BINS的值为 'foo bar'。
all: ${BINS} 行:伪目标 all 调用 ${BINS} 变量中的所有值作为子目标。
规则:

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

下面通过一个示例来理解这条规则。假定 foo 是变量 ${BINS} 中的一个值。% 会匹配到 foo(%匹配任意一个目标)。下面是规则展开后的内容:

foo:foo.o
@echo"Checking.."
gcc-lmfoo.o-ofoo

如上所示,% 被 foo 替换掉了。$< 被 foo.o 替换掉。$<用于匹配预置条件,$@ 匹配目标。对 ${BINS} 中的每个值,这条规则都会被调用一遍。
规则:

%.o:%.c
@echo"Creatingobject.."
${CC}-c$<

之前规则中的每个预置条件在这条规则中都会都被作为一个目标。下面是展开后的内容:

foo.o:foo.c
@echo"Creatingobject.."
gcc-cfoo.c

最后,在 clean 目标中,所有的二进制文件和编译文件将被删除。
下面是重写后的 Makefile,该文件应该被放置在一个有 foo.c 文件的目录下:

#Usage:
#make#compileallbinary
#makeclean#removeALLbinariesandobjects
.PHONY=allclean
CC=gcc#compilertouse
LINKERFLAG=-lm
SRCS:=foo.c
BINS:=foo
all:foo
foo:foo.o
@echo"Checking.."
gcc-lmfoo.o-ofoo
foo.o:foo.c
@echo"Creatingobject.."
gcc-cfoo.c
clean:
@echo"Cleaningup..."
rm-rvffoo.ofoo

这些和到一起,就是makefile,当然这些功能还太少,可以加上很多别的项目。但宗旨就是:让编译器知道要编译一个文件需要依赖其他的哪些文件。当那些依赖文件有了改变,编译器会自动的发现最终的生成文件已经过时,而重新编译相应的模块。

以上是“Linux中Makefile作用在哪里”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!


TikTok千粉号购买平台:https://tiktokusername.com/