如何递归地用 bash 中的路径变量替换 configure.ac 中的变量?

How to recursively substitute variable for a path in bash variable in configure.ac?

我正在处理 autotools,情况如下:

默认情况下 libdir 设置为 '${exec_prefix}/lib'exec_prefix 设置为 '${prefix}' 并且 prefix 设置为 '/usr/local'.

这里的关键是递归,在第一级 libdir 变量包含另一个变量 一个后续路径。

那么如何将${libdir}转换成包含'/usr/local/lib'的变量呢?

信息:所有 3 个(libdir、exec_prefix、前缀)都可以根据配置进行更改。

考虑以下文件:

configure.ac

AC_PREREQ([2.59])
AC_INIT([test], [0.0.0] )
AM_INIT_AUTOMAKE()
AC_CONFIG_SRCDIR([test.cpp])
AC_LANG([C++])
AC_PROG_CXXCPP
AC_PROG_CXX

AC_CONFIG_FILES([Makefile path.conf])

AC_MSG_NOTICE([">>> Before ac_output prefix=${prefix}"])
AC_OUTPUT
AC_MSG_NOTICE([">>> after ac_output prefix=${prefix}"])

Makefile.am

bin_PROGRAMS = test
test_SOURCES = test.cpp

test.cpp

int main()
{}

path.conf.in

@libdir@

然后在调用之后:

aclocal && autoconf && automake -a --foreign && ./configure

配置日志显示:

configure: ">>> Before ac_output prefix=NONE"
...
...
...
configure: ">>> after ac_output prefix=/usr/local"

并且生成的文件 path.conf 包含

${exec_prefix}/lib

目标是让一个变量包含要在 path.conf.in 中使用的路径的扩展版本,以便 autotools 生成 path.conf 使用扩展路径。


编辑:Bash唯一的解决方案

挖掘相关主题并在@Aserre 回答的帮助下,我设法使用正则表达式执行以下操作。

while expr match "${libdir}" '^.*$.*$' 1>/dev/null;
do
    echo ">${libdir}"
    libdir="$(eval echo ${libdir})"
done

这意味着:虽然 $libdir 包含一个 $ 扩展 eval.

但在 AC_OUTPUT

之前的 configure.ac 脚本中不起作用

如果您 100% 确定 ${exec_prefix} 变量的内容,您可以使用以下行来实现您想要的:

libdir="$(eval echo ${exec_prefix})"

请注意,在很多情况下,不鼓励使用 eval。在这里,如果用户覆盖了变量 exec_prefix 的内容,例如使用 exec_prefix='a; rm -rf /',将执行所有编写的代码。

如果您完全控制您的环境(即您在启动脚本时确定变量的值),应该没有问题,否则要警惕潜在的副作用

The goal is to have a variable containing the expanded version of the path to be used in a path.conf.in so autotools generate path.conf with that expanded path.

Autotools 为安装目录变量的默认值提供特殊处理,以便用户能够在 make install 时间指定或覆盖安装前缀:

make install prefix=/my/special/prefix

你打算做的事情会打破它。如果用户在安装阶段指定的安装前缀与他们告诉 configure 的不同(或者他们让 configure 默认选择),那么您将以失败的安装结束。

解决此类问题的最佳方法是在 make 的控制下在 make install 时构建配置文件,而不是在配置时构建。如果项目使用 Automake,那么这可能意味着:

install-data-local:
    $(SED) -e 's,[@]libdir[@],$(libdir),' path.conf.in > $(sysconfdir)/path.conf
    chmod 0644 $(sysconfdir)/path.conf
    chown root:root $(sysconfdir)/path.conf

uninstall-local:
    rm $(sysconfdir)/path.conf

如果您愿意,您当然可以替换比这更多的输出变量。它与 configure 本身的作用非常接近。

当然,如果您这样做,则无需担心执行额外的扩展。