2

I am dealing with autotools and here is the situation:

By default libdir is set to '${exec_prefix}/lib' with exec_prefix set to '${prefix}' and prefix set to '/usr/local'.

Key here recursion and at first level libdir variable contain another variable and a following path.

So how to convert ${libdir} into a variable containing '/usr/local/lib' ?

Info : all 3 (libdir, exec_prefix, prefix) can change according configuration.

Consider the following files:

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@

Then after invoking :

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

configure log show:

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

And generated file path.conf contains

${exec_prefix}/lib

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.


Edit: Bash only solution

Digging related topics and helped by @Aserre answer, I manage to do the following with a regex.

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

Which means : While $libdir contain one $ expand with eval.

But does not work in configure.ac script before AC_OUTPUT

Mike Kinghan
  • 55,740
  • 12
  • 153
  • 182
Nelstaar
  • 769
  • 9
  • 26
  • `exec_prefix` is the *literal* string `${prefix}`? Why not (and I admit, I am ignorant about autotools) just wait until `prefix` has a value to set `exec_prefix=${prefix}`? – chepner Jan 28 '19 at 15:41
  • @chepner : _echo ${libdir}_ return _${exec_prefix}/lib_ – Nelstaar Jan 28 '19 at 16:22
  • 1
    Yes, @chepner, and that is deliberate, so that the user can override the installation prefix when they run `make install`. The `${prefix}` is ordinarily expanded by `make`. – John Bollinger Jan 28 '19 at 17:54
  • @Nelstaar, can you perhaps explain why you want to do this? Because a prettier (and better) solution *might* be to do nothing. – John Bollinger Jan 28 '19 at 17:56
  • Possible duplicate of [Bash expand variable in a variable](https://stackoverflow.com/questions/14049057/bash-expand-variable-in-a-variable) – John Bollinger Jan 28 '19 at 18:11
  • @John Bollinger, question edited, but I just figured out that $prefix and $exec_prefix are set to NONE by defaut before AC_OUTPUT call. :_( – Nelstaar Jan 28 '19 at 18:12
  • Although the proposed dupe target asks about Bash specifically, the answers include both Bash-specific and general POSIX-conforming alternatives. – John Bollinger Jan 28 '19 at 18:12
  • @Nelstaar, maybe it's time for a [mcve], then. I have worked rather a lot with the Autotools, and I have never seen the `$prefix` or `$exec_prefix` reset automatically. I have especially not seen them reset to "NONE" -- if you do not specify them at all, then the default for `$prefix` is `/usr/local`, and this is what normally ends up being used in such cases. – John Bollinger Jan 28 '19 at 18:15

2 Answers2

4

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.

The Autotools provide special handling for default values of the installation-directory variables, in order to enable the user to specify or override the installation prefix at make install time:

make install prefix=/my/special/prefix

What you propose to do will break that. If a user specifies a different installation prefix at the installation stage than they tell configure (or that they let configure choose by default) then you will end up with a broken installation.

The best way to do address problems like this is to build the configuration file under make's control, at make install time, instead of doing it at configuration time. If the project uses Automake, then that might mean something like this:

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

You can of course substitute more output variables than that if you like. It's pretty close to what configure does itself.

And of course, if you do it this way then you do not need to worry about performing extra expansions.

Nelstaar
  • 769
  • 9
  • 26
John Bollinger
  • 160,171
  • 8
  • 81
  • 157
2

If you are 100% sure of the content of the ${exec_prefix} variable, you could use the following line to achieve what you want :

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

Note that in a lot of cases, the use of eval is discouraged. Here, if the user has overriden the content of the variable exec_prefix, for instance with exec_prefix='a; rm -rf /', all the code written will be executed.

If you are in total control of your environment (i.e. you are certain of the value of the variables when you launch the script), there should be no problem, otherwise be wary of the potential side effects

Aserre
  • 4,916
  • 5
  • 33
  • 56
  • Of course content of libdir is subject to change. Like when invoking ./configure --libdir=/what/ever/path – Nelstaar Jan 28 '19 at 16:20