Weird behavior in glibc Makefiles, or: another example why you should never build software as root user
Thomas Schwinge
thomas@schwinge.name
Thu Sep 22 11:50:00 GMT 2011
Hi!
This is about an oddity in glibc's Makefiles. The underlying Makefile
issue is generally valid even if it was triggered on GNU/Hurd in this
case.
My first email on this topic has been eaten by the libc-alpha moderators
(and I did not exactly enjoy their boilerplate answer); perhaps this one
will make it through? At least I would consider it on-topic for
libc-alpha.
On Tue, 20 Sep 2011 10:49:06 +0200, I wrote:
> About a year ago I have once seen this while running ``make check'' after
> having run ``make check'' before on the same build tree. Now, on a
> different system, I have seen it with a plain ``make''. Mind you, *not*
> ``make install''.
>
> [...]
> make subdir=nss -C nss ..=../ others
> make[2]: Entering directory `/media/erich/home/thomas/tmp/glibc/tschwinge/Roger_Whittaker/nss'
> /usr/bin/install -c -m 644 ../include/pthread.h /usr/include/pthread.h
> /usr/bin/install: cannot remove `/usr/include/pthread.h': Permission denied
> make[2]: *** [/usr/include/pthread.h] Error 1
> make[2]: Leaving directory `/media/erich/home/thomas/tmp/glibc/tschwinge/Roger_Whittaker/nss'
> make[1]: *** [nss/others] Error 2
> make[1]: Leaving directory `/media/erich/home/thomas/tmp/glibc/tschwinge/Roger_Whittaker'
> make: *** [all] Error 2
>
> That happend after I was editing nss/nss_db/db-initgroups.c, and then
> resuming the build.
>
> I guess nobody has ever seen this before, or has an explanation for such
> behavior?
>
> This is on GNU/Hurd (but I can't see why that would matter), with Debian
> make 3.81-8.1.
>
> I will try poking around in the Makefiles later on...
Which I have now done, and here follows my analysis.
In the recent case, this behavior is triggered with
[glibc]/nss/nss_files/files-init.c. That one contains #include
<nscd/nscd.h>.
[glibc]/nscd/nscd.h contains #include <pthread.h>. <pthread.h> is
resolved to [glibc]/include/pthread.h which is a glibc-internal wrapper
that does #include_next <pthread.h> to get the real pthread header, and
additionally ``extern void __pthread_initialize (void) __attribute__
((weak));''. On GNU/Hurd, the #include_next <pthread.h> resolves to
/usr/include/pthread.h, as our libpthread is not yet integrated with
glibc. So far, so good; this works.
After the first build, [glibc.build]/nss/files-init.os.d contains these
dependency rules:
$(common-objpfx)nss/files-init.os: \
nss_files/files-init.c ../include/libc-symbols.h \
$(common-objpfx)config.h \
../sysdeps/wordsize-32/symbol-hacks.h ../nscd/nscd.h \
../include/pthread.h /usr/include/pthread.h \
/usr/include/pthread/pthread.h ../include/features.h \
[...]
That is, [glibc.build]/nss/files-init.os depends on
/usr/include/pthread.h (which is correct).
Now, [glibc]/Makerules happens to contain the following rules:
# This implicit rule installs headers from the source directory.
# It may be ignored in preference to rules from sysd-rules to find
# headers in the sysdeps tree.
$(inst_includedir)/%.h: $(objpfx)%.h $(+force)
$(do-install)
$(inst_includedir)/%.h: %.h $(+force)
$(do-install)
$(inst_includedir)/%.h: $(..)include/%.h $(+force)
$(do-install)
These are, of course intended for header installation. (But are not
guarded for the ``make install'' case.)
The last of these can be expanded as follows:
/usr/include/pthread.h: $(..)include/pthread.h $(+force)
$(do-install)
Thus, we can see what happens -- due to the *.d file containing a
files-init.os: /usr/include/pthread dependency, the build system will try
to $(do-install) from include/pthread.h to /usr/include/pthread.h -- even
in a ``make all'' or ``make check'' case, not ``make install''! This
will only be triggered on a re-make (after the *.d files have been
built), and it can also be triggered in the testsuite where there are
also several #include <pthread.h>.
At first I thought: ``Why would glibc ever install a header from
[glibc]/include/ to /usr/include/; aren't these purely for glibc-local
build-internal headers?'' But this is not true, as it turns out. For
example, on x86 GNU/Linux, include/limits.h, include/values.h,
include/features.h, include/gnu-versions.h, include/bits/xopen_lim.h,
include/gnu/libc-version.h, include/stubs-biarch.h are installed from
[glibc]/include/ to /usr/include/.
Thinking about it, a cure is to *build* (as in ``make all'') with
``install_root=/INVALID'', thus invalidating the
``$(inst_includedir)/%.h: $(..)include/%.h'' rule. This works; nice.
For a one-off build of glibc, this issue does never matter, as there are
no *.d files yet.
In the long term, we (GNU/Hurd) are planning on integrating our
libpthread with glibc, as there are other inter-dependency issues, too.
Doing so will resolve this specific case, but the general Makefile oddity
remains.
Grüße,
Thomas
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 489 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/libc-alpha/attachments/20110922/bafa2b8f/attachment.sig>
More information about the Libc-alpha
mailing list