如何递归地用 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
本身的作用非常接近。
当然,如果您这样做,则无需担心执行额外的扩展。
我正在处理 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
本身的作用非常接近。
当然,如果您这样做,则无需担心执行额外的扩展。