MakeFile 常见函数和语法
$(filter-out
makefile 中的$(filter-out
在Makefile中,$(filter-out)
是一个Makefile函数,用于过滤出不符合指定模式的字符串。
语法如下:
$(filter-out pattern...,text)
其中,pattern
是一个模式字符串,可以包含通配符,例如%.o
表示所有以.o
结尾的字符串。
text
是要过滤的字符串列表。
$(filter-out)
函数会返回在text
中不符合任何pattern
的字符串。
以下是一个示例:
objects := foo.o bar.o baz.c
# 过滤出不以".c"结尾的字符串
filtered_objects := $(filter-out %.c, $(objects))
all:
@echo $(filtered_objects)
在上面的示例中,objects
变量包含了foo.o
、bar.o
和baz.c
三个字符串。然后使用$(filter-out %.c, $(objects))
过滤出不以.c
结尾的字符串,结果存储在filtered_objects
变量中。在all
目标中,通过@echo
命令输出filtered_objects
的值,结果为foo.o bar.o
。
$(call
在Makefile中,$(call)
是一个Makefile函数,用于调用自定义的函数。
语法如下:
$(call function-name,arguments)
其中,function-name
是自定义函数的名称。
arguments
是传递给函数的参数列表,参数之间用逗号分隔。
$(call)
函数会根据指定的函数名称和参数列表来调用对应的函数,并返回函数的结果。
以下是一个示例:
# 定义一个自定义函数,用于连接两个字符串
define concat
$(1)$(2)
endef
# 调用自定义函数
result := $(call concat,Hello, World)
all:
@echo $(result)
在上面的示例中,首先使用define
关键字定义了一个名为concat
的自定义函数,该函数接受两个参数,并将它们连接起来。
然后,在all
目标中,使用$(call concat,Hello, World)
调用了concat
函数,并将结果存储在result
变量中。
最后,通过@echo
命令输出result
的值,结果为Hello World
。
请注意,$(call)
函数可以用于调用任何自定义函数,不仅限于连接字符串的示例。您可以根据自己的需求定义和调用自己的函数。
$(subst
在Makefile中,$(subst)
是一个Makefile函数,用于在字符串中进行替换操作。
语法如下:
$(subst from,to,text)
其中,from
是要被替换的字符串,to
是要替换成的字符串,text
是要进行替换操作的文本。
$(subst)
函数会在text
中将所有出现的from
字符串替换为to
字符串,并返回替换后的结果。
以下是一个示例:
message := Hello, world!
new_message := $(subst world,Makefile,$(message))
all:
@echo $(new_message)
在上面的示例中,message
变量包含了一个字符串Hello, world!
。
然后,使用$(subst world,Makefile,$(message))
将message
中的world
字符串替换为Makefile
,结果存储在new_message
变量中。
在all
目标中,通过@echo
命令输出new_message
的值,结果为Hello, Makefile!
。
请注意,$(subst)
函数只会替换字符串中的第一个匹配项。如果要替换所有匹配项,可以使用$(patsubst)
函数结合通配符来实现。
$(patsubst
在Makefile中,$(patsubst)
是一个Makefile函数,用于进行模式匹配和替换操作。
语法如下:
$(patsubst pattern,replacement,text)
其中,pattern
是要匹配的模式,replacement
是要替换成的字符串,text
是要进行模式匹配和替换操作的文本。
$(patsubst)
函数会在text
中查找符合pattern
模式的字符串,并将其替换为replacement
字符串,并返回替换后的结果。
pattern
可以包含通配符%
,用于匹配任意字符序列。
以下是一个示例:
sources := file1.c file2.cpp file3.cxx
objects := $(patsubst %.c,%.o,$(sources))
all:
@echo $(objects)
在上面的示例中,sources
变量包含了一组源文件名。
然后,使用$(patsubst %.c,%.o,$(sources))
将sources
中以.c
结尾的文件名替换为以.o
结尾的目标文件名,并将结果存储在objects
变量中。
在all
目标中,通过@echo
命令输出objects
的值,结果为file1.o file2.cpp file3.cxx
。
请注意,$(patsubst)
函数可以进行多次替换,只要在pattern
中使用多个通配符%
即可。这使得它非常灵活,可以适应各种模式匹配和替换的需求。
$(wildcard
在Makefile中,$(wildcard)
是一个Makefile函数,用于获取指定模式下的文件列表。
语法如下:
$(wildcard pattern)
其中,pattern
是要匹配的文件模式。
$(wildcard)
函数会在当前目录下查找符合pattern
模式的文件,并返回文件列表。
以下是一个示例:
sources := $(wildcard *.c)
all:
@echo $(sources)
在上面的示例中,$(wildcard *.c)
会在当前目录下查找所有以.c
结尾的文件,并将文件列表存储在sources
变量中。
在all
目标中,通过@echo
命令输出sources
的值,结果为当前目录下所有以.c
结尾的文件名。
$(wildcard)
函数还可以与其他Makefile函数结合使用,例如可以与$(patsubst)
函数一起使用,对文件列表进行模式匹配和替换操作。
请注意,$(wildcard)
函数只会在当前目录下查找文件,不会递归查找子目录。如果需要递归查找文件,可以使用find
命令或其他工具来实现。
$(sort
在Makefile中,$(sort)
是一个Makefile函数,用于对字符串列表进行排序。
语法如下:
$(sort list)
其中,list
是要排序的字符串列表。
$(sort)
函数会对list
中的字符串进行排序,并返回排序后的结果。
以下是一个示例:
names := John Mary Alice Bob
sorted_names := $(sort $(names))
all:
@echo $(sorted_names)
在上面的示例中,names
变量包含了一组姓名。
然后,使用$(sort $(names))
对names
中的姓名进行排序,并将排序后的结果存储在sorted_names
变量中。
在all
目标中,通过@echo
命令输出sorted_names
的值,结果为Alice Bob John Mary
。
请注意,$(sort)
函数会按照字母顺序对字符串进行排序。如果有重复的字符串,它们将被视为一个字符串处理。
此外,$(sort)
函数还可以与其他Makefile函数结合使用,例如可以与$(wildcard)
函数一起使用,对文件列表进行排序操作。
总之,$(sort)
函数可以帮助我们对字符串列表进行排序,使其更有序和可读性。
$(dir
在Makefile中,$(dir)
是一个Makefile函数,用于获取路径中的目录部分。
语法如下:
$(dir names)
其中,names
是要获取目录部分的路径。
$(dir)
函数会提取names
中的目录部分,并返回目录部分的结果。
以下是一个示例:
paths := src/main.c include/header.h
directories := $(dir $(paths))
all:
@echo $(directories)
在上面的示例中,paths
变量包含了一组路径。
然后,使用$(dir $(paths))
对paths
中的路径进行处理,提取出路径中的目录部分,并将结果存储在directories
变量中。
在all
目标中,通过@echo
命令输出directories
的值,结果为src/ include/
。
请注意,$(dir)
函数会保留路径中的末尾斜杠。如果路径已经以斜杠结尾,则目录部分将保留斜杠;如果路径没有斜杠结尾,则目录部分将不包含斜杠。
此外,$(dir)
函数还可以与其他Makefile函数结合使用,例如可以与$(wildcard)
函数一起使用,获取文件列表中的目录部分。
总之,$(dir)
函数可以帮助我们从路径中提取出目录部分,方便进行路径操作和处理。
.PHONY
在Makefile中,.PHONY
是一个特殊的目标,用于声明伪目标(Phony Target)。
伪目标是指在Makefile中定义的目标,但其实际上并不对应一个真正的文件。相反,它们只是用来执行一系列命令或其他目标的名称。
使用.PHONY
可以告诉Make工具,这个目标是伪目标,不需要检查对应的文件是否存在或更新。
语法如下:
.PHONY: target1 target2 ...
其中,target1 target2 ...
是要声明为伪目标的目标名称。
以下是一个示例:
.PHONY: clean all
all: program
program:
gcc -o program main.c
clean:
rm -f program
在上面的示例中,.PHONY
声明了两个伪目标:clean
和all
。
all
目标依赖于program
目标,program
目标执行了一个编译命令来生成可执行文件。
clean
目标用于删除生成的可执行文件。
通过声明.PHONY
,我们告诉Make工具,clean
和all
是伪目标,不需要检查对应的文件是否存在或更新。
这样,我们可以在命令行中直接执行make clean
或make all
,而不必担心是否存在对应的文件。
总之,.PHONY
是一个用于声明伪目标的指令,它可以在Makefile中指定一些不对应实际文件的目标。
$@
在Makefile中,$@
是一个自动化变量,表示当前规则中的目标文件名。
当Make工具执行一个规则时,$@
会被替换为当前规则中的目标文件名。
以下是一个示例:
all: program
program: main.c
gcc -o $@ $<
在上面的示例中,all
是顶级目标,它依赖于program
目标。
program
目标定义了一个规则,使用gcc
编译main.c
文件,并将输出文件命名为$@
。
当执行make
命令时,Make工具会根据依赖关系执行规则。在执行program
规则时,$@
会被替换为program
,即表示当前规则中的目标文件名。
这样,gcc -o $@ $<
会被展开为gcc -o program main.c
,从而编译main.c
文件并生成可执行文件program
。
总之,$@
是一个自动化变量,用于表示当前规则中的目标文件名。它可以在规则的命令中使用,方便地引用目标文件名。
$<
在Makefile中,$<
是一个自动化变量,表示当前规则中的第一个依赖文件的名称。
当Make工具执行一个规则时,$<
会被替换为当前规则中的第一个依赖文件的名称。
以下是一个示例:
all: program
program: main.c helper.c
gcc -o $@ $<
在上面的示例中,all
是顶级目标,它依赖于program
目标。
program
目标定义了一个规则,它有两个依赖文件:main.c
和helper.c
。在规则的命令中,使用gcc
编译$<
,即表示当前规则中的第一个依赖文件。
当执行make
命令时,Make工具会根据依赖关系执行规则。在执行program
规则时,$<
会被替换为main.c
,即表示当前规则中的第一个依赖文件的名称。
这样,gcc -o $@ $<
会被展开为gcc -o program main.c
,从而编译main.c
文件并生成可执行文件program
。
总之,$<
是一个自动化变量,用于表示当前规则中的第一个依赖文件的名称。它可以在规则的命令中使用,方便地引用依赖文件的名称。