从 makefile 中的 bash 命令输出创建变量
Creating variable from bash command output in makefile
你好我想问一下如何在makefile中创建bash变量。
下面的代码确实有效,但变量“目标”一直为空。我如何在 makefile 中实际创建“目标”和“current_target”变量?问题是我必须从实际的 bash 命令创建这个变量。
SHELL=/bin/bash
...
MAIN_APPS = 01_prep 02_prep 03_prep 04_prep 05_prep
foo : .check_targets .check_segment
@for f in $(MAIN_APPS) ; do \
targets=$(expr $(last_target) + 1); \
echo $(targets) + 1; \
curent_target=$(expr "$(echo $(f) | head -c 2) + 0"); \
if [ $(targets) = $(current_target)]; then \
break; \
else \
make $(f); \
fi \
done
输出:
make foo last_target="02" segm=KI
+ 1
我想做的是从我的 makefile 创建目标,如果我传递一个参数 last_target="05"
,它实际上从 01 到 05 开始
您混淆了 make 变量和 shell 变量。而且您没有考虑到 make 在将食谱传递给 shell 之前扩展了食谱,这是您经常需要使用 $$
而不是 $
的原因。或者,对于命令扩展,`...` 而不是 $(...)
。您还在不应该使用的地方使用双引号 (expr "..."
)。最后,您在食谱中使用 make
,这不是一个好主意。您应该使用 $(MAKE)
(有关详细信息,请参阅 How the MAKE Variable Works section of the GNU make manual)。
也许可以尝试以下(未测试):
SHELL=/bin/bash
...
MAIN_APPS = 01_prep 02_prep 03_prep 04_prep 05_prep
foo : .check_targets .check_segment
@for f in $(MAIN_APPS) ; do \
targets=`expr "$(last_target)" + 1`; \
echo "$$targets + 1"; \
tmp=`echo "$$f" | head -c 2`; \
curent_target=`expr "$$tmp" + 0`; \
if [ "$$targets" = "$$current_target" ]; then \
break; \
else \
$(MAKE) "$$f"; \
fi \
done
但我几乎 100% 相信您正在尝试将 make 用作一种脚本语言,而不是用作复杂的构建系统。如果我理解得很好,您正试图通过指定最后一个目标编号来仅重建 MAIN_APPS
的一个子集。您可能可以使用更加虚构的风格来实现相同的效果:
TARGETS := $(shell printf '%02d_prep\n' $$(seq $(last_target)))
.PHONY: foo
foo: $(TARGETS) .check_targets .check_segment
仅此而已,foo
没有复杂的配方。什么都没有(当然,除了构建 .check_targets
、.check_segment
和所有 xx_prep
目标的规则,您没有显示)。
说明:我使用 $(shell ...)
make 函数和一个小的 shell 脚本将 make 变量 TARGETS
初始化为 01_prep 02_prep ...
直到 $(last_target)_prep
。如评论中所述,此 shell 脚本甚至不需要 bash 并且可以使用默认 make shell (sh)。因此,如果您没有其他充分理由使用 bash,请删除 SHELL=/bin/bash
行,您的 Makefile 将更加便携。
然后,我将 foo
声明为假文件,因为您可能没有名为 foo
的文件,如果您有一个文件,您可能需要 make 来构建 foo
无论如何。
最后,我宣布$(TARGETS)
、.check_targets
和.check_segment
为foo
的先决条件。如果您要求 make 构建 foo
而这些先决条件中的任何一个都已过时,make 将使用您为它声明的规则来构建它。
这更像是制作,因为它清楚地告诉制作取决于什么,而不是将其隐藏在食谱中。 make 需要这个来正确地完成它的工作,这包括比较文件的最后修改日期来决定是否必须重建某些东西。它还具有额外的好处,例如,如果可能的话,利用计算机的并行性来并行构建多个 xx_prep
。
你好我想问一下如何在makefile中创建bash变量。 下面的代码确实有效,但变量“目标”一直为空。我如何在 makefile 中实际创建“目标”和“current_target”变量?问题是我必须从实际的 bash 命令创建这个变量。
SHELL=/bin/bash
...
MAIN_APPS = 01_prep 02_prep 03_prep 04_prep 05_prep
foo : .check_targets .check_segment
@for f in $(MAIN_APPS) ; do \
targets=$(expr $(last_target) + 1); \
echo $(targets) + 1; \
curent_target=$(expr "$(echo $(f) | head -c 2) + 0"); \
if [ $(targets) = $(current_target)]; then \
break; \
else \
make $(f); \
fi \
done
输出:
make foo last_target="02" segm=KI
+ 1
我想做的是从我的 makefile 创建目标,如果我传递一个参数 last_target="05"
,它实际上从 01 到 05 开始您混淆了 make 变量和 shell 变量。而且您没有考虑到 make 在将食谱传递给 shell 之前扩展了食谱,这是您经常需要使用 $$
而不是 $
的原因。或者,对于命令扩展,`...` 而不是 $(...)
。您还在不应该使用的地方使用双引号 (expr "..."
)。最后,您在食谱中使用 make
,这不是一个好主意。您应该使用 $(MAKE)
(有关详细信息,请参阅 How the MAKE Variable Works section of the GNU make manual)。
也许可以尝试以下(未测试):
SHELL=/bin/bash
...
MAIN_APPS = 01_prep 02_prep 03_prep 04_prep 05_prep
foo : .check_targets .check_segment
@for f in $(MAIN_APPS) ; do \
targets=`expr "$(last_target)" + 1`; \
echo "$$targets + 1"; \
tmp=`echo "$$f" | head -c 2`; \
curent_target=`expr "$$tmp" + 0`; \
if [ "$$targets" = "$$current_target" ]; then \
break; \
else \
$(MAKE) "$$f"; \
fi \
done
但我几乎 100% 相信您正在尝试将 make 用作一种脚本语言,而不是用作复杂的构建系统。如果我理解得很好,您正试图通过指定最后一个目标编号来仅重建 MAIN_APPS
的一个子集。您可能可以使用更加虚构的风格来实现相同的效果:
TARGETS := $(shell printf '%02d_prep\n' $$(seq $(last_target)))
.PHONY: foo
foo: $(TARGETS) .check_targets .check_segment
仅此而已,foo
没有复杂的配方。什么都没有(当然,除了构建 .check_targets
、.check_segment
和所有 xx_prep
目标的规则,您没有显示)。
说明:我使用 $(shell ...)
make 函数和一个小的 shell 脚本将 make 变量 TARGETS
初始化为 01_prep 02_prep ...
直到 $(last_target)_prep
。如评论中所述,此 shell 脚本甚至不需要 bash 并且可以使用默认 make shell (sh)。因此,如果您没有其他充分理由使用 bash,请删除 SHELL=/bin/bash
行,您的 Makefile 将更加便携。
然后,我将 foo
声明为假文件,因为您可能没有名为 foo
的文件,如果您有一个文件,您可能需要 make 来构建 foo
无论如何。
最后,我宣布$(TARGETS)
、.check_targets
和.check_segment
为foo
的先决条件。如果您要求 make 构建 foo
而这些先决条件中的任何一个都已过时,make 将使用您为它声明的规则来构建它。
这更像是制作,因为它清楚地告诉制作取决于什么,而不是将其隐藏在食谱中。 make 需要这个来正确地完成它的工作,这包括比较文件的最后修改日期来决定是否必须重建某些东西。它还具有额外的好处,例如,如果可能的话,利用计算机的并行性来并行构建多个 xx_prep
。