这是命令 makepp_functions,可以使用我们的多个免费在线工作站之一在 OnWorks 免费托管服务提供商中运行,例如 Ubuntu Online、Fedora Online、Windows 在线模拟器或 MAC OS 在线模拟器
程序:
您的姓名
makepp_functions -- makepp 中的函数
商品描述
A: 绝对文件名,
绝对文件名_无链接,
断然,
添加前缀,
添加后缀,
和, B: 基名, C: 呼叫, D: 是,
dir_noslash, E: 错误, F: 文件subst,
过滤,
过滤掉,
filter_out_dirs,
查找文件,
find_first_upwards,
查找程序,
查找字符串,
find_upwards,
第一个可用,
第一个字,
foreach, I: 如果,
如果是真的,
推断链接器,
推断对象,
信息, J: 加入, M: 制作,
制作地图,
制造商,
地图,
"mktemp", N: 不目录, O: 只有_生成,
only_nontargets,
only_phony_targets,
only_stale,
only_targets,
或,
起源, P: patsubst,
珀尔,
假,
预建,
打印, R: 真实路径,
相对文件名,
关系到, S: 贝壳,
分类,
跳闸,
副,
后缀, T: 暂时的, W: 警告,
通配符,
字,
词汇表,
话, X: 参数
任何格式为“$(name)”的表达式,其中“name”不是变量的名称,或
“$(name arg1 arg2 arg3)”被解释为函数调用。 名称可能包含字母,
下划线或连字符; 为避免混淆,您可以使用连字符或下划线
可以互换,因为内部连字符转换为下划线。 评估这样的
表达式只是调用 Perl 子例程。 如果“name”前面有“&”,它运行
makepp 进程中该名称的内置命令或脚本,并返回标准
输出。 这需要为 PerlIO 构建 perl。 如果名称未命名函数
它被转换为调用调用。
与变量一样,您可以选择“$(name ...)”或“${name ...}”。 如果你想
嵌入同一个括号,必须成对,其他无所谓:"$(name
...(){..." 或 "${name ...{}(...}"。(但是对于 map 和 perl,第一个结束括号结束
表达式。)加倍允许参数跨越多行。 换行符是
然后将其视为空格,但可能在“定义”中除外。 还有语法“$[name ...]”
或 $[[name ...]],它在阅读 makefile 时被评估,在探索规则之前
和其他构造。
Makepp 有许多可能有用的内置函数。 它支持几乎所有
GNU make 的文本函数(详见 GNU make 的文档),以及它的一些
自己的。 你可以定义 Perl 子程序来做任何你喜欢的事情。 见“子”声明
以及有关扩展 makepp 的部分以获取更多详细信息。
条件 主要工作内容
和 条件 1[,条件 2[,条件 3...]]
and 函数提供“短路”AND 运算。 每个参数是
展开,有序。 如果参数扩展为空字符串,则处理停止并
扩展的结果是空字符串。 如果所有参数都扩展为非
空字符串则扩展的结果是最后一个参数的扩展。
if 细绳, 结果-如果-字符串-非空[, 结果-如果-字符串-空白]
如果是真的 细绳, 结果-如果-字符串-真[, 结果-如果-字符串-假]
“ifeq”等语句的替代。 如果字符串不为空(即
条件为真),则返回第二个参数(“then”子句)(在
变量扩展); 如果字符串为空,则第三个参数(“else”子句)是
回。
例如,
CFLAGS := $(if $(过滤 gcc egcc, $(CC)), -g -Wall, -g)
如果变量 CC 是“gcc”或“egcc”,并且“-g”,则将 CFLAGS 定义为“-g -Wall”
除此以外。 (这是默认构建规则所做的。)
"iftrue" 与 "if" 类似,只是字符串 0 被视为空白。
or 条件 1[,条件 2[,条件 3...]]
or 函数提供“短路”或操作。 每个参数都被扩展,
为了。 如果参数扩展为非空字符串,则处理停止并且
扩展的结果是那个字符串。 如果在所有参数都展开后,所有的
它们是假的(空),那么展开的结果就是空字符串。
文件 和 文件名 主要工作内容
绝对文件名 档
绝对的 档
将相对文件名转换为绝对文件名而不 . or ..。 例如,
“$(absolute_filename xyz.c)”可能会返回“/usr/src/our_project/subdir/xyz.c”。
绝对文件名_nolink 档
实路径 档
与 absolute_filename 类似,但可确保解析符号链接。
基本名 档名
basename 是整个文件名(包含目录),减去和之后的文本
包括上一期。 例如,“$(basename myfile/version-1.0-module.c)”是
“myfile/version-1.0-module”
DIR 档名
提取文件名列表中每个文件的目录部分,包括尾随
削减。 如果文件名中没有目录,则返回“./”。
目录_noslash 文件名
与 "$(dir )" 相同,只是它不返回尾部斜杠。
文件subst 图案, 代替, 话
对文件名执行模式替换。 这与 patsubst 的不同之处在于
当给出目录的备用名称时,它将正确执行(只要
它们在百分号之前)。 例如,
$(filesubst ./src/%.c, %.o, $(通配符 src/*.c))
将与 filesubst 一起使用,但不能与 patsubst 一起使用。
过滤器输出目录 档名
返回所有不引用目录的文件名。
查找文件 文档名称, 径
在指定路径中查找文件,如果没有,则在环境变量 PATH 中查找
指定的。 这对于查找二进制文件或包含文件很有用。 例如,
TCL_INCLUDE := -I$(dir_noslash $(findfile tcl.h, \
/usr/local/stow/tcl-8.4.5-nothread/包括\
/usr/include/tcl8.4 /usr/include/tcl \
/net/na1/tcl8.4a3/include /net/na1/tcl8.4a3/include))
这将定位文件 文件 通过搜索上述所有目录。 绝对的
返回文件的路径。 然后“$(dir_noslash)”提取该目录,它
被放入包含路径。
查找程序 姓名
返回列表中可以在 PATH 中找到的第一个程序。 这很有用
当有多个等效的程序可以使用,而您只想
选择其中之一。 比如这里是几个常用的默认定义
如果你没有在你的 makefile 中放置一个 makepp 提供的变量:
CC = $(find_program gcc egcc pgcc c89 cc) # 和更多,取决于机器
F77 = $(查找程序 f77 g77 fort77)
CXX = $(find_program g++ c++ pg++ cxx CC aCC)
如果没有找到任何程序,"$(find_program)" 返回未找到的字符串,并且
记录未找到的内容。 这通常不会产生一个功能性的 makefile,但是它
将倾向于产生更好的错误消息。 例如,如果你做类似的事情
这个:
%.o : %.c
$(CC) $(输入) -o $(输出)
并且 makepp 在上面的列表中找不到 C 编译器,它会替换为 not-found。
否则,shell 将尝试执行源文件和由此产生的错误
消息可能真的很奇怪。
向上查找 文件名
在目录 ., .., .. 中搜索给定名称的文件/ ..,../../..等,
直到找到文件或到达根目录或找到目录
在不同的文件系统上。 (最后一个要求是为了防止出现问题
自动挂载程序或挂起的网络文件系统。)如果您有 根Makepp文件,这也是
阻止搜索更高的障碍。
例如,如果您有一个包含多级子目录的项目,您可以
在所有的 makefile 中包含这个公共片段(例如,通过使用“include”
陈述):
TOP_LEVEL_INCLUDE_DIR := $(find_upwards 包括)
# 搜索包含该目录的目录
# 包含子目录。
%.o : %.c
$(CC) $(CFLAGS) -I$(TOP_LEVEL_INCLUDE_DIR) -c $(输入) -o $(输出)
“find_upwards”可以帮助解决的另一个问题是定位顶级目录
的一个构建。 像这样定义变量通常很有用:
顶部 := ../../..
如果您有一些仅位于顶级目录中的重要信息。 但
这很难维护,因为不同级别的“..”数量不同
的目录树。 相反,您可以使用“find_upwards”来定位一个文件
已知仅存在于顶级目录中。 例如,假设
文件“LICENSE”仅位于顶级目录中。 那么你可以这样做:
顶部 := $(dir_noslash $(find_upwards LICENSE))
"$(find_upwards LICENSE)" 返回许可证文件的完整路径;
"$(dir_noslash ...)" 去掉文件名,只返回目录。
(注意“include”语句会自动向上搜索文件,所以有
没有必要做这样的事情:
包括 $(find_upwards top_level_rules.mk)
相反,你可以做
包括 top_level_rules.mk
它也能正常工作。)
如果未找到该文件,“find_upwards”将中止构建并显示错误消息。
如果指定多个文件, find_upwards 将搜索第一个,然后
第二个,以此类推。 换句话说,
$(find_upwards 文件 1 文件 2)
相当于
$(find_upwards 文件1) $(find_upwards 文件2)
如果要查找任何一个文件,请改用“find_first_upwards”。
向上查找 file1 file2 ...
此函数的行为类似于“find_upwards”,除了它返回任何
它找到的列表中的文件。 具体来说,它检查当前目录
列表中的任何文件,并返回第一个存在或可以构建的文件。
如果没有文件存在或可以在该目录中构建,它会检查 .., 然后
../ ..等,直到它到达根目录或目录
位于不同的文件系统上。
第一个可用 file1 file2 ...
返回列表中存在或可以构建的第一个文件。 这对
调整您的 makefile 以在多个不同的机器或网络上工作,其中
重要的文件可能位于不同的地方。 例如,这里有一行来自
我的生成文件之一:
TCL_LIB = $(第一个可用\
/usr/local/stow/tcl-8.4.5-nothread/lib/libtcl8.4.so \
/usr/lib/libtcl8.4.so /usr/lib/libtcl.so \
/net/na1/tcl8.4a3/lib/libtcl8.4.a \
/net/na1/tcl8.4a3/lib/libtcl8.4.sl)
此行将在上述所有位置检查 Tcl 库,并在
它找到的第一个。 链接命令然后包含 $(TCL_LIB) 所以我们得到
适当的 Tcl 库。
推断链接器 file1 file2 ...
给定一个目标文件列表,如果它们还没有,首先构建它们。 然后找到
它们是否依赖于 Fortran、C++ 或 C 源并返回相应的
编译器(它比“ld”更知道如何链接)。
推断对象 file1 file2 ..., 模式
$(infer_objects object1.o object2.o, *.o)
如果您使用有关头文件名的标准约定,makepp 能够
猜测哪些“.o”或“.lo”文件需要与您的程序链接。 我用这个
从包含许多不同模块中使用的模块的库目录中挑选文件
程式。 而不是制作库“.a”文件并让链接器挑选出
相关模块,makepp可以为你挑选相关模块。 这样,只
相关模块被编译。
Makepp 用于推断对象依赖关系的算法取决于约定
头文件“xyz.h”中定义的所有类或函数的实现是
编译成一个名为“xyz.o”(或“xyz.lo”)的目标文件。 所以makepp的算法
推断对象依赖关系从一个或几个我们知道必须是的对象开始
链接到程序中。 它查看哪些文件包含在“#include”中
这些源,并尝试为每个包含的对象找到相应的目标文件
文件。
"$(infer_objects)" 需要在程序的依赖列表中提及,例如
这个:
myprog: $(infer_objects main.o another_object.o, \
**/*.o /other/library/dirs/**/*.o)
$(CXX) $(输入) -o $(输出) $(LIBS)
“$(infer_objects)”函数接受两个参数(用逗号分隔,如图所示)。
第一个是已知需要的一个或几个目标文件(通配符是
此处允许)。 第二个是可能的对象列表(通常你会使用
此处的通配符)可以在必要时链接。 从这个返回值
函数是一个列表,首先包含第一个参数中的所有对象,并且
然后在这些之后,包含在第二个参数中的所有其他对象
第一个参数中的对象所需要的。
例如,假设“main.o”来自“main.cpp”,其中包括“my_class.h”。
“$(infer_objects)”查找名称为“my_class.o”的文件。 如果恰好是这样的
找到文件,将其添加到列表中。 (如果找到两个目标文件“my_class.o”
在不同的目录中,会打印一条警告消息。)“infer_objects”也
检查“my_class.cpp”以查看它包含的内容以及附加的目标文件
默示。
临时表
临时表 字首
临时表 字首XXX
温度 /
返回当前不存在的不可预测的临时文件名。 无名
指向同一个文件会返回两次,即使相对路径不同,
在一次 makepp 运行中(除了可能使用传统的递归 make,或者如果 Perl
在规则操作中运行的代码调用“f_mktemp”)。 在 makepp 结束时运行所有
此函数返回的文件将被删除,如果它们存在(同样除了那些
此函数在规则内运行的 Perl 代码中返回)。
参数末尾的任意数量的大写“X”被替换成那么多
随机字母和数字。 越多,碰撞的可能性就越小
与其他进程,所以如果你给一个前缀像“/tmp/abc。”,你应该够了
“X”。 如果有多个 X,则第一个字符来自进程 ID。 如果
没有,好像有十个,据说足够了 (8.4e17
可能性或 Windows 上的 3.7e15)。 如果没有参数,前缀默认为
"时间。" 在当前目录中。
请注意,您不想将这样的名称命名为规则目标和依赖项。 这
结果是正确的,但每次运行 makepp 时都会重新创建它。
此外,由于它总是不同的,因此只有在使用时才应该在规则操作中使用它
":build_check ignore_action":
TMPFILE ;= $(mktemp) # 1 次调用; “=”表示 3 个调用:3 个文件
A 计数 B 计数::build_check ignore_action
生产和 Bs >$(TMPFILE)
&grep -c /A/ $(TMPFILE) -o A-count
&grep -c /B/ $(TMPFILE) -o B-count
或者您应该导出它并让 Shell 评估它:
导出 TMPFILE ;= $(mktemp)
A 计数 B 计数:
generate-As-and-Bs >$$TMPFILE # makepp 没有看到 var 值
fgrep -c A $$TMPFILE >A-count
fgrep -c B $$TMPFILE >B-count
最后一种形式重复之前的返回值,因此您可以在模式规则中使用它:
%.x: %.y
&grep foo $(input) -o $(mktemp)
&sed bar $(mktemp /) -o $(output) # 对&grep的输出进行操作
不目录 档名
返回文件名的非目录部分,即最后一个之后的所有内容
如果有斜杠,则为斜杠,否则为整个文件名。
仅生成 档名
仅返回列表中由 makepp 生成的文件名,而不是从
修改,根据构建信息文件。
这个函数在干净的目标规则中很有用(当然“makeppclean”是
首选变体):
$(虚假清洁):
&rm -f $(only_generated **/*)
仅_非目标 档名
只返回列表中那些不是任何规则目标的文件名(或者
显式或模式规则)。 您可以指定通配符(请参阅“$(wildcard)”
有关 makepp 通配符的更多详细信息,请参阅函数)。 这可用于生成
分配目标,例如:
.PHONY:分发
分配:
&mkdir our_product-$(VERSION)
&cp $(filter-out %~, $(only_nontargets *)) our_product-$(VERSION)
tar cf - our_product-$(VERSION) | gzip -9c > our_product-$(VERSION).tar.gz
在这种情况下,“$(only_nontargets *)”返回当前目录中的每个文件
这不是某些规则的目标。 “$(filter_out %~, ...)”删除编辑器
备份。
与“only_targets”(见上文)类似,“only_nontargets”只知道那些
已经被定义了。 如果你用它来定义变量,这只是一个问题
使用“:=”赋值; 如果您在依赖项列表或主体中使用它
规则,所有其他规则都已经看到了。
仅陈旧 档名
仅返回列表中由 makepp 生成的文件名,而不是从
根据构建信息文件进行了修改,但不再是任何规则的目标。
此功能可用于确保对此类文件没有依赖关系,
不强制所有目标的干净构建:
$(虚假同花顺):
&rm -f $(only_stale **/*)
实际上,最好编写一个调用 makepp 生成的脚本
陈旧文件列表,然后让该脚本删除所有列出的文件
当前不受源代码控制,以防万一生成的文件成为源
文件。 Makepp 没有内置这样的功能,因为 makepp 是(并且可能
应该保持)对源代码控制不可知。
只有_targets 档名
仅返回列表中实际上是某个规则目标的那些文件名
(显式或模式规则)。 您可以指定通配符(包括 makepp 的
特殊通配符,“**”)在文件名中。 (有关更多信息,请参阅“$(wildcard)”函数
细节。 这可以用于干净的目标,例如:
.PHONY:干净
清洁:
&rm -f $(only_targets *)
现在,如果您键入“makepp clean”,它将删除它知道如何构建的所有内容。 但
不要创建干净的目标,而是使用“makeppclean”!
另一个可能有用的地方是避免包含陈旧的 .o 你的文件
建造。 例如,如果您构建这样的库:
mylib.a: *.o
&rm -f $(输出)
$(AR) cr $(输出) $(输入)
然后你删除了一些源文件但忘记删除相应的 .o 文件,
此 .o 文件仍然存在。 这意味着它们仍将被纳入
图书馆,尽管它们不再有用。 如果你修改你的
像这样的规则:
mylib.a: $(only_targets *.o)
&rm -f $(输出)
$(AR) cr $(输出) $(输入)
那么这个问题就不会发生了。
请注意,这仅指已知为目标的文件 at 此 次 您
调用 “唯一目标”。 如果“only_targets”出现在依赖项或操作中
规则,那么所有可能的目标都将是已知的,因为依赖项和操作不是
评估直到规则被执行。 但是,如果您评估尝试评估它
之前在 makefile 中使用“:=”变量,如下所示:
ALL_TARGETS := $(only_targets *)
目标 1:依赖项 1
行动
目标 2:依赖项 2
行动
那么“only_targets”将不知道后续规则。
类似地,“only_targets”不知道在生成文件中生成的目标是
加载了递归make。 (但无论如何你都不应该使用递归make;使用
使用“load_makefile”语句,或使用隐式生成文件加载代替。)
相对文件名 file1 file2 文件 3[, 削减]
返回这些文件相对于当前目录的名称(
生成文件在)。 这也可以用来清除不必要的“./”和其他垃圾
路径:
目录:=。
子目录:= ..
FNAME := $(DIR)/../otherdir/$(SUBDIR)/文件
X := $(相对文件名 $(FNAME))
If 削减 为真(通常为 1)返回的文件名保证包含斜杠
如有必要,在前面加上“./”,这样您就可以将其用作可执行文件名,而无需
担心命令搜索路径会覆盖目录位置。
如果路径经过根目录,则是您的主目录或
构建系统的“$(ROOT)”,或在 Windows 上的驱动器根目录(取决于
环境,这也发生在 /cygdrive/c or /c),绝对路径将是
而是返回。
关系到 file1 file2 文件 3[, 目录]
返回这些文件相对于指定目录的名称。 这是
无论出于何种原因,您必须从
不同的目录(默认当前目录):
source_backup.tar:
cd .. && tar cf $(relative_to $(output), ..) $(relative_to ., ..)
后缀 名字...
提取名称中每个文件名的后缀。 如果文件名包含句点,
后缀是从最后一个句点开始的所有内容。 否则,后缀是
空字符串。 这通常意味着当名称不是时结果将为空,
如果 names 包含多个文件名,则结果可能包含更少的文件名。
例如,
$(后缀src/foo.c src-1.0/bar.c hacks)
产生结果“.c .c”。
临时 话
让 makepp 知道指定的目标可能会被生成的规则删除
他们。 类似于“虚假”,除了 makepp 期望该名称的真实文件
will 可能会受到规则的影响。 如果只是临时规则,则不会执行规则
目标已过时。
通配符 模式
返回与存在的给定模式匹配的所有文件的排序名称,或那些
尚不存在但可以根据 makepp 知道的规则构建的文件
大约在它评估表达式的时候。 在最后一点,它有所不同
来自规则输入通配符,这些通配符甚至适用于由稍后发现的规则创建的文件。
Makepp 支持所有常用的 shell 通配符(“*”、“?”和“[]”)。 它还有一个
通配符“**”匹配任意数量的中间目录。 (这个想法是
从 zsh 窃取。)例如,“**/*.c”匹配所有 .c 整个源中的文件
树。 "objects/**/*.o" 匹配所有 .o 包含在任何位置的文件
子目录 对象 或其任何子目录或其任何子目录。 这
“**”通配符不会跟随软链接到任何级别的目录,也不会
尝试输入存在但无法读取的目录。 还有文件和
“$(wildcard)”不会返回存在但无法读取的目录。
串 主要工作内容
添加前缀 字首, 话
为每个单词添加前缀字符串。 这主要是针对 GNU make
兼容性; 使用 rc-style 扩展,这可以以更具可读性的方式完成
喜欢这个:
模块:= abcd
X_OLD_STYLE := $(addprefix $(OBJDIR)/, $(addsuffix .o, $(MODULES)))
X_NEW_STYLE := $(OBJDIR)/$(MODULES).o # 这不是更容易阅读吗?
添加后缀 后缀, 话
将后缀字符串附加到每个单词。 这主要是针对 GNU make
兼容性; 使用 rc-style 扩展,这可以以更具可读性的方式完成
喜欢这个:
X_OLD_STYLE := $(addsuffix .o, $(MODULES))
X_NEW_STYLE := $(MODULES).o
呼叫 多变的[, 字]...
函数“call”的独特之处在于它可以用来考虑 变量 作为一个
参数化函数您可以将复杂的表达式分配给 变量 并使用
“调用”将其内容扩展为由参数化的不同值 话 稍后的。 在
其他 make 系统,一个主要用于扩展目的的变量
“呼叫”,被称为 宏.
在宏扩展期间,临时变量 $1, $2, “......” 参考
在调用期间提供给“call”的参数。 变量 $0 将扩展到
宏的名称(即 变量) 那个“呼叫”目前正在扩大。
没有限制,宏可以“调用”多少个参数或多少个
宏可能期望的参数。 如果您将更多参数作为宏传递给“call”
需要,所有超出的参数都将被丢弃。 如果您传递的参数少于 a
宏期望,所有超出的参数都折叠为空字符串。
先举个简单的例子:
休息 = $(wordlist 2, $(words $(1)),$(1))
列表 = ABCDE
但首先:= $(呼叫休息,$(列表))
在这里,变量“$(butfirst)”将包含列表“BCDE”。
现在用一个更复杂的例子来展示什么是可能的:
休息 = $(wordlist 2,$(words $(1)),${1})
mymap = $(如果 $2,$(调用 $1,$(第一个词 $2)) $(调用 $0,$1,$(调用其余部分,$2)))
downcase = ${makeperl lc("$1")}
UCWORDS = 所有这些单词都是大写
DCWORDS := $(调用 mymap,downcase,$(UCWORDS))
现在“$(DCWORDS)”包含“所有这些单词都是大写的”。 顺便说一句:它没有
区别,我们是否通过访问参数 $1, “${1}” or “$(1)” 在一个宏中。
如果没有,您可以直接使用该变量,就好像它是一个函数一样
那个名字的功能。 这在内部转换为“呼叫”,所以这些是
当量:
讨论 = 0 美元变成了 1 美元 2 美元。
直接= $(讨论一个,参数)
调用 = $(调用讨论,一个,参数)
"$[call]" 是否也应该扩展宏的 "$[]" 似乎有争议
表达式,或者一个函数是否应该总是做同样的事情,不管它如何
叫做。 选择后者,因为使用正常的 make 语法,它将是
不可能将 "$[1], $[2]..." 放入变量中(它们会被什么都不替换,
在赋值之前。)因此,如果你有一个宏来定义一个
规则,您希望在解析规则时看到像 "$(output)" 这样的表达式,所以
你必须保护他们免受“呼叫”:
定义规则
$ 2:$ 1
mycommand $$(输入) -o $$(输出)
恩德夫
$[我的规则我的输入,我的输出]
过滤 模式 话
返回列表中与模式匹配的所有单词。 模式可能只是其他
单词或文件名通配符(即,“*”、“?”和“[az]”被识别),或者它们可能
有一个“%”字符,这意味着匹配该点的任何字符串(与“*”相同)。
过滤掉 模式 话
返回列表中与模式不匹配的所有单词。 模式可能只是
换句话说,或文件名通配符(即识别“*”、“?”和“[az]”),或
它们可能有一个“%”字符,这意味着匹配该点的任何字符串(与
“*”)。
例如:
libproduct.a: $(filter_out test_*, $(通配符 *.o))
将把所有 .o 存在或可以构建的文件,除了以 test_,
成 lib生产.a.
查找字符串 找, in
退货 发现, 如果它是一个子串 in.
第一个字 话
返回第一个单词。
地图 话, 代码
制作地图 话, 代码
类似于 Perl 的映射,适用 代码 依次返回每个单词并返回
结果。 第一个变体是普通的 Perl 代码,而第二个变体首先通过
perlcode 通过 Make 风格的变量扩展。 这两个词都扩展了
案例。
单词在 $_ 中,除非您取消定义 $_,否则将返回。 这是为了
“patsubst”不容易处理的修改。 只有第一个逗号是分隔符,
任何其他人都被视为 代码.
# 切换单词。 双括号,允许在 perlcode 中出现括号,或使用 ${}:
X = $((映射 $(VALUES), s/(.+)-(.+)/$2-$1/))
# 你可以使用 make 表达式,但是你必须使用 $$ 来表示 Perl $:
Y = $(makemap $(VALUES), tr/$(OLDCHARS)/$(NEWCHARS)/ 或 $$_ = 'failed')
# 你可以消除候选人:
Y = $(map $(VALUES), undef $_ if /no_good/)
加入 词1, 字2
对第一个单词和第二个单词进行成对连接。
模式物质 图案, 代替, 话
对单词列表中的每个单词执行替换。 “%”字符匹配任何
细绳。 最好通过一个例子来说明这一点:
OBJS = $(patsubst %.c, object_dir/%.o, $(C_SOURCES))
获取 C_SOURCES 中的每个文件并返回 object_dir 中的目标文件的名称。
有时使用替换引用更简洁,例如,上面可以
被写成
OBJS = $(C_SOURCES:%.c=object_dir/%.o)
分类 word1 word2 word3 ...
按词汇顺序对单词进行排序并删除重复项。
剥离 绳子
从字符串中删除前导和尾随空格并替换每个内部
一个或多个空白字符的序列,带有一个空格。 因此,“$(strip ab
c )" 结果为 "abc"。
SUBST 从,到,文本
对文本文本执行文本替换:每次出现的 from 都被替换
到。 结果被替换为函数调用。 例如,
$(subst ee,EE,街上的脚)
替换字符串“fEEt on the strEEt”。
字 n,文本
返回 n第一句话 文本. 合法的价值观 n 从 1 开始
或最后从 -1 向后。 如果 n 大于单词的数量 文本是,
值为空。
词汇表 索引列表, 话
词汇表 第一个索引, 最后一个索引, 话
在第一种形式中,您提供一个索引列表(从开头的 1 或
从末尾的 -1 向后)以选择您想要的单词。 在第二种形式中你
指定要返回的单词范围。
话 文本
返回单词的数量 文本.
其他 主要工作内容
的foreach 变量、列表、文本
前两个论点, VAR 和 名单, 在做任何其他事情之前被扩展; 笔记
最后一个参数 text 不会同时展开。 然后对于每个单词
list 的扩展值,由 var 扩展值命名的变量设置为
那个词,文字就展开了。 大概文本包含对该变量的引用,
所以它的扩展每次都会不同。
这个简单的例子设置变量 档 到所有文件的列表
列表中的目录 迪尔斯:
目录:= abcd
文件 := $(foreach dir,$(dirs),$(wildcard $(dir)/*))
这里的文字是“$(wildcard $(dir)/*)”。 第一次重复找到 dir 的值“a”,
所以它产生与“$(wildcard a/*)”相同的结果; 第二次重复产生
"$(wildcard b/*)" 的结果; 第三个是“$(wildcard c/*)”。
此示例与以下示例具有相同的结果(除了设置“dirs”):
文件 := $(通配符 a/* b/* c/* d/*)
当文本很复杂时,你可以通过给它一个名字来提高可读性,
附加变量:
find_files = $(通配符 $(dir)/*)
目录:= abcd
文件 := $(foreach 目录,$(dirs),$(find_files))
这里我们以这种方式使用变量 find_files。 我们使用普通的“=”来定义一个
递归扩展变量,使其值包含对
在foreach的控制下重新展开; 一个简单扩展的变量不会做,
因为通配符在定义 find_files 时只会被调用一次。
注意:不要将它与“$(foreach)”特殊变量混淆。
info 文本
警告 文本
错误 文本
输出文本返回空。 第一个到 STDOUT,第二个到 STDERR,
第三个额外中止处理。
预建 目标
使 目标
逐字返回其参数,但首先构建列出的所有文件。 这很有用
在评估 make 表达式时需要给定文件时。 这通常会发生
当你有一个构建,其中所涉及的文件集是由某个 shell 计算的
命令。 例如,
文件列表:
# shell 命令来计算要放入程序的文件列表
my_program : $(&cat $(prebuild file_list))
如果您需要多个规则中的列表,使用
最多扩展一次变量:
file_list ;= $(&cat $(prebuild file_list))
my_program1 : ao $(file_list)
my_program2 : bo $(file_list)
如果您只指定了“$(&cat file_list)”,则 makepp 不会强制
file_list 在执行 shell 命令之前是最新的。 使用 "$(prebuild )"
是解决这个问题的最好方法。 你可能想尝试其他的东西,比如
这个:
my_program : file_list $(&cat file_list)
但这不起作用,因为在 makepp 尝试之前评估了“$(&cat file_list)”
构建“文件列表”。
only_phony_targets 名称
仅返回列表中作为某些规则的虚假目标的名称(或者
显式或模式规则)。 您可以指定通配符(包括 makepp 的特殊
通配符,“**”)在文件名中。 (有关更多详细信息,请参阅“$(wildcard)”函数。
这可用于对目标进行分组,例如:
$(虚假测试):$(only_phony_targets */**/tests)
起源 变量
给定一个变量的名称,告诉你它的值来自哪里。
perl的 代码
编译器 代码
评估块中的 perlcode 并返回结果。 第一个变体是普通的 Perl
代码,而第二个变体首先通过 Make-style 变量传递 perlcode
扩张。
请注意,与所有函数一样,所使用的函数分隔符可能不会出现在
单引号或双引号字符串之外的 perlcode。 但是你可以把它加倍
最后一个例子:
自变量=1
VAR1 = ${perl ($VAR + 1) * 3}
VAR2 = $(perl do { $VAR *= 3; 返回 $VAR + 1 } 如果 $VAR)
VAR3 = $(makeperl $(VAR1) * 3 + $$VAR) # 一个 Make var 和一个 Perl var
VAR = $((perl if( ... ) { ... }))
假 话
表示单词列表实际上是虚假目标,并返回
目标。 它的用途是这样的:
$(虚假全部):my_program
$(虚假清洁):
&rm -f *.o my_program
您也可以在
你的生成文件:
.PHONY:全部干净
打印 文本
输出文本并返回它。 这对于调试最有用,当你不
理解为什么变量替换会产生这样的结果。 例如,
XYZ := $(打印 $(patsubst %.c, %o, $(SOURCE_FILES)))
将打印出“patsubst”调用的结果。
XYZ := $(patsubst %.c, %o, $(打印 $(SOURCE_FILES)))
将打印出“patsubst”调用的最后一个参数。
壳 外壳命令
返回给定 shell 命令的输出,用空格替换换行符。
请注意,与所有函数一样,所使用的函数分隔符可能不会出现在
单引号或双引号字符串之外的 shell 命令。 但你可以加倍
如第二个例子:
date = $(shell date) # 更好: $(perl scalar localtime)
VAR = ${{shell f() { echo hello; }; F}}
参数 命令,参数[,后缀[,长度]]
返回一个以换行符分隔的命令列表,每个命令都以指定的开头
命令,并以列表中尽可能多的元素结尾,而无需遍历
长度 (默认 1000)个字符。
这样做的目的是避免溢出系统上的命令长度限制。
例如,如果有很多生成的文件,那么你可能想要你的
干净的目标(你不应该有,因为“makeppclean”更有效)到
看起来像这样:
$(虚假清洁):
$(xargs $(RM), $(only_targets **/*))
这也有副作用,如果列表不生成任何命令
恰好是空的。 但在这种情况下,最好使用内置的 &rm,
因为内置命令的参数仅受 Perl 内存的限制:
$(虚假清洁):
&rm -f $(only_targets **/*)
如果指定了第三个参数,则它用于后缀每个命令。 这是
用于指定重定向器,例如(尽管这里再次 &echo 会有所帮助):
显现:
&rm -f $@
&触摸$@
$(xargs echo, $(only_nontargets **/*), >> $@)
此文档中的一些基于 GNU make 文档。
请注意,如果在 makefile 初始化期间调用函数,例如
导出变量、错误或警告消息的扩展将报告行号 0。
使用 onworks.net 服务在线使用 makepp_functions