DevHeads.net

Autoreconf race condition?

Hello all!

I've run into a problem when I was trying to build tftp (master branch) package locally.

~/work/tftp$ fedpkg local
...
config.status: creating MCONFIG
config.status: creating aconfig.h
configure: WARNING: unrecognized options: --disable-dependency-tracking
+ make -j4
rm -f aconfig.h.in aconfig.h
echo \#define VERSION \"tftp-hpa `cat version`\" > version.h
autoheader
make -C lib
make -C common
make[1]: Entering directory `/home/jsynacek/work/tftp/tftp-hpa-5.2/common'
gcc -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector
--param=ssp-buffer-size=4 -m64 -mtune=generic -W -Wall -Wpointer-arith
-Wbad-function-cast -Wstrict-prototypes -Wmissing-prototypes
-Wmissing-declarations -Wnested-externs -Winline -Wwrite-strings -Wundef
-Wshadow -Wsign-compare -pipe -fno-strict-aliasing
-I/home/jsynacek/work/tftp/tftp-hpa-5.2 -c tftpsubs.c
make[1]: Entering directory `/home/jsynacek/work/tftp/tftp-hpa-5.2/lib'
make[1]: Nothing to be done for `all'.
make[1]: Leaving directory `/home/jsynacek/work/tftp/tftp-hpa-5.2/lib'
In file included from tftpsubs.h:41:0,
from tftpsubs.c:34:
/home/jsynacek/work/tftp/tftp-hpa-5.2/config.h:21:73: fatal error: aconfig.h: No
such file or directory
compilation terminated.

Notice the execution of rm -f aconfig.h *after* make. The spec doesn't seem to
be wrong:

...
autoreconf
%configure
make %{?_smp_mflags}
...

And here is the corresponding part from the build log:

...
autoreconf
CFLAGS="${CFLAGS:--O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=gen
CXXFLAGS="${CXXFLAGS:--O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune
FFLAGS="${FFLAGS:--O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=gen
LDFLAGS="${LDFLAGS:--Wl,-z,relro }"; export LDFLAGS;
./configure --build=x86_64-unknown-linux-gnu --host=x86_64-unknown-linux-gnu \
--program-prefix= \
--disable-dependency-tracking \
--prefix=/usr \
--exec-prefix=/usr \
--bindir=/usr/bin \
--sbindir=/usr/sbin \
--sysconfdir=/etc \
--datadir=/usr/share \
--includedir=/usr/include \
--libdir=/usr/lib64 \
--libexecdir=/usr/libexec \
--localstatedir=/var \
--sharedstatedir=/var/lib \
--mandir=/usr/share/man \
--infodir=/usr/share/info
make -j4
...

I also noticed a rather weird comment in the Makefile:

# Adding "configure" to the dependencies serializes this with running
# autoconf, because there are apparently race conditions between
# autoconf and autoheader.
aconfig.h.in: configure.in configure aclocal.m4
rm -f aconfig.h.in aconfig.h
autoheader

This part also seems to be causing my problem. Adding configure to the
dependencies apparently does not help.

I don't really know what the root cause of my problem is. I looks like a race
condition between some of the autotools, but I'm not really sure.

The problem goes away when I add sleep 1 between autoreconf and %configure in
the spec file.

Any ideas?

Thanks,

Comments

Re: Autoreconf race condition?

By Petr Pisar at 05/22/2012 - 08:21

On 2012-05-22, Jan Synacek < ... at redhat dot com> wrote:
That's how the Makefile is written. Unfortunatelly, it does not define
all targets produced by each command. Also the make compares
modification times of targets and prerequisites. And that's the reason,
why make does not re-run configure (needed to generate aconfig.h removed
before explicitly). You can see it by running:

$ make -j5 -n --no-builtin-rules -d
[...]
No implicit rule found for `all'.
Considering target file `MCONFIG'.
Considering target file `configure'.
Considering target file `configure.in'.
Looking for an implicit rule for `configure.in'.
No implicit rule found for `configure.in'.
Finished prerequisites of target file `configure.in'.
No need to remake target `configure.in'.
Considering target file `aclocal.m4'.
Looking for an implicit rule for `aclocal.m4'.
No implicit rule found for `aclocal.m4'.
Finished prerequisites of target file `aclocal.m4'.
No need to remake target `aclocal.m4'.
Finished prerequisites of target file `configure'.
Prerequisite `configure.in' is older than target `configure'.
Prerequisite `aclocal.m4' is older than target `configure'.
No need to remake target `configure'.
Considering target file `MCONFIG.in'.
Looking for an implicit rule for `MCONFIG.in'.
No implicit rule found for `MCONFIG.in'.
Finished prerequisites of target file `MCONFIG.in'.
No need to remake target `MCONFIG.in'.
Considering target file `aconfig.h.in'.
Pruning file `configure.in'.
Pruning file `configure'.
Pruning file `aclocal.m4'.
Finished prerequisites of target file `aconfig.h.in'.
Prerequisite `configure.in' is older than target `aconfig.h.in'.
→ Prerequisite `configure' is newer than target `aconfig.h.in'.
Prerequisite `aclocal.m4' is older than target `aconfig.h.in'.
Must remake target `aconfig.h.in'.
[...]

Which is dragged in by upstream `fix':
Thus you get rm file removal without re-runing configure. The last
bullet is they remove a file which has been already considered by make
as up-to-date target (and call it side-effect).

I would remove the configure prequisite from aconfig.h.in target (that's
really fake dependency) or touch the files to get better ordering.

-- Petr