简体   繁体   English

从makefile中的bash命令输出创建变量

[英]Creating variable from bash command output in makefile

Hello I would like to ask how I can create bash variable in makefile.你好,我想问一下如何在makefile中创建bash变量。 Below code does work but variable "targets" keeps being empty.下面的代码确实有效,但变量“目标”一直为空。 How I can actually create "targets" and "current_target" variables in makefile?.我如何在 makefile 中实际创建“目标”和“current_target”变量?。 Problem is that I have to create this variables from actual bash commands.问题是我必须从实际的 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

output:输出:

make foo last_target="02" segm=KI
+ 1

What I want to do is to make targets from my makefile which actually starts from 01 to 05 if I pass an argument last_target="05"我想要做的是从我的 makefile 中创建目标,如果我传递一个参数 last_target="05",它实际上从 01 到 05

You mix up between make variables and shell variables.您混淆了 make 变量和 shell 变量。 And you did not consider that make expands the recipes before passing them to the shell, reason why you frequently need to use $$ instead of $ .并且您没有考虑 make 在将配方传递给 shell 之前扩展它们,这就是为什么您经常需要使用$$而不是$ Or, for command expansion, `...` instead of $(...) .或者,对于命令扩展,`...` 而不是$(...) You are also using double quotes where you shouldn't ( expr "..." ).您还在不应该使用的地方使用双引号( expr "..." )。 Finally, you use make in your recipe, which is not a good idea.最后,您在食谱中使用make ,这不是一个好主意。 You should use $(MAKE) (see the How the MAKE Variable Works section of the GNU make manual for the details).您应该使用$(MAKE) (有关详细信息,请参阅GNU make 手册的 MAKE 变量如何工作部分)。

Try the following (not tested) maybe:尝试以下(未测试)也许:

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

But I am almost 100% convinced that you are trying to use make as a kind of scripting language instead of as a sophisticated build system.但是我几乎 100% 确信您正在尝试将 make 作为一种脚本语言而不是作为复杂的构建系统使用。 If I understand well you are trying to rebuild only a subset of your MAIN_APPS by specifying a last target number.如果我理解得很好,您正在尝试通过指定最后一个目标编号来仅重建MAIN_APPS的一个子集。 You could probably achieve the same with a much more make-ish style:您可能可以使用更制作的风格来实现相同的效果:

TARGETS := $(shell printf '%02d_prep\n' $$(seq $(last_target)))

.PHONY: foo
foo: $(TARGETS) .check_targets .check_segment

And that's all, no complex recipe for foo .就是这样, foo没有复杂的配方。 Nothing at all (except, of course, the rules to build .check_targets , .check_segment and all xx_prep targets, that you do not show).什么都没有(当然,除了构建.check_targets.check_segment和所有xx_prep目标的规则,您没有显示)。

Explanation: I used the $(shell ...) make function and a small shell script to initialize make variable TARGETS with 01_prep 02_prep ... up to $(last_target)_prep .说明:我使用$(shell ...) make 函数和一个小的 shell 脚本来初始化 make 变量TARGETS01_prep 02_prep ... up to $(last_target)_prep As noted in the comments this shell script does not even require bash and would work with the default make shell (sh).正如评论中所指出的,这个 shell 脚本甚至不需要 bash,并且可以与默认的 make shell (sh) 一起使用。 So, if you do not have other good reasons to use bash, get rid of the SHELL=/bin/bash line and your Makefile will be a bit more portable.因此,如果您没有其他充分理由使用 bash,请去掉SHELL=/bin/bash行,这样您的 Makefile 将更加便携。

Then, I declared foo as phony because you probably don't have a file named foo and, in case you have one, you probably want make to build foo anyway.然后,我将foo声明为虚假文件,因为您可能没有名为foo的文件,如果您有文件,您可能无论如何都希望 make 构建foo

Finally, I declared $(TARGETS) , .check_targets , and .check_segment as prerequisites of foo .最后,我将$(TARGETS).check_targets.check_segmentfoo先决条件。 If you ask make to build foo and any of these prerequisites is out-of-date, make will build it using the rules you declared for it.如果您要求 make 构建foo并且这些先决条件中的任何一个已经过时,则 make 将使用您为其声明的规则构建它。

This is far more make-ish because it clearly tells make what depends on what instead of hiding it in a recipe.这更像是 make-ish,因为它清楚地告诉 make 什么取决于什么,而不是将它隐藏在食谱中。 And make needs this to do its job correctly, which consist in comparing last modification dates of files to decide if something must be rebuilt or not.而 make 需要这样做才能正确地完成它的工作,包括比较文件的最后修改日期来决定是否必须重建某些东西。 It also has extra benefits like, for instance, exploiting the parallelism of your computer to build several xx_prep in parallel if it is possible.它还具有额外的好处,例如,如果可能的话,可以利用计算机的并行性来并行构建多个xx_prep

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM