Shell 如何防止make将任何变量传递给submake?

Shell 如何防止make将任何变量传递给submake?,shell,makefile,Shell,Makefile,我无法阻止make将任何变量传递给submake。我已经阅读了手册,并遵循了他们的建议(重置MAKEOVERRIDES和MAKEFLAGS),但它仍然不起作用,我认为它应该起作用 考虑以下原型生成文件: ${warning $(MAKEOVERRIDES)} ${warning $(MAKEFLAGS)} ${warning $(VAR)} none: $(MAKE) -f Makefile MAKEOVERRIDES= MAKEFLAGS= all all: echo do

我无法阻止
make
将任何变量传递给submake。我已经阅读了手册,并遵循了他们的建议(重置
MAKEOVERRIDES
MAKEFLAGS
),但它仍然不起作用,我认为它应该起作用

考虑以下原型生成文件:

${warning $(MAKEOVERRIDES)}
${warning $(MAKEFLAGS)}
${warning $(VAR)}

none:
    $(MAKE) -f Makefile MAKEOVERRIDES= MAKEFLAGS= all

all:
    echo done!
如果我
make VAR=10 none
,我会得到以下结果:

Makefile:2: VAR=10
Makefile:3: 
Makefile:4: 10
make -f Makefile MAKEOVERRIDES= MAKEFLAGS= all
make[1]: Entering directory `/home/adriano/sandbox/makes'
Makefile:2: 
Makefile:3: 
Makefile:4: 10
echo done!
done!
make[1]: Leaving directory `/home/adriano/sandbox/makes'
这意味着
make
是与submake的通信
VAR
。这是正确的行为吗

我尝试了
unexport VAR
bash-c make…
,但没有任何运气

编辑:我将
none
的配方修改为:
bash-c“echo$$MAKEOVERRIDES$$MAKEFLAGS$$VAR”;制作…

通过这种方式,我发现VAR实际上是通过make为要执行的命令创建的环境传递的,而不是通过其他变量传递的(其他变量也通过这种方式传递给make)

我想我现在的问题是:如何创建一个新的shell/环境来运行sub make

编辑:有人问我为什么要这么做;我会尽力回答这个问题

我有一个“模块”,它使用一个名为CONFIG的变量。为了构建这个模块,我需要构建另一个部分不相关的“模块”,它也使用CONFIG,但具有不同的值。问题是,当我尝试构建“子模块”时,配置包含“超级模块”的值。我可以在创建“子模块”时指定配置,但是两个模块使用许多同名变量,并且尝试将它们全部指定会使模块紧密耦合,这是我无法承受的

这怎么会这么难…

这是错误的:

none:
        $(MAKE) -f Makefile MAKEOVERRIDES= MAKEFLAGS= all
这些变量(
MAKEOVERRIDES
MAKEFLAGS
)由要传递给子make的父make在环境中设置。在配方中设置这些值的覆盖将没有帮助,因为make必须在实际启动配方中的命令之前设置配方的环境(当然)

您必须覆盖/删除父make文件中的这些值,以便父make在构造子make的环境之前可以看到这些更改:

MAKEOVERRIDES =
none:
        $(MAKE) -f Makefile all
没有完美的方法可以做到这一点。但是,您可以玩一个在大多数情况下都有效的技巧:

unexport $(shell echo '$(MAKEOVERRIDES)' | sed 's/=[^ ]*//g')
MAKEOVERRIDES =
第一行尝试取消导出
MAKEOVERRIDES
中的所有变量,第二行重置MAKEOVERRIDES。这有几个问题。一个是,如果MAKEOVERRIDES为空,它将使用“unexport”本身来取消所有内容的输出。通过在shell函数之前粘贴一些伪变量,可以很容易地解决这个问题。另一种情况是,如果任何变量的值包含空格,扩展将考虑它是一个不被导出的变量。这可能没问题,但很奇怪

我想不出比这更好的办法了

你没有说你为什么要这么做。您是否考虑过做一些不同的事情,例如使用
env
,在希望拥有“普通”环境的地方运行命令;例如,如果要使用有限的特定环境变量集运行命令,可以运行:

test:
        env -i PATH='$(PATH)' LANG='$(LANG)' runMyCommand --with --my arguments
不幸的是,一些版本的
env
使用
-
而不是
-i
;检查你的手册页

或者,您可以尝试启动一个登录shell,它将从头开始重新读取用户的shell设置环境:

test:
        /bin/sh -lc 'runMyCommand --with --my arguments'
编辑:这很难,因为你要求做的事情(限制子品牌的环境)很棘手

幸运的是,根据你的描述,这似乎没有必要。Make对于查找变量值具有重要的层次结构。命令行是最高级别的(当然,有
override
,但我们将忽略它)。之后是makefile本身中设置的变量。最后也是最低的是从环境中导入的变量(默认变量甚至更低,但我们也会忽略)


因此,如果您的目标是允许子make中的变量不受提供给上层make的命令行变量的影响,那么从环境中获取变量的所有这些繁琐操作都是不必要的。子生成文件中设置的变量将优先于环境中的值。因此,您所要做的就是通过设置MAKEOVERRIDES来摆脱命令行上设置的变量,我已经在上面演示了如何做。

您希望第一个Make不导出变量,还是第二个Make拒绝接受它?我希望第一个Make不导出任何内容。换句话说,我希望第二个make重新开始,就像从一个shell调用一样。您可以省略一个类似这样的变量:
$(make)-f Makefile VAR=all
,但我不知道如何从命令行中省略所有变量。我已经尝试了您的解决方案。还是不行。和上面的结果一样。是的。。。问题来自GNU make手册:除了通过显式请求之外,make仅在最初在环境中定义变量或在命令行上设置变量时才导出变量。因此,仅仅取消MAKEOVERRIDES不足以将其从子make的环境中删除。您能看看我上次的编辑吗。非常感谢。