Subject: bug#32269: AM_INIT_AUTOMAKE, subdir-objects, and $(DEPDIR) not being set correctly

From: Philip Prindeville <[email-masked]>
Date: Wed, 25 Jul 2018 00:01:07 -0600

I’m using automake 1.15.1 on Fedora 28.

I changed my AM_INIT_AUTOMAKE() to include subdir-objects.

As soon as I did this, I started seeing failures like:

make[2]: Entering directory '/home/philipp/git/snt/libntp'
Makefile:902: warning: overriding recipe for target '../lib/isc/pthreads/.dirstamp'
Makefile:802: warning: ignoring old recipe for target '../lib/isc/pthreads/.dirstamp'
Makefile:905: warning: overriding recipe for target '../lib/isc/pthreads/.deps/.dirstamp'
Makefile:805: warning: ignoring old recipe for target '../lib/isc/pthreads/.deps/.dirstamp'
Makefile:964: ../lib/isc/unix/.deps/time.Po: No such file or directory
make[2]: *** No rule to make target '../lib/isc/unix/.deps/time.Po'.  Stop.
make[2]: Leaving directory '/home/philipp/git/snt/libntp'

After some head-scratching, I noticed:

$ find . -name '$*' -print
./sntp/tests/$(top_builddir)
./tests/ntpd/$(srcdir)
./libntp/$(srcdir)
$ 

and root-caused this to here:

    # Extract the definition of DEPDIR, am__include, and am__quote
    # from the Makefile without running 'make'.
    DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
    test -z "$DEPDIR" && continue
    am__include=`sed -n 's/^am__include = //p' < "$mf"`
    test -z "$am__include" && continue
    am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
    # Find all dependency output files, they are included files with
    # $(DEPDIR) in their names.  We invoke sed twice because it is the
    # simplest approach to changing $(DEPDIR) to its actual value in the
    # expansion.
    for file in `sed -n "
      s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
         sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
      # Make sure the directory exists.
      test -f "$dirpart/$file" && continue
      fdir=`$as_dirname -- "$file" ||
…
      as_dir=$dirpart/$fdir; as_fn_mkdir_p
      # echo "creating $dirpart/$file"
      echo '# dummy' > "$dirpart/$file"
    done

Problem is, what happens if the line you’ve read looks like:

include $(srcdir)/../lib/isc/unix/$(DEPDIR)/time.Po

after mangling that, we end up with file=$(srcdir)/../lib/isc/unix/.deps/time.Po which is obviously wrong.

Yes, $(DEPDIR) needs to be substituted out… but so does every other variable potentially, including $(srcdir) …

Either subdir-objects should handle ALL possible expansions (might require some hackery and recursively calling Makefile on each line to do expansions)… or configure should make sure that $file doesn’t match /\$(.*)/ indicating that it contains unexpanded variables… and maybe suggest using @variable@ substitutions instead if possible.

If you want to reproduce this yourselves, grab the ntp-4.8.2p11 tarball and change configure.ac and sntp/configure.ac to use AM_INIT_AUTOMAKE([… subdir-objects …]) instead.

Run:

./bootstrap
./configure --with-crypto --with-threads --disable-silent-rules --disable-local-libevent

and you’ll see the broken behavior.

Thanks,

-Philip