Subject: bug#8616: conflict between build-aux/compile script and coreutils Makefiles

From: Jim Meyering <[email-masked]>
Date: Thu, 05 May 2011 12:42:07 +0200

Green, Paul wrote:
> Gentle Coreutils Developers,
>
> I am writing to notify you of an issue that I stumbled across while
> building coreutils-8.12 on the Stratus OpenVOS platform.

Hi Paul,

Thanks for the detailed report.
I'm Cc'ing the automake list, since that's
the source of the compile script.

> On this platform, we have both gcc and a native cc compiler. While gcc
> handles the combination of the -c and -o arguments, our native cc
> compiler does not. Thus, the coreutils configure script sets
> ac_cv_prog_gcc_cc_c_o=no. This leads to using the build-aux/compile
> script, which in turn leads to the following "interesting" result
> (edited for clarity):
>
>   CC       version.o
>   AR       libver.a
>   CC       cp.o
>   CC       copy.o  (point 1)
>   CC       cp-hash.o
>   CC       extent-scan.o
>   CCLD     cp.pm
>   CC       ginstall-install.o
>   CC       ginstall-prog-fprintf.o
>   CC       ginstall-copy.o  (point 2)
>   CC       ginstall-cp-hash.o
>   CC       ginstall-extent-scan.o
>   CCLD     ginstall.pm
>   CC       mv.o
>   CC       remove.o
>   CCLD     mv.pm
> gcc: copy.o: No such file or directory.
> gcc: cp-hash.o: No such file or directory.
> gcc: extent-scan.o: No such file or directory.
> make[3]: *** [mv.pm] Error 1
>
> The root cause of this failure is as follows. The same issue affects
> copy.o, cp-hash.o and extent-scan.o, but I'll just focus on copy.o.
>
> At point 1, the build-aux/compile runs gcc (w/o -o) to produce copy.o.
> At point 2, the script produces copy.o again, then renames it to
> ginstall-copy.o, thereby deleting copy.o.
>
> The src/Makefile does not list copy.o as a dependency of mv.pm (Oops),
> so Make does not rebuild copy.o prior to running the link command.

My src/Makefile and src/Makefile.in do include that dependency,
assuming your EXEEXT is ".pm".
Does your version of that file look different from this?

    am__objects_1 = copy.$(OBJEXT) cp-hash.$(OBJEXT) extent-scan.$(OBJEXT)
    am_mv_OBJECTS = mv.$(OBJEXT) remove.$(OBJEXT) $(am__objects_1)
    mv_OBJECTS = $(am_mv_OBJECTS)
    ...
    mv$(EXEEXT): $(mv_OBJECTS) $(mv_DEPENDENCIES) $(EXTRA_mv_DEPENDENCIES)

This is not due to a missing dependency,
but rather that the compile script removes copy.o
in the process of creating ginstall-copy.o.
You can see that by the fact that when you rerun "make"
after the above failure, it does regenerate copy.o.

> Hence, the linker (gcc) complains that it cannot find the file.
>
> On a platform where both cc and $CC handle the combination of -c and -o
> correctly, this issue cannot arise.
>
> The solution is either to make the compile script smarter, or to have
> the dependencies of mv.pm properly listed, or to have mv.pm depend upon
> a renamed copy of copy.o, much as is done for ginstall, or to set the
> environment variable ac_cv_prog_cc_gcc_c_o=yes before running configure.
> This last technique presumes that the faulty "cc" compiler is never
> actually used, which seems to be the case here.
>
> Speaking as someone who is fairly familiar with bash, make, and
> autoconf, this was still took a lot longer to figure out that I'd like
> to admit.  I believe that I have correctly explained the issue, but I
> apologize if there are errors in the above description.
>
> I suspect that you can reproduce this issue by forcing
> ac_cv_prog_cc_gcc_c_o=no and then running configure.

Running this,
  ac_cv_prog_cc_gcc_c_o=no ./configure && make
I was indeed able to reproduce it.

I think you're right that making "compile" smarter is the way to go.
It looks like it could be modified to link (or copy) the source file
to some temporary file name, e.g., copy-xYV4aP.c, compile that
to copy-xYV4aP.o, and rename the latter to the destination .o file.
Of course, it would have to remove the temporary file upon termination--
both irregular and normal.

This would also resolve the parallel build race whereby two or more
programs using the same object file both compile the same source to
the same object and rename that file to a different destination.

To the automake folks, is there any reason not to do that?