路径中的符号和百分号
Make and Percent Sign in Paths
关于 Makefile、列表处理和模式规则,我似乎遇到了一个怪癖。当我的源安装在名称包含“%”的目录中时,它无法正确构建。我把它归结为一个任何人都可以 运行.
的简单测试用例
我有以下 Makefile:
INSTALL_DIR=$(shell pwd)/idir
INSTALL_TREE =
INSTALL_TREE += $(INSTALL_DIR)/dir1
INSTALL_TREE += $(INSTALL_DIR)/dir2
INSTALL_TREE += $(INSTALL_DIR)/dir3
create_tree: $(INSTALL_TREE)
$(INSTALL_TREE):
mkdir -p $@
我把它放在一个名为 test1 的目录中,当我 运行 它时,我得到了我想要的... INSTALL_TREE 中列出的所有目录都已创建:
% make -n
mkdir -p /home/christopher.arguin/test/test1/idir/dir1
mkdir -p /home/christopher.arguin/test/test1/idir/dir2
mkdir -p /home/christopher.arguin/test/test1/idir/dir3
现在在名为 test%2 的目录中使用完全相同的 Makefile,这就是我得到的:
% make -n
mkdir -p /home/christopher.arguin/test/test2%/idir/dir1
它在第一个目录后停止。有趣的是,如果第一个目录没有 % 符号,它们都会生成...,例如,
INSTALL_TREE =
INSTALL_TREE += ./idir/dir4
INSTALL_TREE += $(INSTALL_DIR)/dir1
INSTALL_TREE += $(INSTALL_DIR)/dir2
INSTALL_TREE += $(INSTALL_DIR)/dir3
给我:
mkdir -p dir4
mkdir -p /home/christopher.arguin/test/test2%/idir/dir1
mkdir -p /home/christopher.arguin/test/test2%/idir/dir2
mkdir -p /home/christopher.arguin/test/test2%/idir/dir3
另一件有趣的事情是文件名是正确的...如果 % 被误解为前缀规则或您可能希望进行一些替换的东西,但如果我让它创建目录,它就绝对正确东西。
我尝试转义 % 字符,但无济于事。添加此代码:
PERCENT := %
ITREE = $(subst $(PERCENT),$(PERCENT)$(PERCENT),$(INSTALL_TREE))
create_tree2: $(ITREE)
$(ITREE):
mkdir -p $@
刚刚投降
mkdir -p /home/christopher.arguin/test/test2%%/idir/dir1
替换有效,但实际上并没有转义百分号。也没有用“$(PERCENT)”替换“%”,因为文件名之后只包含 $(PERCENT)。
我发现了两个相关的问题,
Does GNU Make support '%' in a filename?
和 How to correctly escape "%" sign when using pattern rules and patsubst in GNU make?
但是这些都没有遇到我遇到的基本问题......我的源所在的目录不在我的控制范围内。
背景:
这对我来说是个问题,因为我正在尝试迁移到 Jenkins Multibranch Pipeline。当 Jenkins 检测到提交时,它会根据分支名称创建一个工作区。如果您的分支命名约定中恰好有斜杠,Jenkins 会做正确的事情并将它们转换为“%2F”。我的 makefile 运行ning 与这些冲突。
包含%
的目标定义了模式规则,具有多个目标的模式规则处理不同:
https://www.gnu.org/software/make/manual/make.html#Pattern-Intro
Pattern rules may have more than one target. Unlike normal rules, this does not act as many different rules with the same prerequisites and recipe. If a pattern rule has multiple targets, make knows that the rule’s recipe is responsible for making all of the targets. The recipe is executed only once to make all the targets.
您可以通过在定义路径规则时引用 %
来解决这个问题。请注意,这对于 create_tree
的依赖项不是必需的,因为这是常规规则,事实上,如果您这样做,它不会起作用,因为 make 将查找具有文字 \%
的目标。
INSTALL_DIR := $(abspath .)/idir
INSTALL_TREE += $(INSTALL_DIR)/dir1
INSTALL_TREE += $(INSTALL_DIR)/dir2
INSTALL_TREE += $(INSTALL_DIR)/dir3
.PHONY: create_tree
create_tree: $(INSTALL_TREE)
$(subst %,\%,$(INSTALL_TREE)):
mkdir -p $@
关于 Makefile、列表处理和模式规则,我似乎遇到了一个怪癖。当我的源安装在名称包含“%”的目录中时,它无法正确构建。我把它归结为一个任何人都可以 运行.
的简单测试用例我有以下 Makefile:
INSTALL_DIR=$(shell pwd)/idir
INSTALL_TREE =
INSTALL_TREE += $(INSTALL_DIR)/dir1
INSTALL_TREE += $(INSTALL_DIR)/dir2
INSTALL_TREE += $(INSTALL_DIR)/dir3
create_tree: $(INSTALL_TREE)
$(INSTALL_TREE):
mkdir -p $@
我把它放在一个名为 test1 的目录中,当我 运行 它时,我得到了我想要的... INSTALL_TREE 中列出的所有目录都已创建:
% make -n
mkdir -p /home/christopher.arguin/test/test1/idir/dir1
mkdir -p /home/christopher.arguin/test/test1/idir/dir2
mkdir -p /home/christopher.arguin/test/test1/idir/dir3
现在在名为 test%2 的目录中使用完全相同的 Makefile,这就是我得到的:
% make -n
mkdir -p /home/christopher.arguin/test/test2%/idir/dir1
它在第一个目录后停止。有趣的是,如果第一个目录没有 % 符号,它们都会生成...,例如,
INSTALL_TREE =
INSTALL_TREE += ./idir/dir4
INSTALL_TREE += $(INSTALL_DIR)/dir1
INSTALL_TREE += $(INSTALL_DIR)/dir2
INSTALL_TREE += $(INSTALL_DIR)/dir3
给我:
mkdir -p dir4
mkdir -p /home/christopher.arguin/test/test2%/idir/dir1
mkdir -p /home/christopher.arguin/test/test2%/idir/dir2
mkdir -p /home/christopher.arguin/test/test2%/idir/dir3
另一件有趣的事情是文件名是正确的...如果 % 被误解为前缀规则或您可能希望进行一些替换的东西,但如果我让它创建目录,它就绝对正确东西。
我尝试转义 % 字符,但无济于事。添加此代码:
PERCENT := %
ITREE = $(subst $(PERCENT),$(PERCENT)$(PERCENT),$(INSTALL_TREE))
create_tree2: $(ITREE)
$(ITREE):
mkdir -p $@
刚刚投降
mkdir -p /home/christopher.arguin/test/test2%%/idir/dir1
替换有效,但实际上并没有转义百分号。也没有用“$(PERCENT)”替换“%”,因为文件名之后只包含 $(PERCENT)。
我发现了两个相关的问题, Does GNU Make support '%' in a filename? 和 How to correctly escape "%" sign when using pattern rules and patsubst in GNU make? 但是这些都没有遇到我遇到的基本问题......我的源所在的目录不在我的控制范围内。
背景: 这对我来说是个问题,因为我正在尝试迁移到 Jenkins Multibranch Pipeline。当 Jenkins 检测到提交时,它会根据分支名称创建一个工作区。如果您的分支命名约定中恰好有斜杠,Jenkins 会做正确的事情并将它们转换为“%2F”。我的 makefile 运行ning 与这些冲突。
包含%
的目标定义了模式规则,具有多个目标的模式规则处理不同:
https://www.gnu.org/software/make/manual/make.html#Pattern-Intro
Pattern rules may have more than one target. Unlike normal rules, this does not act as many different rules with the same prerequisites and recipe. If a pattern rule has multiple targets, make knows that the rule’s recipe is responsible for making all of the targets. The recipe is executed only once to make all the targets.
您可以通过在定义路径规则时引用 %
来解决这个问题。请注意,这对于 create_tree
的依赖项不是必需的,因为这是常规规则,事实上,如果您这样做,它不会起作用,因为 make 将查找具有文字 \%
的目标。
INSTALL_DIR := $(abspath .)/idir
INSTALL_TREE += $(INSTALL_DIR)/dir1
INSTALL_TREE += $(INSTALL_DIR)/dir2
INSTALL_TREE += $(INSTALL_DIR)/dir3
.PHONY: create_tree
create_tree: $(INSTALL_TREE)
$(subst %,\%,$(INSTALL_TREE)):
mkdir -p $@