This is the mail archive of the
mailing list for the GCC project.
PR/15448: add a compiler timestamp to PCH files
While, this would be good, it isn't the fix to the problem you
describe. The way to add better validation would be to add __TIME__ to
the compiler and validate it across PCH usage. This way, if the
compiler is ever rebuilt, we get a new timestamp, which then will kill
all PCH files.
Unless I am misunderstanding you, we were speaking of the same solution.
Unluckily, getting the timestamp from the preprocessor is a sure recipe
for a bootstrap comparison failure on the file where you put the
timestamp. I even implemented it, having libcpp define an unsigned long
__TIMESTAMP__ together with __DATE__ and __TIME__, but it fails
bootstrap for that precise reason.
Thinking more about it, my patch would not have worked even in my case,
because c-pch.c was not changed by my cvs update, and thus make would
not have bootstrapped the compiler. So, the timestamp should be put
into a file that is compiled to a different extension than .o, and the
object file should be made dependent on every C file in a front-end;
but, I wouldn't like adding more and more hacks to the GCC Makefile.
The executable path can be used on Linux to find the compiler timestamp
(see the attached patch). A similar test is used in libjava, but I
enhanced it by supporting the cache variable even in the
cross-compilation case (Canadian in gcc's case), so that the test can be
Unlike Autoconf's AC_CHECK_FILES, an absolute path is expected and the
leading / is accounted for when creating the name of the #define (so we
have HAVE_PROC_SELF_EXE while Autoconf would yield HAVE__PROC_SELF_EXE).
To fix the problem you describe, the PCH building rules in libstdc++
should just always rebuild them. If they want to get crafty, they can
check the timestamp on the compiler (cc1plus), and ensure that the PCH
is rebuilt if the compiler is newer.
That's just a workaround (maybe a necessary one in GCC, where
libstdc++-v3 also acts as a PCH testsuite). But it cannot be used
outside GCC, even though the bug is present there for people who build
their own GCC and are not developers. Non-bootstrapped, bootstrapped
and profiledbootstrapped installations, for example, have the same
version string but their PCH's are incompatible.
The attached patch was bootstrapped and regtested (C/C++ only) on
i686-pc-linux-gnu, and I checked on powerpc-darwin that
HAVE_PROC_SELF_EXE is not misdetected. Ok for mainline?
2005-05-16 Paolo Bonzini <email@example.com>
* aclocal.m4 (GCC_CHECK_FILE_CROSS): New.
* configure.ac: Use it.
* configure: Regenerate.
* config.in: Regenerate.
* c-pch.c (get_ident) [HAVE_PROC_SELF_EXE]: Add a fingerprint
made from the compiler's size and modification time.
RCS file: /cvs/gcc/gcc/gcc/configure.ac,v
retrieving revision 2.94
diff -u -p -r2.94 configure.ac
--- configure.ac 7 Feb 2005 23:10:54 -0000 2.94
+++ configure.ac 16 Feb 2005 10:58:09 -0000
@@ -878,6 +878,12 @@ AC_CHECK_HEADER(pthread.h, [have_pthread
+# Checks for other host features
RCS file: /cvs/gcc/gcc/gcc/aclocal.m4,v
retrieving revision 1.100
diff -u -p -r1.100 aclocal.m4
--- aclocal.m4 2 Dec 2004 11:04:01 -0000 1.100
+++ aclocal.m4 16 Feb 2005 10:58:17 -0000
@@ -657,3 +657,23 @@ AC_PREREQ([2.50])dnl
# expand $ac_aux_dir to an absolute path
am_aux_dir=`cd $ac_aux_dir && pwd`
+m4_bmatch([$1], [^/.*], ,
+ [m4_fatal([GCC_CHECK_FILE_CROSS expects an absolute pathname])])
+AC_CACHE_CHECK([for $1], ac_File,
+[if test "$cross_compiling" = yes; then
+ case $host in
+ $2) AS_VAR_SET(ac_File, yes) ;;
+ *) AS_VAR_SET(ac_File, no) ;;
+elif test -r "$1"; then
+ AS_VAR_SET(ac_File, yes)
+ AS_VAR_SET(ac_File, no)
+AS_IF([test AS_VAR_GET(ac_File) = yes],
+ [AC_DEFINE(HAVEAS_TR_CPP([$1]), 1, [Define if you have $1])])
RCS file: /cvs/gcc/gcc/gcc/c-pch.c,v
retrieving revision 1.30
diff -u -p -r1.30 c-pch.c
--- c-pch.c 9 Nov 2004 10:12:15 -0000 1.30
+++ c-pch.c 16 Feb 2005 10:58:20 -0000
@@ -104,10 +104,23 @@ get_ident (void)
static char result[IDENT_LENGTH];
static const char template[IDENT_LENGTH] = "gpch.012";
static const char c_language_chars = "Co+O";
+ struct stat s;
memcpy (result, template, IDENT_LENGTH);
result = c_language_chars[c_language];
+ if (stat ("/proc/self/exe", &s) != -1)
+ int fingerprint = (int) s.st_size ^ (int) (8087 * s.st_mtime);
+ result = (fingerprint & 255);
+ result = (fingerprint & 0xFF00) >> 8;
+ result = (fingerprint & 0xFF0000) >> 16;