bug-gnu-utils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

parallel build of gettext may fail


From: Ralf Wildenhues
Subject: parallel build of gettext may fail
Date: Fri, 27 Oct 2006 17:51:43 +0200
User-agent: Mutt/1.5.13 (2006-10-09)

Hello Bruno,

gettext-tools/libgettextpo/Makefile.am contains a code snippet like
this:

BUILT_SOURCES += config.h
config.h:
        { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
          : "Avoid double inclusion, to avoid a warning about redefinition of 
DLL_VARIABLE."; \
[...]
        } > config.h && \
        { $(MAKE) $(BUILT_SOURCES) || { rm -f config.h; exit 1; }; } && \
        if test -n "$(HAVE_GLOBAL_SYMBOL_PIPE)"; then \
          { \
            for f in $(libgettextpo_la_AUXSOURCES) $(libgnu_la_SOURCES) 
$(libgnu_la_LIBADD); do \
              case $$f in \
                *.c | *.$(OBJEXT) | *.lo ) \
                  sf=`echo "$$f" | sed -e 's,\\.[^.]*$$,,'`.c; \
                  of=`echo "$$f" | sed -e 's,^.*/,,' -e 
's,\\.[^.]*$$,,'`.$(OBJEXT); \
                  $(COMPILE) -c $(srcdir)/$$sf || { rm -f config.h; exit 1; }; \
                  sh ./exported.sh $$of 1>&5; \
                  rm -f $$of; \
                  ;; \
              esac; \
            done; \
          } 5>&1 \
            | sed -e 's,.* ,,' | LC_ALL=C sort | LC_ALL=C uniq \
            | sed -e 's,^obstack_free$$,__obstack_free,' \
            | sed -e 's,^\(.*\)$$,#define \1 libgettextpo_\1,' > config.h-t && \
          if test -f config.h; then \
            cat config.h-t >> config.h; \
            rm -f config.h-t; \
          else \
            rm -f config.h-t; \
            exit 1; \
          fi \
        fi
MOSTLYCLEANFILES += config.h config.h-t

This code warrants (at least) two comments:

1) Since the inner $(MAKE) is unaware of the work of any outer ones
on the `$(BUILT_SOURCES)' targets, there is a race condition for
parallel make invocations.  This race easily breaks a build on a system
with several CPUs:

$ make -j2
{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
          : "Avoid double inclusion, to avoid a warning about redefinition of 
DLL_VARIABLE."; \
[...]
          echo '#endif /* GTPO_CONFIG_H */'; \
        } > config.h && \
        { make config.h gettext-po.h alloca.h configmake.h  stdint.h || { rm -f 
config.h; exit 1; }; } && \
        if test -n "1"; then \
          { \
            for f in ../src/str-list.c ../src/dir-list.c ../src/message.c 
../src/msgl-ascii.c ../src/po-error.c ../src/po-xerror.c ../src/write-catalog.c 
../src/write-po.c ../src/open-catalog.c ../src/po-charset.c ../src/po-lex.c 
../src/po-gram-gen.c ../src/read-po.c ../src/read-catalog-abstract.c 
../src/read-catalog.c ../src/plural-table.c ../src/format-c.c 
../src/format-sh.c ../src/format-python.c ../src/format-lisp.c 
../src/format-elisp.c ../src/format-librep.c ../src/format-scheme.c 
../src/format-java.c ../src/format-csharp.c ../src/format-awk.c 
../src/format-pascal.c ../src/format-ycp.c ../src/format-tcl.c 
../src/format-perl.c ../src/format-perl-brace.c ../src/format-php.c 
../src/format-gcc-internal.c ../src/format-qt.c ../src/format-boost.c 
../src/format.c ../src/plural-exp.c ../src/plural-eval.c ../src/msgl-check.c 
allocsa.h allocsa.c basename.h basename.c c-ctype.h c-ctype.c c-strcase.h 
c-strcasecmp.c c-strncasecmp.c c-strstr.h c-strstr.c error-progname.h 
error-progname.c exit.h exitfail.h exitfail.c fstrcmp.h fstrcmp.c fwriteerror.h 
fwriteerror.c gcd.h gcd.c gettext.h hash.h hash.c linebreak.h linebreak.c 
lbrkprop.h localcharset.h localcharset.c lock.h lock.c mbswidth.h mbswidth.c 
minmax.h pathname.h concatpath.c progname.h progname.c size_max.h striconv.h 
striconv.c tls.h tls.c ucs4-utf8.h utf16-ucs4.h utf8-ucs4.h wcwidth.h xalloc.h 
xmalloc.c xstrdup.c xallocsa.h xallocsa.c xerror.h xerror.c xsize.h xstriconv.h 
xstriconv.c xvasprintf.h xvasprintf.c xasprintf.c ; do \
              case $f in \
                *.c | *.o | *.lo ) \
                  sf=`echo "$f" | sed -e 's,\\.[^.]*$,,'`.c; \
                  of=`echo "$f" | sed -e 's,^.*/,,' -e 's,\\.[^.]*$,,'`.o; \
                  gcc -DHAVE_CONFIG_H -I. -I.. 
-I../../../gettext-0.16/gettext-tools/libgettextpo  -I. 
-I../../../gettext-0.16/gettext-tools/libgettextpo -I.. 
-I../../../gettext-0.16/gettext-tools -I../src 
-I../../../gettext-0.16/gettext-tools/src -I../intl 
-I../../../gettext-0.16/gettext-tools/../gettext-runtime/intl   -g -O2 -c 
../../../gettext-0.16/gettext-tools/libgettextpo/$sf || { rm -f config.h; exit 
1; }; \
                  sh ./exported.sh $of 1>&5; \
                  rm -f $of; \
                  ;; \
              esac; \
            done; \
          } 5>&1 \
            | sed -e 's,.* ,,' | LC_ALL=C sort | LC_ALL=C uniq \
            | sed -e 's,^obstack_free$,__obstack_free,' \
            | sed -e 's,^\(.*\)$,#define \1 libgettextpo_\1,' > config.h-t && \
          if test -f config.h; then \
            cat config.h-t >> config.h; \
            rm -f config.h-t; \
          else \
            rm -f config.h-t; \
            exit 1; \
          fi \
        fi
cp ../../../gettext-0.16/gettext-tools/libgettextpo/gettext-po.h.in 
gettext-po.h-tmp
mv gettext-po.h-tmp gettext-po.h
{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
          cat ../../../gettext-0.16/gettext-tools/libgettextpo/alloca_.h; \
        } > alloca.h-t
mv -f alloca.h-t alloca.h
make[1]: Entering directory `/tmp/gettext/build-0.16/gettext-tools/libgettextpo'
make[1]: `config.h' is up to date.
make[1]: `gettext-po.h' is up to date.
{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
          cat ../../../gettext-0.16/gettext-tools/libgettextpo/alloca_.h; \
        } > alloca.h-t
rm -f configmake.h-t configmake.h
mv -f alloca.h-t alloca.h
{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
          echo '#define PREFIX "/usr/local"'; \
[...]
          echo '#define PKGLIBEXECDIR ""'; \
        } | sed '/""/d' > configmake.h-t
mv configmake.h-t configmake.h
mv: cannot stat `alloca.h-t': No such file or directory
make[1]: *** [alloca.h] Error 1
make[1]: Leaving directory `/tmp/gettext/build-0.16/gettext-tools/libgettextpo'
rm -f stdint.h-t stdint.h
{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
          sed -e 's/@''HAVE_WCHAR_H''@/1/g' \
[...]
              -e 's/@''WINT_T_SUFFIX''@/u/g' \
              < ../../../gettext-0.16/gettext-tools/libgettextpo/stdint_.h; \
        } > stdint.h-t
make: *** [config.h] Error 1
make: *** Waiting for unfinished jobs....
mv stdint.h-t stdint.h


2) Solaris make with its dreaded VPATH rewriting "feature" will, in this
loop:

for f in $(libgettextpo_la_AUXSOURCES) $(libgnu_la_SOURCES) 
$(libgnu_la_LIBADD); do
\
              case $$f in \
                *.c | *.$(OBJEXT) | *.lo ) \
                  sf=`echo "$$f" | sed -e 's,\\.[^.]*$$,,'`.c; \
                  of=`echo "$$f" | sed -e 's,^.*/,,' -e 
's,\\.[^.]*$$,,'`.$(OBJEXT); \
                  $(COMPILE) -c $(srcdir)/$$sf || { rm -f config.h; exit 1; }; \

rewrite all f that point to files from the source tree to contain a
$(srcdir) prefix.  Since you do not strip it, the compile command will
pass a doubled $(srcdir) prefix.

Automake itself works around this (in non-inference rules) like this:
   ... -c `test -f '$(SOURCE)' || echo '$(srcdir)/'`$(SOURCE)

with $(SOURCE) replaced by the source file name.

Hope that helps.

Cheers,
Ralf




reply via email to

[Prev in Thread] Current Thread [Next in Thread]