跨多个 Makefile 转义的环境变量

Environment variable escaping across multiple Makefiles

通过多级makefile传递和修改环境变量的正确方法是什么?具体来说,我使用 special $ORIGIN RPATH value 在父 makefile 中设置 LDFLAGS,并且我需要添加到某些子 makefile 中的变量。链接器需要文字字符串 $ORIGIN,这不是要扩展的另一个变量。

Makefile:

# default value for all children
export LDFLAGS = -Wl,-rpath='$$ORIGIN'

all:
    env | grep LDFLAGS
    $(MAKE) -f child1.mk
    $(MAKE) -f child2.mk

child1.mk:

# add an additional RPATH value
export LDFLAGS += -Wl,-rpath='$$ORIGIN/../..'

all:
    env | grep LDFLAGS

child2.mk:

all:
    env | grep LDFLAGS

事情是这样的:

$ make
env | grep LDFLAGS
LDFLAGS=-Wl,-rpath='$ORIGIN'
make -f child1.mk
make[1]: Entering directory `/build/test'
env | grep LDFLAGS
LDFLAGS=-Wl,-rpath='RIGIN' -Wl,-rpath='$ORIGIN/../..'
make[1]: Leaving directory `/build/test'
make -f child2.mk
make[1]: Entering directory `/build/test'
env | grep LDFLAGS
LDFLAGS=-Wl,-rpath='$ORIGIN'
make[1]: Leaving directory `/build/test'

在 child1 输出中,'RIGIN' 是错误的,$$ 似乎已被第二次评估。

documentation has this note about exports,这可能是相关的,但并没有真正解释如何避免它:

In both of these forms, the arguments to export and unexport are expanded, and so could be variables or functions which expand to a (list of) variable names to be (un)exported.

在顶级 Makefile "works" 中对 child1 使用 $$$$ORIGIN,但对 child2 不使用 LDFLAGS 值并以 $$ORIGIN 结尾.

这是 Linux 下的 GNU Make 3.81。

我链接到的 RPATH post 有一个解决方法,但感觉这不是必需的:

LDFLAGS="-Wl,-rpath=XORIGIN/../lib" ./configure --prefix=/blabla/place

See the X? That will be replaced by a dollar sign later when you run chrpath on the resultant binaries.

这是一个工作示例,如何使用 bash$ORIGIN 传递给多个级别的 makefile:

SHELL := /bin/bash

ifeq (${MAKELEVEL},0)
export LDFLAGS := -Wl,-rpath=`printf "%bORIGIN" "4"`
endif

all :
    @echo MAKELEVEL=${MAKELEVEL} LDFLAGS=${LDFLAGS}
    @if [[ ${MAKELEVEL} -lt 3 ]]; then ${MAKE}; fi

输出:

$ make --no-print-directory
MAKELEVEL=0 LDFLAGS=-Wl,-rpath=$ORIGIN
MAKELEVEL=1 LDFLAGS=-Wl,-rpath=$ORIGIN
MAKELEVEL=2 LDFLAGS=-Wl,-rpath=$ORIGIN
MAKELEVEL=3 LDFLAGS=-Wl,-rpath=$ORIGIN

或者,如果您使用 Linux,在没有 $ORIGIN 的情况下构建,然后使用 Exodus 进行 无痛重定位 Linux 二进制文件 – 以及所有他们的依赖关系——没有容器.

从表面上看,这似乎是 make 与环境变量集成时可能出现的意外错误。似乎每当 'make' 拾取环境变量时,它都会 'expand' 任何 '$v'(以及可能的其他构造)。

考虑这个非常简单的 makefile

all:
    echo "V=$V"
    env | grep V=

将 V 设置为 '$$SHELL' (bash export V='$$SHELL'),运行 make 将显示内部 'V'变量是/bin/bash,而环境变量是'$$SHELL'

echo "V=$SHELL"
V=/bin/bash
env | grep V=
V=$$SHELL

抛开这个问题是特性还是错误,您可以使用 $(value var) 函数来访问 "raw" 值。在 child 中使用:

# Append extra flags to env LDFLAGS, without 'expansion'
export LDFLAGS := $(value LDFLAGS) -Wl,-rpath='$$ORIGIN/../..'

您还可以设置 O 的附加变量以在附加到 LDFLAGS 之前扩展到相同的变量,这样即使 make 在 [= 中扩展 $O 16=],它仍然会导致 $ORIGIN:

$ cat child1.mk
# add an additional RPATH value
O := $$O
LDFLAGS += -Wl,-rpath='$$ORIGIN/../..'

all:
        env | grep LDFLAGS

输出:

$ make
env | grep LDFLAGS
LDFLAGS=-Wl,-rpath='$ORIGIN'
make -f child1.mk
make[1]: Entering directory '/home/raspy/so-62298900'
env | grep LDFLAGS
LDFLAGS=-Wl,-rpath='$ORIGIN' -Wl,-rpath='$ORIGIN/../..'
make[1]: Leaving directory '/home/raspy/so-62298900'
make -f child2.mk
make[1]: Entering directory '/home/raspy/so-62298900'
env | grep LDFLAGS
LDFLAGS=-Wl,-rpath='$ORIGIN'
make[1]: Leaving directory '/home/raspy/so-62298900'