【问题标题】:How to recursively substitute variable for a path in bash variable in configure.ac?如何在configure.ac中递归替换bash变量中的路径?
【发布时间】:2019-06-21 15:42:19
【问题描述】:

我正在处理自动工具,情况如下:

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

这里的关键递归和在第一级libdir变量包含另一个变量以下路径。

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

Info : 所有 3 (libdir, exec_prefix, prefix) 都可以根据配置进行更改。

考虑以下文件:

配置.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 中使用一个包含扩展版本路径的变量,以便自动工具生成具有扩展的 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 脚本中不起作用

【问题讨论】:

  • exec_prefixliteral 字符串 ${prefix}?为什么不(我承认,我对自动工具一无所知)只是等到prefix 有一个值来设置exec_prefix=${prefix}
  • @chepner : echo ${libdir} 返回 ${exec_prefix}/lib
  • 是的,@chepner,这是故意的,以便用户在运行 make install 时可以覆盖安装前缀。 ${prefix} 通常由 make 扩展。
  • @Nelstaar,你能解释一下你为什么要这样做吗?因为更漂亮(更好)的解决方案可能是什么都不做。

标签: bash autotools autoconf


【解决方案1】:

目标是在 path.conf.in 中使用一个包含扩展版本路径的变量,以便自动工具生成具有扩展的 path.conf路径。

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 本身所做的非常接近。

当然,如果你这样做,那么你不必担心执行额外的扩展。

【讨论】:

  • 我希望在配置时有解决方案。谢谢@John Bollinger
  • 我认为任何理智的 autoconf 用户都不需要这个功能,但它给其他人带来了无穷无尽的麻烦。
  • 我不关注,@Rich。您在谈论哪个功能,它如何给任何人带来麻烦?
  • @Nelstaar build-time solution 会帮忙吗?
【解决方案2】:

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

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

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

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

【讨论】:

  • 当然 libdir 的内容可能会发生变化。就像调用 ./configure --libdir=/what/ever/path 时一样
猜你喜欢
  • 2013-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-25
  • 2016-12-02
  • 2013-09-24
相关资源
最近更新 更多