From: Jan Nieuwenhuizen <janneke@gnu.org>
To: "Ludovic Courtès" <ludo@gnu.org>
Cc: guix-devel@gnu.org, bootstrappable@freelists.org
Subject: Re: [bootstrappable] diverse double compilation: using $ORIGIN?
Date: Fri, 10 Nov 2017 20:19:17 +0100 [thread overview]
Message-ID: <87efp6x7pm.fsf@gnu.org> (raw)
In-Reply-To: <87k1z4668j.fsf@gnu.org> (Jan Nieuwenhuizen's message of "Sun, 05 Nov 2017 17:27:24 +0100")
[-- Attachment #1: Type: text/plain, Size: 1868 bytes --]
Jan Nieuwenhuizen writes:
>>> Usage: guix build gcc-dcc
>>>
>>> Building gcc-dcc tests the diverse double compilation property
>>> of the gcc that Guix is using.
>>>
>>> * gnu/packages/bootstrappable.scm: New file.
>>> * gnu/local.mk (GNU_SYSTEM_MODULES): Add it.
>>
>> Awesome! Does it build fine out-of-the-box? I didn’t expect it to be
>> “this easy.” :-)
>
> I got very positive feedback from a slightly guix-sceptic person saying
> something like: you lisp guys can do quite a lot with very little code.
>
> However, all this patch adds is a test that fails: gcc built with gcc is
> not bit-for-bit the same as gcc built with clang.
>
> Since then I have included the build-path-prefix-map patch, use -rpath
> $ORIGIN instead of -rpath "-lib", switched to gcc-7.2.0. Still, no
> bit-reproducibility.
>
> I'll be sending updated patches soon.
Well, that took more time than I expected.
I switched from 7.2.0 to 4.7.4 as the first target for diverse double
compilation as it seems that 7.2 uses some non-reproducible hash map
that I cannot track down _and_ 4.7.x is the latest bootstrappable gcc.
Finally, I succeeded in building repro-gcc@4.7.4 using $ORIGIN for
rpath. However, gcc-ddc@4.7.4 still shows that some absolute file names
are embedded in bin/gcc (yes, I know cpp, cc1 and ../lib* hold most of
the functionality):
/gnu/store/zw672zcmykdwzm4x7l098hb94c34ak85-repro-gcc-4.7.4/bin/
/gnu/store/zw672zcmykdwzm4x7l098hb94c34ak85-repro-gcc-4.7.4/lib/gcc/
/gnu/store/zw672zcmykdwzm4x7l098hb94c34ak85repro-gcc-4.7.4._ROOT
the first one most probably comes from
static const char *const standard_bindir_prefix = STANDARD_BINDIR_PREFIX;
I haven't looked a the other two yet. I'm attaching the diffoscope diff
and the new patch. Could do with some help here.
Thanks,
janneke
[-- Attachment #2: 0001-gnu-Add-clang-gcc-gcc-ddc.-WIP.patch --]
[-- Type: text/x-patch, Size: 85165 bytes --]
From 761ec12aa3a34cd3b95a1c3d828d8bb45558d383 Mon Sep 17 00:00:00 2001
From: Jan Nieuwenhuizen <janneke@gnu.org>
Date: Thu, 2 Nov 2017 06:52:46 +0100
Subject: [PATCH] gnu: Add clang-gcc, gcc-ddc. WIP
Usage: guix build gcc-dcc
Building gcc-dcc tests the diverse double compilation property
of the gcc that Guix is using.
gcc-dcc is a meta-package that depends on repro-gcc-4.7.4 and on
clang-gcc-4.7.4 (the same GCC built with clang). The builder
checks if both gcc's are bit-by-bit identical and fails if
they differ.
* gnu/packages/patches/gcc-4-build-path-prefix-map.patch: New file.
* gnu/packages/patches/gcc-7-build-path-prefix-map.patch: New file.
* gnu/packages/bootstrappable.scm: New file.
* gnu/local.mk (GNU_SYSTEM_MODULES,dist_patch_DATA): Add them.
---
gnu/local.mk | 2 +
gnu/packages/bootstrappable.scm | 356 ++++++++
.../patches/gcc-4-build-path-prefix-map.patch | 780 +++++++++++++++++
...fns-fix-mismatch-in-gnu_inline-attributes.patch | 65 ++
.../gcc-5-reproducibility-drop-profile.patch | 36 +
.../patches/gcc-7-build-path-prefix-map.patch | 934 +++++++++++++++++++++
6 files changed, 2173 insertions(+)
create mode 100644 gnu/packages/bootstrappable.scm
create mode 100644 gnu/packages/patches/gcc-4-build-path-prefix-map.patch
create mode 100644 gnu/packages/patches/gcc-4-cfns-fix-mismatch-in-gnu_inline-attributes.patch
create mode 100644 gnu/packages/patches/gcc-5-reproducibility-drop-profile.patch
create mode 100644 gnu/packages/patches/gcc-7-build-path-prefix-map.patch
diff --git a/gnu/local.mk b/gnu/local.mk
index 71392d86c..335678160 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -79,6 +79,7 @@ GNU_SYSTEM_MODULES = \
%D%/packages/boost.scm \
%D%/packages/bootloaders.scm \
%D%/packages/bootstrap.scm \
+ %D%/packages/bootstrappable.scm \
%D%/packages/build-tools.scm \
%D%/packages/busybox.scm \
%D%/packages/c.scm \
@@ -646,6 +647,7 @@ dist_patch_DATA = \
%D%/packages/patches/gcc-5-source-date-epoch-2.patch \
%D%/packages/patches/gcc-6-arm-none-eabi-multilib.patch \
%D%/packages/patches/gcc-6-cross-environment-variables.patch \
+ %D%/packages/patches/gcc-7-build-path-prefix-map.patch \
%D%/packages/patches/gcr-disable-failing-tests.patch \
%D%/packages/patches/gcr-fix-collection-tests-to-work-with-gpg-21.patch \
%D%/packages/patches/gd-fix-tests-on-i686.patch \
diff --git a/gnu/packages/bootstrappable.scm b/gnu/packages/bootstrappable.scm
new file mode 100644
index 000000000..cbd7592db
--- /dev/null
+++ b/gnu/packages/bootstrappable.scm
@@ -0,0 +1,356 @@
+;;; GNU Guix --- Functional package management for GNU
+;;; Copyright © 2017 Jan Nieuwenhuizen <janneke@gnu.org>
+;;;
+;;; This file is part of GNU Guix.
+;;;
+;;; GNU Guix is free software; you can redistribute it and/or modify it
+;;; under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 3 of the License, or (at
+;;; your option) any later version.
+;;;
+;;; GNU Guix is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
+
+(define-module (gnu packages bootstrappable)
+ #:use-module ((guix licenses)
+ #:select (gpl3+))
+ #:use-module (gnu packages)
+ #:use-module (gnu packages bootstrap) ; glibc-dynamic-linker
+ #:use-module (gnu packages gcc)
+ #:use-module (gnu packages llvm)
+
+ #:use-module (gnu packages package-management) ; diffosscope
+ #:use-module (gnu packages acl) ; diffosscope->getfacl
+ #:use-module (gnu packages base) ; diffoscope->cmp
+ #:use-module (gnu packages vim) ; diffosscope->xxd
+
+ #:use-module (guix download)
+ #:use-module (guix packages)
+ #:use-module (guix build-system trivial)
+ #:use-module (guix utils)
+ #:use-module (srfi srfi-1))
+
+
+(define-public gcc-1.4
+ (package
+ (inherit hello)
+ (name "gcc")
+ (version "1.40")
+ (source (origin
+ (method url-fetch)
+ (uri (string-append "http://ftp.gnu.org/pub/old-gnu/gcc/gcc-"
+ version "/gcc-" version ".tar.bz2"))
+ (sha256
+ (base32
+ "0z4wzpc3cdlzn35iwkc8xsykcxz23msxgsc96r8f5s124rncadd8"))))
+ (arguments
+ `(#:make-flags ("CC=gcc")
+ #:phases
+ (modify-phases %standard-phases
+ (delete 'configure))))))
+
+(define-public gcc-4.7-$ORIGIN
+ (package
+ (inherit gcc-4.7)
+ (name "gcc-$ORIGIN")
+ ;; Using $ORIGIN we cannot have a separate "lib" output
+ ;; so let's remove lib output
+ (outputs '("out" ;commands, etc. (60+ MiB)
+ "debug")) ;debug symbols of run-time libraries
+ (arguments
+ (substitute-keyword-arguments (package-arguments gcc-4.7)
+ ((#:configure-flags original-flags)
+ ;;--with-stage1-ldflags="-Wl,-rpath,/path/to/isl/lib,-rpath,/path/to/cloog/lib,-rpath,/path/to/gmp/lib"
+ ;;`(cons "--with-boot-ldflags=-Wl,-rpath,\\$ORIGIN/../lib" ,original-flags)
+ `(cons* "--enable-languages=c"
+ "--enable-relocatable"
+ "--disable-nls"
+ "--disable-rpath"
+ ;;"--with-boot-ldflags=-Wl,-rpath,\\$$\\$$ORIGIN/../lib -Wl,-rpath,../lib -Wl,-rpath=../prev-x86_64-unknown-linux-gnu/libstdc++-v3/src/.libs/"
+ (delete "--enable-languages=c,c++" ,original-flags)))
+ ((#:phases original-phases)
+ `(modify-phases ,original-phases
+ (replace 'pre-configure
+ (lambda* (#:key inputs outputs #:allow-other-keys)
+ (let* ((libdir-suffix (or ,(%current-target-system) ""))
+ (libdir (string-append
+ (assoc-ref outputs "out")
+ libdir-suffix))
+ (origin-libdir (string-append "$ORIGIN/.." libdir-suffix))
+ (libc (assoc-ref inputs "libc")))
+ (when libc
+ ;; The following is not performed for `--without-headers'
+ ;; cross-compiler builds.
+
+ ;; Join multi-line definitions of GLIBC_DYNAMIC_LINKER* into a
+ ;; single line, to allow the next step to work properly.
+ (for-each
+ (lambda (x)
+ (substitute* (find-files "gcc/config"
+ "^(linux|gnu|sysv4)(64|-elf|-eabi)?\\.h$")
+ (("(#define (GLIBC|GNU_USER)_DYNAMIC_LINKER.*)\\\\\n$" _ line)
+ line)))
+ '(1 2 3))
+
+ ;; Fix the dynamic linker's file name.
+ (substitute* (find-files "gcc/config"
+ "^(linux|gnu|sysv4)(64|-elf|-eabi)?\\.h$")
+ (("#define (GLIBC|GNU_USER)_DYNAMIC_LINKER([^ \t]*).*$"
+ _ gnu-user suffix)
+ (format #f "#define ~a_DYNAMIC_LINKER~a \"~a\"~%"
+ gnu-user suffix
+ (string-append libc ,(glibc-dynamic-linker)))))
+
+ ;; Tell where to find libstdc++, libc, and `?crt*.o', except
+ ;; `crt{begin,end}.o', which come with GCC.
+ (substitute* (find-files "gcc/config"
+ "^gnu-user.*\\.h$")
+ (("#define GNU_USER_TARGET_LIB_SPEC (.*)$" _ suffix)
+ ;; Help libgcc_s.so be found (see also below.) Always use
+ ;; '-lgcc_s' so that libgcc_s.so is always found by those
+ ;; programs that use 'pthread_cancel' (glibc dlopens
+ ;; libgcc_s.so when pthread_cancel support is needed, but
+ ;; having it in the application's RUNPATH isn't enough; see
+ ;; <http://sourceware.org/ml/libc-help/2013-11/msg00023.html>.)
+ ;;
+ ;; NOTE: The '-lgcc_s' added below needs to be removed in a
+ ;; later phase of %gcc-static. If you change the string
+ ;; below, make sure to update the relevant code in
+ ;; %gcc-static package as needed.
+ (format #f "#define GNU_USER_TARGET_LIB_SPEC \
+\"-L~a/lib %{!static:-rpath=~a/lib %{!static-libgcc:\
+-rpath=~a/lib \
+-rpath=~a/gcc \
+-rpath=~a/../lib \
+-rpath=~a/../gcc \
+-rpath=~a/../../lib \
+-rpath=~a/../../../lib \
+-rpath=~a/../../../../lib \
+-lgcc_s}} \" ~a"
+ libc libc
+ origin-libdir origin-libdir origin-libdir origin-libdir
+ origin-libdir origin-libdir origin-libdir
+ suffix))
+ (("#define GNU_USER_TARGET_STARTFILE_SPEC.*$" line)
+ (format #f "#define STANDARD_STARTFILE_PREFIX_1 \"~a/lib\"
+#define STANDARD_STARTFILE_PREFIX_2 \"\"
+~a"
+ libc line)))
+
+ ;; The rs6000 (a.k.a. powerpc) config in GCC does not use
+ ;; GNU_USER_* defines. Do the above for this case.
+ (substitute*
+ "gcc/config/rs6000/sysv4.h"
+ (("#define LIB_LINUX_SPEC (.*)$" _ suffix)
+ (format #f "#define LIB_LINUX_SPEC \
+\"-L~a/lib %{!static:-rpath=~a/lib %{!static-libgcc:-rpath=~a/lib -lgcc_s}} \" ~a"
+ libc libc origin-libdir suffix))
+ (("#define STARTFILE_LINUX_SPEC.*$" line)
+ (format #f "#define STANDARD_STARTFILE_PREFIX_1 \"~a/lib\"
+#define STANDARD_STARTFILE_PREFIX_2 \"\"
+~a"
+ libc line))))
+
+ ;; Don't retain a dependency on the build-time sed.
+ (substitute* "fixincludes/fixincl.x"
+ (("static char const sed_cmd_z\\[\\] =.*;")
+ "static char const sed_cmd_z[] = \"sed\";"))
+
+ ;; Aarch64 support didn't land in GCC until the 4.8 series.
+ (when (file-exists? "gcc/config/aarch64")
+ ;; Force Aarch64 libdir to be /lib and not /lib64
+ (substitute* "gcc/config/aarch64/t-aarch64-linux"
+ (("lib64") "lib")))
+
+ (when (file-exists? "libbacktrace")
+ ;; GCC 4.8+ comes with libbacktrace. By default it builds
+ ;; with -Werror, which fails with a -Wcast-qual error in glibc
+ ;; 2.21's stdlib-bsearch.h. Remove -Werror.
+ (substitute* "libbacktrace/configure"
+ (("WARN_FLAGS=(.*)-Werror" _ flags)
+ (string-append "WARN_FLAGS=" flags)))
+
+ (when (file-exists? "libsanitizer/libbacktrace")
+ ;; Same in libsanitizer's bundled copy (!) found in 4.9+.
+ (substitute* "libsanitizer/libbacktrace/Makefile.in"
+ (("-Werror")
+ ""))))
+
+ ;; Add a RUNPATH to libstdc++.so so that it finds libgcc_s.
+ ;; See <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=32354>
+ ;; and <http://bugs.gnu.org/20358>.
+ (substitute* "libstdc++-v3/src/Makefile.in"
+ (("^OPT_LDFLAGS = ")
+ ;;"OPT_LDFLAGS = -Wl,-rpath=$(libdir) "
+ (string-append "OPT_LDFLAGS ="
+ " '-Wl,-rpath=$" origin-libdir "//lib'"
+ " '-Wl,-rpath=$" origin-libdir "//gcc'"
+ " '-Wl,-rpath=$" origin-libdir "//../lib'"
+ " '-Wl,-rpath=$" origin-libdir "//../gcc' "
+ " '-Wl,-rpath=$" origin-libdir "//../lib'"
+ ;; FIXME?
+;;; /gnu/store/qxwsck61dm7h3n1pgzzs2psj06ihsslj-repro-gcc-4.7.4/libexec/gcc/x86_64-unknown-linux-gnu/4.7.4/install-tools/fixincl: error: depends on 'libgcc_s.so.1'
+ " '-Wl,-rpath=$" origin-libdir "//../../lib'"
+ " '-Wl,-rpath=$" origin-libdir "//../../../lib'"
+
+ )))
+
+ ;; Move libstdc++*-gdb.py to the "lib" output to avoid a
+ ;; circularity between "out" and "lib". (Note:
+ ;; --with-python-dir is useless because it imposes $(prefix) as
+ ;; the parent directory.)
+ (substitute* "libstdc++-v3/python/Makefile.in"
+ (("pythondir = .*$")
+ (string-append "pythondir = " libdir "/share"
+ "/gcc-$(gcc_version)/python\n")))
+
+ ;; Avoid another circularity between the outputs: this #define
+ ;; ends up in auto-host.h in the "lib" output, referring to
+ ;; "out". (This variable is used to augment cpp's search path,
+ ;; but there's nothing useful to look for here.)
+ (substitute* "gcc/config.in"
+ (("PREFIX_INCLUDE_DIR")
+ "PREFIX_INCLUDE_DIR_isnt_necessary_here")))))
+
+ (replace 'post-configure
+ (lambda _
+ ;; Don't store configure flags, to avoid retaining references to
+ ;; build-time dependencies---e.g., `--with-ppl=/gnu/store/xxx'.
+ (substitute* "Makefile"
+ (("^TOPLEVEL_CONFIGURE_ARGUMENTS=(.*)$" _ rest)
+ "TOPLEVEL_CONFIGURE_ARGUMENTS=\n"))))))))))
+
+
+(define-public repro-gcc-4.7
+ (package
+ (inherit gcc-4.7-$ORIGIN)
+ (source
+ (origin
+ (inherit (package-source gcc-4.7-$ORIGIN))
+ (patches (append ((compose origin-patches package-source) gcc-4.7)
+ (search-patches "gcc-5-reproducibility-drop-profile.patch"
+ ;;"gcc-4-compile-with-gcc-5.patch"
+ "gcc-4-build-path-prefix-map.patch")))))
+ (name "repro-gcc")
+ (version "4.7.4")
+ (arguments
+ (substitute-keyword-arguments (package-arguments gcc-4.7-$ORIGIN)
+ ((#:phases original-phases)
+ `(modify-phases ,original-phases
+ (add-before 'configure 'build-prefix-path
+ (lambda* (#:key inputs #:allow-other-keys)
+ (setenv "BUILD_PATH_PREFIX_MAP"
+ (string-append "gcc" "-" ,version "=" (getcwd)))
+ (format (current-error-port)
+ "BUILD_PATH_PREFIX_MAP=~s\n"
+ (getenv "BUILD_PATH_PREFIX_MAP"))))))))))
+
+(define-public repr2-gcc-4.7
+ (package
+ (inherit repro-gcc-4.7)
+ (name "repr2-gcc")))
+
+(define-public repro-gcc-7
+ (package
+ (inherit gcc-4.7-$ORIGIN)
+ (source
+ (origin
+ (inherit (package-source gcc-7))
+ (patches (append (search-patches "gcc-5-reproducibility-drop-profile.patch"
+ "gcc-7-build-path-prefix-map.patch")
+ ((compose origin-patches package-source) gcc-7)))))
+ (name "repro-gcc")
+ (version "7.2.0")
+ (arguments
+ (substitute-keyword-arguments (package-arguments gcc-4.7-$ORIGIN)
+ ((#:phases original-phases)
+ `(modify-phases ,original-phases
+ (add-before 'configure 'build-prefix-path
+ (lambda* (#:key inputs #:allow-other-keys)
+ (setenv "BUILD_PATH_PREFIX_MAP"
+ (string-append "gcc" "-" ,version "=" (getcwd)))
+ (format (current-error-port)
+ "BUILD_PATH_PREFIX_MAP=~s\n"
+ (getenv "BUILD_PATH_PREFIX_MAP"))))))))))
+
+(define-public repr2-gcc-7
+ (package
+ (inherit repro-gcc-7)
+ (name "repr2-gcc")))
+
+(define-public clang-gcc-7
+ (package
+ (inherit repro-gcc-7)
+ (name "clang-gcc")
+ (native-inputs `(("clang" ,clang)
+ ,@(alist-delete "gcc" (package-native-inputs gcc-7))))
+ (arguments
+ (substitute-keyword-arguments (package-arguments repro-gcc-7)
+ ((#:phases original-phases)
+ `(modify-phases ,original-phases
+ (add-before 'configure 'setenv
+ (lambda* (#:key inputs #:allow-other-keys)
+ (let ((clang (assoc-ref inputs "clang")))
+ (setenv "CC" (string-append clang "/bin/clang"))
+ (setenv "CXX "(string-append clang "/bin/clang++")))))))))))
+
+(define-public gcc-ddc-gcc+clang
+ (package
+ (name "gcc-ddc")
+ (version "4.7.4")
+ (source #f)
+ (native-inputs `(;;("clang-gcc" ,clang-gcc-7)
+ ("clang-gcc" ,repr2-gcc-4.7)
+ ("gcc" ,repro-gcc-4.7)
+
+ ("diffoscope" ,diffoscope)
+ ("acl" ,acl) ; For diffoscope
+ ("binutils" ,binutils)
+ ("coreutils" ,coreutils)
+ ("diffutils" ,diffutils)
+ ("xxd" ,xxd)))
+ (build-system trivial-build-system)
+ (arguments
+ `(#:modules ((guix build utils))
+ #:builder
+ (begin
+ (use-modules (guix build utils))
+ (let* ((diffoscope (assoc-ref %build-inputs "diffoscope"))
+ (acl (assoc-ref %build-inputs "acl"))
+ (binutils (assoc-ref %build-inputs "binutils"))
+ (coreutils (assoc-ref %build-inputs "coreutils"))
+ (diffutils (assoc-ref %build-inputs "diffutils"))
+ (xxd (assoc-ref %build-inputs "xxd"))
+ (gcc (assoc-ref %build-inputs "gcc"))
+ (gcc/bin/gcc (string-append gcc "/bin/gcc"))
+ (clang-gcc (assoc-ref %build-inputs "clang-gcc"))
+ (clang-gcc/bin/gcc (string-append clang-gcc "/bin/gcc")))
+ ;; diffoscope.exc.RequiredToolNotFound: cmp
+ ;; diffoscope.comparators.directory: 'stat' not found! Is PATH wrong?
+ ;; FileNotFoundError: [Errno 2] No such file or directory: 'readelf'
+ ;; diffoscope.comparators.directory: Unable to find 'getfacl'
+ (setenv "PATH" (string-append diffoscope "/bin:"
+
+ acl "/acl:"
+ binutils "/bin:"
+ coreutils "/bin:"
+ diffutils "/bin:"
+ xxd "/bin:"))
+ ;; ?? xxd not available in path. Falling back to Python hexlify.
+ ;; diffoscope.presenters.formats: Console is unable to print Unicode characters. Set e.g. PYTHONIOENCODING=utf-8
+ (setenv "PYTHONIOENCODING" "utf-8")
+ ;; for starters, only check the gcc binary
+ (zero? (system* "diffoscope" gcc/bin/gcc clang-gcc/bin/gcc))
+ ;;(zero? (system* "diffoscope" gcc clang-gcc))
+ ))))
+ (synopsis "test gcc+clang DDC property for gcc-7.2.0")
+ (description "gcc-dcc is a meta-package that depends on repro-gcc-7.2.0
+and on clang-gcc-7.2.0 (the same GCC built with clang). The builder checks if
+both gcc's are bit-for-bit identical and fails if they differ.")
+ (home-page "http://bootstrappable.org")
+ (license gpl3+)))
diff --git a/gnu/packages/patches/gcc-4-build-path-prefix-map.patch b/gnu/packages/patches/gcc-4-build-path-prefix-map.patch
new file mode 100644
index 000000000..738a59c8d
--- /dev/null
+++ b/gnu/packages/patches/gcc-4-build-path-prefix-map.patch
@@ -0,0 +1,780 @@
+From 1bfd15d4f07f7d76ec399b1a45bc16c404f1465a Mon Sep 17 00:00:00 2001
+From: Jan Nieuwenhuizen <janneke@gnu.org>
+Date: Mon, 6 Nov 2017 07:35:24 +0100
+Subject: [PATCH] backport build path prefix map. WIP
+
+---
+ gcc/c-family/c-common.c | 20 ++
+ gcc/c-family/c-common.h | 5 +
+ gcc/c-family/c-lex.c | 1 +
+ gcc/cp/cfns.gperf | 2 +-
+ gcc/debug.h | 1 +
+ gcc/final.c | 54 +++--
+ gcc/opts-global.c | 2 +
+ gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-1.c | 11 +
+ gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-2.c | 12 ++
+ .../gcc.dg/debug/dwarf2/build_path_prefix_map-1.c | 9 +
+ .../gcc.dg/debug/dwarf2/build_path_prefix_map-2.c | 8 +
+ include/prefix-map.h | 108 ++++++++++
+ libcpp/include/cpplib.h | 3 +
+ libcpp/init.c | 3 +
+ libcpp/internal.h | 5 +
+ libcpp/macro.c | 16 ++
+ libiberty/Makefile.in | 14 +-
+ libiberty/prefix-map.c | 226 +++++++++++++++++++++
+ 18 files changed, 467 insertions(+), 33 deletions(-)
+ create mode 100644 gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-1.c
+ create mode 100644 gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-2.c
+ create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2/build_path_prefix_map-1.c
+ create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2/build_path_prefix_map-2.c
+ create mode 100644 include/prefix-map.h
+ create mode 100644 libiberty/prefix-map.c
+
+diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
+index 82a2b8d6c..b4ca42b73 100644
+--- a/gcc/c-family/c-common.c
++++ b/gcc/c-family/c-common.c
+@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see
+
+ #include "config.h"
+ #include "system.h"
++#include "prefix-map.h"
+ #include "coretypes.h"
+ #include "tm.h"
+ #include "intl.h"
+@@ -10736,4 +10737,23 @@ build_userdef_literal (tree suffix_id, tree value, tree num_string)
+ return literal;
+ }
+
++/* Read BUILD_PATH_PREFIX_MAP from environment to have deterministic relative
++ paths to replace embedded absolute paths to get reproducible results.
++ Returns NULL if BUILD_PATH_PREFIX_MAP is badly formed. */
++
++struct prefix_map **
++cb_get_build_path_prefix_map (cpp_reader *pfile ATTRIBUTE_UNUSED)
++{
++ struct prefix_map **map = XCNEW (struct prefix_map *);
++
++ const char *arg = getenv ("BUILD_PATH_PREFIX_MAP");
++ if (!arg || prefix_map_parse (map, arg))
++ return map;
++
++ free (map);
++ error_at (input_location, "environment variable BUILD_PATH_PREFIX_MAP is "
++ "not well formed; see the GCC documentation for more details.");
++ return NULL;
++}
++
+ #include "gt-c-family-c-common.h"
+diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
+index 835b13bbc..7591bd6b0 100644
+--- a/gcc/c-family/c-common.h
++++ b/gcc/c-family/c-common.h
+@@ -1116,4 +1116,9 @@ struct GTY(()) tree_userdef_literal {
+
+ extern tree build_userdef_literal (tree suffix_id, tree value, tree num_string);
+
++/* Read BUILD_PATH_PREFIX_MAP from environment to have deterministic relative
++ paths to replace embedded absolute paths to get reproducible results.
++ Returns NULL if BUILD_PATH_PREFIX_MAP is badly formed. */
++extern struct prefix_map **cb_get_build_path_prefix_map (cpp_reader *pfile);
++
+ #endif /* ! GCC_C_COMMON_H */
+diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
+index 7e2029ce0..8cef0f2a8 100644
+--- a/gcc/c-family/c-lex.c
++++ b/gcc/c-family/c-lex.c
+@@ -84,6 +84,7 @@ init_c_lex (void)
+ cb->def_pragma = cb_def_pragma;
+ cb->valid_pch = c_common_valid_pch;
+ cb->read_pch = c_common_read_pch;
++ cb->get_build_path_prefix_map = cb_get_build_path_prefix_map;
+
+ /* Set the debug callbacks if we can use them. */
+ if ((debug_info_level == DINFO_LEVEL_VERBOSE
+diff --git a/gcc/cp/cfns.gperf b/gcc/cp/cfns.gperf
+index ba0c487a6..0f9a79ac7 100644
+--- a/gcc/cp/cfns.gperf
++++ b/gcc/cp/cfns.gperf
+@@ -26,7 +26,7 @@ __inline
+ __attribute__ ((__gnu_inline__))
+ #endif
+ #endif
+-const char * libc_name_p (const char *, unsigned int);
++inline const char * libc_name_p (const char *, unsigned int);
+ %}
+ %%
+ # The standard C library functions, for feeding to gperf; the result is used
+diff --git a/gcc/debug.h b/gcc/debug.h
+index 828ede230..1f9a69e56 100644
+--- a/gcc/debug.h
++++ b/gcc/debug.h
+@@ -187,6 +187,7 @@ extern void dwarf2out_switch_text_section (void);
+
+ const char *remap_debug_filename (const char *);
+ void add_debug_prefix_map (const char *);
++void add_debug_prefix_map_from_envvar ();
+
+ /* For -fdump-go-spec. */
+
+diff --git a/gcc/final.c b/gcc/final.c
+index 718caf154..d72dec2e5 100644
+--- a/gcc/final.c
++++ b/gcc/final.c
+@@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see
+ #include "config.h"
+ #include "system.h"
+ #include "coretypes.h"
++#include "prefix-map.h"
+ #include "tm.h"
+
+ #include "tree.h"
+@@ -1435,22 +1436,9 @@ asm_str_count (const char *templ)
+ return count;
+ }
+ \f
+-/* ??? This is probably the wrong place for these. */
+-/* Structure recording the mapping from source file and directory
+- names at compile time to those to be embedded in debug
+- information. */
+-typedef struct debug_prefix_map
+-{
+- const char *old_prefix;
+- const char *new_prefix;
+- size_t old_len;
+- size_t new_len;
+- struct debug_prefix_map *next;
+-} debug_prefix_map;
+-
+-/* Linked list of such structures. */
+-debug_prefix_map *debug_prefix_maps;
+
++/* Linked list of `struct prefix_map'. */
++static struct prefix_map *debug_prefix_maps = NULL;
+
+ /* Record a debug file prefix mapping. ARG is the argument to
+ -fdebug-prefix-map and must be of the form OLD=NEW. */
+@@ -1458,7 +1446,7 @@ debug_prefix_map *debug_prefix_maps;
+ void
+ add_debug_prefix_map (const char *arg)
+ {
+- debug_prefix_map *map;
++ struct prefix_map *map;
+ const char *p;
+
+ p = strchr (arg, '=');
+@@ -1467,7 +1455,7 @@ add_debug_prefix_map (const char *arg)
+ error ("invalid argument %qs to -fdebug-prefix-map", arg);
+ return;
+ }
+- map = XNEW (debug_prefix_map);
++ map = XNEW (struct prefix_map);
+ map->old_prefix = xstrndup (arg, p - arg);
+ map->old_len = p - arg;
+ p++;
+@@ -1477,28 +1465,32 @@ add_debug_prefix_map (const char *arg)
+ debug_prefix_maps = map;
+ }
+
++/* Add debug-prefix-maps from BUILD_PATH_PREFIX_MAP environment variable. */
++
++void
++add_debug_prefix_map_from_envvar ()
++{
++ const char *arg = getenv ("BUILD_PATH_PREFIX_MAP");
++
++ if (!arg || prefix_map_parse (&debug_prefix_maps, arg))
++ return;
++
++ error ("environment variable BUILD_PATH_PREFIX_MAP is "
++ "not well formed; see the GCC documentation for more details.");
++}
++
+ /* Perform user-specified mapping of debug filename prefixes. Return
+ the new name corresponding to FILENAME. */
+
+ const char *
+ remap_debug_filename (const char *filename)
+ {
+- debug_prefix_map *map;
+- char *s;
+- const char *name;
+- size_t name_len;
++ const char *name = prefix_map_remap_alloca (debug_prefix_maps, filename);
+
+- for (map = debug_prefix_maps; map; map = map->next)
+- if (filename_ncmp (filename, map->old_prefix, map->old_len) == 0)
+- break;
+- if (!map)
++ if (name == filename)
+ return filename;
+- name = filename + map->old_len;
+- name_len = strlen (name) + 1;
+- s = (char *) alloca (name_len + map->new_len);
+- memcpy (s, map->new_prefix, map->new_len);
+- memcpy (s + map->new_len, name, name_len);
+- return ggc_strdup (s);
++
++ return ggc_strdup (name);
+ }
+ \f
+ /* Return true if DWARF2 debug info can be emitted for DECL. */
+diff --git a/gcc/opts-global.c b/gcc/opts-global.c
+index b93d56fcd..f3c653bc1 100644
+--- a/gcc/opts-global.c
++++ b/gcc/opts-global.c
+@@ -322,6 +322,8 @@ handle_common_deferred_options (void)
+ if (flag_dump_all_passed)
+ enable_rtl_dump_file ();
+
++ add_debug_prefix_map_from_envvar ();
++
+ FOR_EACH_VEC_ELT (cl_deferred_option, vec, i, opt)
+ {
+ switch (opt->opt_index)
+diff --git a/gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-1.c b/gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-1.c
+new file mode 100644
+index 000000000..960503813
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-1.c
+@@ -0,0 +1,11 @@
++/* __FILE__ should strip BUILD_PATH_PREFIX_MAP if the latter is a prefix. */
++/* { dg-do run } */
++/* { dg-set-compiler-env-var BUILD_PATH_PREFIX_MAP "MACROTEST=$srcdir" } */
++
++int
++main ()
++{
++ if (__builtin_strcmp (__FILE__, "MACROTEST/gcc.dg/cpp/build_path_prefix_map-1.c") != 0)
++ __builtin_abort ();
++ return 0;
++}
+diff --git a/gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-2.c b/gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-2.c
+new file mode 100644
+index 000000000..4b0aacd5e
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-2.c
+@@ -0,0 +1,12 @@
++/* __FILE__ should not be relative if BUILD_PATH_PREFIX_MAP is not set, and gcc is
++ asked to compile an absolute filename as is the case with this test. */
++/* { dg-do run } */
++/* { dg-set-compiler-env-var BUILD_PATH_PREFIX_MAP } */
++
++int
++main ()
++{
++ if (__builtin_strcmp (__FILE__, "./gcc.dg/cpp/build_path_prefix_map-2.c") == 0)
++ __builtin_abort ();
++ return 0;
++}
+diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/build_path_prefix_map-1.c b/gcc/testsuite/gcc.dg/debug/dwarf2/build_path_prefix_map-1.c
+new file mode 100644
+index 000000000..af2b0ed33
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/debug/dwarf2/build_path_prefix_map-1.c
+@@ -0,0 +1,9 @@
++/* DW_AT_comp_dir should be relative if BUILD_PATH_PREFIX_MAP is a prefix of it. */
++/* { dg-do compile } */
++/* { dg-options "-gdwarf -dA" } */
++/* { dg-set-compiler-env-var BUILD_PATH_PREFIX_MAP "DWARF2TEST=[file dirname [pwd]]" } */
++/* { dg-final { scan-assembler "DW_AT_comp_dir: \"DWARF2TEST/gcc" } } */
++
++void func (void)
++{
++}
+diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/build_path_prefix_map-2.c b/gcc/testsuite/gcc.dg/debug/dwarf2/build_path_prefix_map-2.c
+new file mode 100644
+index 000000000..4c66bf521
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/debug/dwarf2/build_path_prefix_map-2.c
+@@ -0,0 +1,8 @@
++/* DW_AT_comp_dir should be absolute if BUILD_PATH_PREFIX_MAP is not set. */
++/* { dg-do compile } */
++/* { dg-options "-gdwarf -dA" } */
++/* { dg-final { scan-assembler "DW_AT_comp_dir: \"/" } } */
++
++void func (void)
++{
++}
+diff --git a/include/prefix-map.h b/include/prefix-map.h
+new file mode 100644
+index 000000000..f8edb547e
+--- /dev/null
++++ b/include/prefix-map.h
+@@ -0,0 +1,108 @@
++/* Declarations for manipulating filename prefixes.
++
++ Copyright (C) 2017 Free Software Foundation, Inc.
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2, or (at your option)
++ any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software Foundation,
++ Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
++
++#ifndef _PREFIX_MAP_H
++#define _PREFIX_MAP_H
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#ifdef HAVE_STDLIB_H
++#include <stdlib.h>
++#endif
++
++/* Linked-list of mappings from old prefixes to new prefixes. */
++
++struct prefix_map
++{
++ const char *old_prefix;
++ const char *new_prefix;
++ size_t old_len;
++ size_t new_len;
++ struct prefix_map *next;
++};
++
++
++/* Find a mapping suitable for the given OLD_NAME in the linked list MAP.\
++
++ If a mapping is found, writes a pointer to the non-matching suffix part of
++ OLD_NAME in SUFFIX, and its length in SUF_LEN.
++
++ Returns NULL if there was no suitable mapping. */
++struct prefix_map *
++prefix_map_find (struct prefix_map *map, const char *old_name,
++ const char **suffix, size_t *suf_len);
++
++/* Prepend a prefix map before a given SUFFIX.
++
++ The remapped name is written to NEW_NAME and returned as a const pointer. No
++ allocations are performed; the caller must ensure it can hold at least
++ MAP->NEW_LEN + SUF_LEN + 1 characters. */
++const char *
++prefix_map_prepend (struct prefix_map *map, char *new_name,
++ const char *suffix, size_t suf_len);
++
++/* Remap a filename.
++
++ Returns OLD_NAME unchanged if there was no remapping, otherwise returns a
++ pointer to newly-allocated memory for the remapped filename. The memory is
++ allocated by the given ALLOC function, which also determines who is
++ responsible for freeing it. */
++#define prefix_map_remap_alloc_(map_head, old_name, alloc) \
++ __extension__ \
++ ({ \
++ const char *__suffix; \
++ size_t __suf_len; \
++ struct prefix_map *__map; \
++ (__map = prefix_map_find ((map_head), (old_name), &__suffix, &__suf_len)) \
++ ? prefix_map_prepend (__map, \
++ (char *) alloc (__map->new_len + __suf_len + 1), \
++ __suffix, __suf_len) \
++ : (old_name); \
++ })
++
++/* Remap a filename.
++
++ Returns OLD_NAME unchanged if there was no remapping, otherwise returns a
++ stack-allocated pointer to the newly-remapped filename. */
++#define prefix_map_remap_alloca(map_head, old_name) \
++ prefix_map_remap_alloc_ (map_head, old_name, alloca)
++
++
++/* Parse prefix-maps according to the BUILD_PATH_PREFIX_MAP standard.
++
++ The input string value is of the form
++
++ dst[0]=src[0]:dst[1]=src[1]...
++
++ Every dst[i] and src[i] has had "%", "=" and ":" characters replaced with
++ "%#", "%+", and "%." respectively; this function reverses this replacement.
++
++ Rightmost entries are stored at the head of the parsed structure.
++
++ Returns 0 on failure and 1 on success. */
++int
++prefix_map_parse (struct prefix_map **map_head, const char *arg);
++
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* _PREFIX_MAP_H */
+diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
+index bf59d0162..082770d04 100644
+--- a/libcpp/include/cpplib.h
++++ b/libcpp/include/cpplib.h
+@@ -541,6 +541,9 @@ struct cpp_callbacks
+
+ /* Callback that can change a user builtin into normal macro. */
+ bool (*user_builtin_macro) (cpp_reader *, cpp_hashnode *);
++
++ /* Callback to parse BUILD_PATH_PREFIX_MAP from environment. */
++ struct prefix_map **(*get_build_path_prefix_map) (cpp_reader *);
+ };
+
+ #ifdef VMS
+diff --git a/libcpp/init.c b/libcpp/init.c
+index 5fa82ca9c..270d42b95 100644
+--- a/libcpp/init.c
++++ b/libcpp/init.c
+@@ -231,6 +231,9 @@ cpp_create_reader (enum c_lang lang, hash_table *table,
+ /* Do not force token locations by default. */
+ pfile->forced_token_location_p = NULL;
+
++ /* Initialize build_path_prefix_map to NULL (not yet set). */
++ pfile->build_path_prefix_map = NULL;
++
+ /* The expression parser stack. */
+ _cpp_expand_op_stack (pfile);
+
+diff --git a/libcpp/internal.h b/libcpp/internal.h
+index 5b3731bba..5b09bf1a4 100644
+--- a/libcpp/internal.h
++++ b/libcpp/internal.h
+@@ -485,6 +485,11 @@ struct cpp_reader
+ const unsigned char *date;
+ const unsigned char *time;
+
++ /* Externally set prefix-map to transform absolute paths, useful for
++ reproducibility. It should be initialized to NULL (not yet set or
++ disabled) or to a `struct prefix_map` double pointer to enable it. */
++ struct prefix_map **build_path_prefix_map;
++
+ /* EOF token, and a token forcing paste avoidance. */
+ cpp_token avoid_paste;
+ cpp_token eof;
+diff --git a/libcpp/macro.c b/libcpp/macro.c
+index 54de3e3fc..6cdd1e5d3 100644
+--- a/libcpp/macro.c
++++ b/libcpp/macro.c
+@@ -28,6 +28,7 @@ along with this program; see the file COPYING3. If not see
+ #include "system.h"
+ #include "cpplib.h"
+ #include "internal.h"
++#include "prefix-map.h"
+
+ typedef struct macro_arg macro_arg;
+ /* This structure represents the tokens of a macro argument. These
+@@ -271,7 +272,17 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node)
+ unsigned int len;
+ const char *name;
+ uchar *buf;
++ struct prefix_map **map = pfile->build_path_prefix_map;
+
++ /* Set a prefix-map for __FILE__ if BUILD_PATH_PREFIX_MAP is defined. */
++ if (map == NULL && pfile->cb.get_build_path_prefix_map != NULL)
++ {
++ map = pfile->cb.get_build_path_prefix_map (pfile);
++ if (map == NULL)
++ abort ();
++ pfile->build_path_prefix_map = map;
++ }
++
+ if (node->value.builtin == BT_FILE)
+ name = linemap_get_expansion_filename (pfile->line_table,
+ pfile->line_table->highest_line);
+@@ -281,6 +292,11 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node)
+ if (!name)
+ abort ();
+ }
++
++ /* Apply the prefix-map for deterministic path output. */
++ if (map != NULL)
++ name = prefix_map_remap_alloca (*map, name);
++
+ len = strlen (name);
+ buf = _cpp_unaligned_alloc (pfile, len * 2 + 3);
+ result = buf;
+diff --git a/libiberty/Makefile.in b/libiberty/Makefile.in
+index 5280bc158..bc098496a 100644
+--- a/libiberty/Makefile.in
++++ b/libiberty/Makefile.in
+@@ -143,6 +143,7 @@ CFILES = alloca.c argv.c asprintf.c atexit.c \
+ pex-common.c pex-djgpp.c pex-msdos.c pex-one.c \
+ pex-unix.c pex-win32.c \
+ physmem.c putenv.c \
++ prefix-map.c \
+ random.c regex.c rename.c rindex.c \
+ safe-ctype.c setenv.c setproctitle.c sha1.c sigsetmask.c \
+ simple-object.c simple-object-coff.c simple-object-elf.c \
+@@ -179,6 +180,7 @@ REQUIRED_OFILES = \
+ ./partition.$(objext) ./pexecute.$(objext) ./physmem.$(objext) \
+ ./pex-common.$(objext) ./pex-one.$(objext) \
+ ./@pexecute@.$(objext) \
++ ./prefix-map.$(objext) \
+ ./safe-ctype.$(objext) \
+ ./simple-object.$(objext) ./simple-object-coff.$(objext) \
+ ./simple-object-elf.$(objext) ./simple-object-mach-o.$(objext) \
+@@ -887,7 +889,8 @@ $(CONFIGURED_OFILES): stamp-picdir
+ $(COMPILE.c) $(srcdir)/pex-one.c $(OUTPUT_OPTION)
+
+ ./pex-unix.$(objext): $(srcdir)/pex-unix.c config.h $(INCDIR)/ansidecl.h \
+- $(INCDIR)/libiberty.h $(srcdir)/pex-common.h
++ $(INCDIR)/libiberty.h \
++ $(srcdir)/pex-common.h
+ if [ x"$(PICFLAG)" != x ]; then \
+ $(COMPILE.c) $(PICFLAG) $(srcdir)/pex-unix.c -o pic/$@; \
+ else true; fi
+@@ -914,6 +917,15 @@ $(CONFIGURED_OFILES): stamp-picdir
+ else true; fi
+ $(COMPILE.c) $(srcdir)/physmem.c $(OUTPUT_OPTION)
+
++./prefix-map.$(objext): $(srcdir)/prefix-map.c config.h $(INCDIR)/prefix-map.h
++ if [ x"$(PICFLAG)" != x ]; then \
++ $(COMPILE.c) $(PICFLAG) $(srcdir)/prefix-map.c -o pic/$@; \
++ else true; fi
++ if [ x"$(NOASANFLAG)" != x ]; then \
++ $(COMPILE.c) $(PICFLAG) $(NOASANFLAG) $(srcdir)/prefix-map.c -o noasan/$@; \
++ else true; fi
++ $(COMPILE.c) $(srcdir)/prefix-map.c $(OUTPUT_OPTION)
++
+ ./putenv.$(objext): $(srcdir)/putenv.c config.h $(INCDIR)/ansidecl.h
+ if [ x"$(PICFLAG)" != x ]; then \
+ $(COMPILE.c) $(PICFLAG) $(srcdir)/putenv.c -o pic/$@; \
+diff --git a/libiberty/prefix-map.c b/libiberty/prefix-map.c
+new file mode 100644
+index 000000000..ecb408856
+--- /dev/null
++++ b/libiberty/prefix-map.c
+@@ -0,0 +1,226 @@
++/* Definitions for manipulating filename prefixes.
++
++ Copyright (C) 2017 Free Software Foundation, Inc.
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2, or (at your option)
++ any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software Foundation,
++ Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++
++#ifdef HAVE_STRING_H
++#include <string.h>
++#endif
++
++#ifdef HAVE_STDLIB_H
++#include <stdlib.h>
++#endif
++
++#include "filenames.h"
++#include "libiberty.h"
++#include "prefix-map.h"
++
++
++/* Add a new mapping.
++
++ The input strings are duplicated and a new prefix_map struct is allocated.
++ Ownership of the duplicates, as well as the new prefix_map, is the same as
++ the ownership of the old struct.
++
++ Returns 0 on failure and 1 on success. */
++int
++prefix_map_push (struct prefix_map **map_head,
++ const char *new_prefix, const char *old_prefix)
++{
++ struct prefix_map *map = XNEW (struct prefix_map);
++ if (!map)
++ goto rewind_0;
++
++ map->old_prefix = xstrdup (old_prefix);
++ if (!map->old_prefix)
++ goto rewind_1;
++ map->old_len = strlen (old_prefix);
++
++ map->new_prefix = xstrdup (new_prefix);
++ if (!map->new_prefix)
++ goto rewind_2;
++ map->new_len = strlen (new_prefix);
++
++ map->next = *map_head;
++ *map_head = map;
++ return 1;
++
++rewind_2:
++ free ((void *) map->old_prefix);
++rewind_1:
++ free (map);
++rewind_0:
++ return 0;
++}
++
++/* Rewind a prefix map.
++
++ Everything up to the given OLD_HEAD is freed. */
++void
++prefix_map_pop_until (struct prefix_map **map_head, struct prefix_map *old_head)
++{
++ struct prefix_map *map;
++ struct prefix_map *next;
++
++ for (map = *map_head; map != old_head; map = next)
++ {
++ free ((void *) map->old_prefix);
++ free ((void *) map->new_prefix);
++ next = map->next;
++ free (map);
++ }
++
++ *map_head = map;
++}
++
++
++/* Find a mapping suitable for the given OLD_NAME in the linked list MAP.\
++
++ If a mapping is found, writes a pointer to the non-matching suffix part of
++ OLD_NAME in SUFFIX, and its length in SUF_LEN.
++
++ Returns NULL if there was no suitable mapping. */
++struct prefix_map *
++prefix_map_find (struct prefix_map *map, const char *old_name,
++ const char **suffix, size_t *suf_len)
++{
++ size_t len;
++
++ for (; map; map = map->next)
++ {
++ len = map->old_len;
++ /* Ignore trailing path separators at the end of old_prefix */
++ while (len > 0 && IS_DIR_SEPARATOR (map->old_prefix[len-1])) len--;
++ /* Check if old_name matches old_prefix at a path component boundary */
++ if (! filename_ncmp (old_name, map->old_prefix, len)
++ && (IS_DIR_SEPARATOR (old_name[len])
++ || old_name[len] == '\0'))
++ {
++ *suf_len = strlen (*suffix = old_name + len);
++ break;
++ }
++ }
++
++ return map;
++}
++
++/* Prepend a prefix map before a given SUFFIX.
++
++ The remapped name is written to NEW_NAME and returned as a const pointer. No
++ allocations are performed; the caller must ensure it can hold at least
++ MAP->NEW_LEN + SUF_LEN + 1 characters. */
++const char *
++prefix_map_prepend (struct prefix_map *map, char *new_name,
++ const char *suffix, size_t suf_len)
++{
++ memcpy (new_name, map->new_prefix, map->new_len);
++ memcpy (new_name + map->new_len, suffix, suf_len + 1);
++ return new_name;
++}
++
++
++/* Parse a single part of a single prefix-map pair.
++
++ Returns 0 on failure and 1 on success. */
++int
++prefix_map_parse_unquote (char *src)
++{
++ char *dest;
++ for (dest = src; 0 != (*dest = *src); ++dest, ++src)
++ switch (*src)
++ {
++ case ':':
++ case '=':
++ return 0; // should have been escaped
++ case '%':
++ switch (*(src + 1))
++ {
++ case '.':
++ *dest = ':';
++ goto unquoted;
++ case '+':
++ *dest = '=';
++ unquoted:
++ case '#':
++ ++src;
++ break;
++ default:
++ return 0; // invalid
++ }
++ }
++ return 1;
++}
++
++/* Parse a single prefix-map.
++
++ Returns 0 on failure and 1 on success. */
++int
++prefix_map_parse1 (struct prefix_map **map_head, char *arg)
++{
++ char *p;
++ p = strchr (arg, '=');
++ if (!p)
++ return 0;
++ *p = '\0';
++ if (!prefix_map_parse_unquote (arg))
++ return 0;
++ p++;
++ if (!prefix_map_parse_unquote (p))
++ return 0;
++
++ return prefix_map_push (map_head, arg, p);
++}
++
++/* Parse a prefix-map according to the BUILD_PATH_PREFIX_MAP standard.
++
++ The input string value is of the form
++
++ dst[0]=src[0]:dst[1]=src[1]...
++
++ Every dst[i] and src[i] has had "%", "=" and ":" characters replaced with
++ "%#", "%+", and "%." respectively; this function reverses this replacement.
++
++ Rightmost entries are stored at the head of the parsed structure.
++
++ Returns 0 on failure and 1 on success. */
++int
++prefix_map_parse (struct prefix_map **map_head, const char *arg)
++{
++ struct prefix_map *old_head = *map_head;
++
++ size_t len = strlen (arg);
++ char *copy = (char *) alloca (len + 1);
++ memcpy (copy, arg, len + 1);
++
++ const char *sep = ":";
++ char *end, *tok = strtok_r (copy, sep, &end);
++ while (tok != NULL)
++ {
++ if (!prefix_map_parse1 (map_head, tok))
++ {
++ prefix_map_pop_until (map_head, old_head);
++ return 0;
++ }
++
++ tok = strtok_r (NULL, sep, &end);
++ }
++
++ return 1;
++}
+--
+Jan Nieuwenhuizen <janneke@gnu.org> | GNU LilyPond http://lilypond.org
+Freelance IT http://JoyofSource.com | Avatar® http://AvatarAcademy.com
+
diff --git a/gnu/packages/patches/gcc-4-cfns-fix-mismatch-in-gnu_inline-attributes.patch b/gnu/packages/patches/gcc-4-cfns-fix-mismatch-in-gnu_inline-attributes.patch
new file mode 100644
index 000000000..861cd4857
--- /dev/null
+++ b/gnu/packages/patches/gcc-4-cfns-fix-mismatch-in-gnu_inline-attributes.patch
@@ -0,0 +1,65 @@
+Taken from https://gcc.gnu.org/cgi-bin/get-raw-msg?listname=gcc-patches&date=2016-01&msgid=1451802493-17406-1-git-send-email-vapier%40gentoo.org
+
+Since the 3.0.3 release of gperf (made in May 2007), the generated func
+has had the gnu_inline attribute applied to it. The gcc source however
+has not been updated to include that which has lead to a mismatch.
+
+In practice, this hasn't been an issue for two reasons:
+(1) Before gcc-5, the default standard was (gnu) C89, and gcc does not
+warn or throw an error in this mode.
+(2) Starting with gcc-4.8, the compiler driver used to build gcc was
+changed to C++, and g++ does not warn or throw an error in this mode.
+
+This error does show up though when using gcc-5 to build gcc-4.7 or
+older as then the default is (gnu) C11 and the C compiler driver is
+used. That failure looks like:
+In file included from .../gcc-4.7.4/gcc/cp/except.c:990:0:
+cfns.gperf: At top level:
+cfns.gperf:101:1: error: 'gnu_inline' attribute present on 'libc_name_p'
+cfns.gperf:26:14: error: but not here
+
+Whether the compiler should always emit this error regardless of the
+active standard or compiler driver is debatable (I think it should be
+consistent -- either always do it or never do it).
+
+2015-08-06 Mike Frysinger <vapier@gentoo.org>
+
+ * cfns.gperf [__GNUC__, __GNUC_STDC_INLINE__]: Apply the
+ __gnu_inline__ attribute.
+ * cfns.h: Regenerated.
+---
+ gcc/cp/cfns.gperf | 3 +++
+ gcc/cp/cfns.h | 3 +++
+ 2 files changed, 6 insertions(+)
+
+diff --git a/gcc/cp/cfns.gperf b/gcc/cp/cfns.gperf
+index 68acd3d..953262f 100644
+--- a/gcc/cp/cfns.gperf
++++ b/gcc/cp/cfns.gperf
+@@ -22,6 +22,9 @@ __inline
+ static unsigned int hash (const char *, unsigned int);
+ #ifdef __GNUC__
+ __inline
++#ifdef __GNUC_STDC_INLINE__
++__attribute__ ((__gnu_inline__))
++#endif
+ #endif
+ const char * libc_name_p (const char *, unsigned int);
+ %}
+diff --git a/gcc/cp/cfns.h b/gcc/cp/cfns.h
+index 1c6665d..6d00c0e 100644
+--- a/gcc/cp/cfns.h
++++ b/gcc/cp/cfns.h
+@@ -53,6 +53,9 @@ __inline
+ static unsigned int hash (const char *, unsigned int);
+ #ifdef __GNUC__
+ __inline
++#ifdef __GNUC_STDC_INLINE__
++__attribute__ ((__gnu_inline__))
++#endif
+ #endif
+ const char * libc_name_p (const char *, unsigned int);
+ /* maximum key range = 391, duplicates = 0 */
+--
+2.6.2
+
diff --git a/gnu/packages/patches/gcc-5-reproducibility-drop-profile.patch b/gnu/packages/patches/gcc-5-reproducibility-drop-profile.patch
new file mode 100644
index 000000000..a3974ad8d
--- /dev/null
+++ b/gnu/packages/patches/gcc-5-reproducibility-drop-profile.patch
@@ -0,0 +1,36 @@
+Courtesy "Bernhard M. Wiedemann" <bernhardout@lsmod.de>
+
+Removing -fprofile-generate, -fprofile-use makes gcc build bit-for-bit reproducible.
+
+diff -purN gcc-5.4.0.orig/Makefile.in gcc-5.4.0/Makefile.in
+--- gcc-5.4.0.orig/Makefile.in 1970-01-01 01:00:00.000000000 +0100
++++ gcc-5.4.0/Makefile.in 2017-11-03 15:34:56.415033525 +0100
+@@ -502,10 +502,10 @@ STAGE1_CONFIGURE_FLAGS = --disable-inter
+ --disable-coverage --enable-languages="$(STAGE1_LANGUAGES)" \
+ --disable-build-format-warnings
+
+-STAGEprofile_CFLAGS = $(STAGE2_CFLAGS) -fprofile-generate
++STAGEprofile_CFLAGS = $(STAGE2_CFLAGS)
+ STAGEprofile_TFLAGS = $(STAGE2_TFLAGS)
+
+-STAGEfeedback_CFLAGS = $(STAGE3_CFLAGS) -fprofile-use
++STAGEfeedback_CFLAGS = $(STAGE3_CFLAGS)
+ STAGEfeedback_TFLAGS = $(STAGE3_TFLAGS)
+
+ do-compare = @do_compare@
+diff -purN gcc-5.4.0.orig/Makefile.tpl gcc-5.4.0/Makefile.tpl
+--- gcc-5.4.0.orig/Makefile.tpl 1970-01-01 01:00:00.000000000 +0100
++++ gcc-5.4.0/Makefile.tpl 2017-11-03 15:34:27.146557384 +0100
+@@ -455,10 +455,10 @@ STAGE1_CONFIGURE_FLAGS = --disable-inter
+ --disable-coverage --enable-languages="$(STAGE1_LANGUAGES)" \
+ --disable-build-format-warnings
+
+-STAGEprofile_CFLAGS = $(STAGE2_CFLAGS) -fprofile-generate
++STAGEprofile_CFLAGS = $(STAGE2_CFLAGS)
+ STAGEprofile_TFLAGS = $(STAGE2_TFLAGS)
+
+-STAGEfeedback_CFLAGS = $(STAGE3_CFLAGS) -fprofile-use
++STAGEfeedback_CFLAGS = $(STAGE3_CFLAGS)
+ STAGEfeedback_TFLAGS = $(STAGE3_TFLAGS)
+
+ do-compare = @do_compare@
diff --git a/gnu/packages/patches/gcc-7-build-path-prefix-map.patch b/gnu/packages/patches/gcc-7-build-path-prefix-map.patch
new file mode 100644
index 000000000..098cbbd41
--- /dev/null
+++ b/gnu/packages/patches/gcc-7-build-path-prefix-map.patch
@@ -0,0 +1,934 @@
+This is the combined BUILD_PATH_PREFIX_MAP patch set. Only using this here as
+a proof of concept to reach bit-by-bit reproducibility for diverse double
+compilation. It will be reworked to meet the needs of GNU GCC upstream.
+
+Subject: [PATCH 1/3] Use BUILD_PATH_PREFIX_MAP envvar for debug-prefix-map
+
+Define the BUILD_PATH_PREFIX_MAP environment variable, and treat it as implicit
+-fdebug-prefix-map CLI options specified before any explicit such options.
+
+Much of the generic code for applying and parsing prefix-maps is implemented in
+libiberty instead of the dwarf2 parts of the code, in order to make subsequent
+patches unrelated to debuginfo easier.
+
+Acknowledgements
+----------------
+
+Daniel Kahn Gillmor who wrote the patch for r231835, which saved me a lot of
+time figuring out what to edit.
+
+HW42 for discussion on the details of the proposal, and for suggesting that we
+retain the ability to map the prefix to something other than ".".
+
+Other contributors to the BUILD_PATH_PREFIX_MAP specification, see
+https://reproducible-builds.org/specs/build-path-prefix-map/
+
+ChangeLogs
+----------
+
+include/ChangeLog:
+
+2017-03-27 Ximin Luo <infinity0@pwned.gg>
+
+ * prefix-map.h: New file implementing the BUILD_PATH_PREFIX_MAP
+ specification; includes code from /gcc/final.c and code adapted from
+ examples attached to the specification.
+
+libiberty/ChangeLog:
+
+2017-03-27 Ximin Luo <infinity0@pwned.gg>
+
+ * prefix-map.c: New file implementing the BUILD_PATH_PREFIX_MAP
+ specification; includes code from /gcc/final.c and code adapted from
+ examples attached to the specification.
+ * Makefile.in: Update for new files.
+
+gcc/ChangeLog:
+
+2017-03-27 Ximin Luo <infinity0@pwned.gg>
+
+ * debug.h: Declare add_debug_prefix_map_from_envvar.
+ * final.c: Define add_debug_prefix_map_from_envvar, and refactor
+ prefix-map utilities to use equivalent code from libiberty instead.
+ * opts-global.c: (handle_common_deferred_options): Call
+ add_debug_prefix_map_from_envvar before processing options.
+
+gcc/testsuite/ChangeLog:
+
+2017-03-27 Ximin Luo <infinity0@pwned.gg>
+
+ * gcc.dg/debug/dwarf2/build_path_prefix_map-1.c: New test.
+ * gcc.dg/debug/dwarf2/build_path_prefix_map-2.c: New test.
+
+Index: b/include/prefix-map.h
+===================================================================
+--- /dev/null
++++ b/include/prefix-map.h
+@@ -0,0 +1,108 @@
++/* Declarations for manipulating filename prefixes.
++
++ Copyright (C) 2017 Free Software Foundation, Inc.
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2, or (at your option)
++ any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software Foundation,
++ Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
++
++#ifndef _PREFIX_MAP_H
++#define _PREFIX_MAP_H
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#ifdef HAVE_STDLIB_H
++#include <stdlib.h>
++#endif
++
++/* Linked-list of mappings from old prefixes to new prefixes. */
++
++struct prefix_map
++{
++ const char *old_prefix;
++ const char *new_prefix;
++ size_t old_len;
++ size_t new_len;
++ struct prefix_map *next;
++};
++
++
++/* Find a mapping suitable for the given OLD_NAME in the linked list MAP.\
++
++ If a mapping is found, writes a pointer to the non-matching suffix part of
++ OLD_NAME in SUFFIX, and its length in SUF_LEN.
++
++ Returns NULL if there was no suitable mapping. */
++struct prefix_map *
++prefix_map_find (struct prefix_map *map, const char *old_name,
++ const char **suffix, size_t *suf_len);
++
++/* Prepend a prefix map before a given SUFFIX.
++
++ The remapped name is written to NEW_NAME and returned as a const pointer. No
++ allocations are performed; the caller must ensure it can hold at least
++ MAP->NEW_LEN + SUF_LEN + 1 characters. */
++const char *
++prefix_map_prepend (struct prefix_map *map, char *new_name,
++ const char *suffix, size_t suf_len);
++
++/* Remap a filename.
++
++ Returns OLD_NAME unchanged if there was no remapping, otherwise returns a
++ pointer to newly-allocated memory for the remapped filename. The memory is
++ allocated by the given ALLOC function, which also determines who is
++ responsible for freeing it. */
++#define prefix_map_remap_alloc_(map_head, old_name, alloc) \
++ __extension__ \
++ ({ \
++ const char *__suffix; \
++ size_t __suf_len; \
++ struct prefix_map *__map; \
++ (__map = prefix_map_find ((map_head), (old_name), &__suffix, &__suf_len)) \
++ ? prefix_map_prepend (__map, \
++ (char *) alloc (__map->new_len + __suf_len + 1), \
++ __suffix, __suf_len) \
++ : (old_name); \
++ })
++
++/* Remap a filename.
++
++ Returns OLD_NAME unchanged if there was no remapping, otherwise returns a
++ stack-allocated pointer to the newly-remapped filename. */
++#define prefix_map_remap_alloca(map_head, old_name) \
++ prefix_map_remap_alloc_ (map_head, old_name, alloca)
++
++
++/* Parse prefix-maps according to the BUILD_PATH_PREFIX_MAP standard.
++
++ The input string value is of the form
++
++ dst[0]=src[0]:dst[1]=src[1]...
++
++ Every dst[i] and src[i] has had "%", "=" and ":" characters replaced with
++ "%#", "%+", and "%." respectively; this function reverses this replacement.
++
++ Rightmost entries are stored at the head of the parsed structure.
++
++ Returns 0 on failure and 1 on success. */
++int
++prefix_map_parse (struct prefix_map **map_head, const char *arg);
++
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* _PREFIX_MAP_H */
+Index: b/libiberty/Makefile.in
+===================================================================
+--- a/libiberty/Makefile.in
++++ b/libiberty/Makefile.in
+@@ -143,6 +143,7 @@ CFILES = alloca.c argv.c asprintf.c atex
+ pex-common.c pex-djgpp.c pex-msdos.c pex-one.c \
+ pex-unix.c pex-win32.c \
+ physmem.c putenv.c \
++ prefix-map.c \
+ random.c regex.c rename.c rindex.c \
+ rust-demangle.c \
+ safe-ctype.c setenv.c setproctitle.c sha1.c sigsetmask.c \
+@@ -182,6 +183,7 @@ REQUIRED_OFILES = \
+ ./partition.$(objext) ./pexecute.$(objext) ./physmem.$(objext) \
+ ./pex-common.$(objext) ./pex-one.$(objext) \
+ ./@pexecute@.$(objext) ./vprintf-support.$(objext) \
++ ./prefix-map.$(objext) \
+ ./rust-demangle.$(objext) \
+ ./safe-ctype.$(objext) \
+ ./simple-object.$(objext) ./simple-object-coff.$(objext) \
+@@ -757,7 +759,7 @@ $(CONFIGURED_OFILES): stamp-picdir stamp
+ $(COMPILE.c) $(srcdir)/fibheap.c $(OUTPUT_OPTION)
+
+ ./filename_cmp.$(objext): $(srcdir)/filename_cmp.c config.h $(INCDIR)/ansidecl.h \
+- $(INCDIR)/filenames.h $(INCDIR)/hashtab.h \
++ $(INCDIR)/filenames.h $(INCDIR)/hashtab.h $(INCDIR)/libiberty.h \
+ $(INCDIR)/safe-ctype.h
+ if [ x"$(PICFLAG)" != x ]; then \
+ $(COMPILE.c) $(PICFLAG) $(srcdir)/filename_cmp.c -o pic/$@; \
+@@ -1104,7 +1106,8 @@ $(CONFIGURED_OFILES): stamp-picdir stamp
+ $(COMPILE.c) $(srcdir)/pex-one.c $(OUTPUT_OPTION)
+
+ ./pex-unix.$(objext): $(srcdir)/pex-unix.c config.h $(INCDIR)/ansidecl.h \
+- $(INCDIR)/libiberty.h $(srcdir)/pex-common.h
++ $(INCDIR)/environ.h $(INCDIR)/libiberty.h \
++ $(srcdir)/pex-common.h
+ if [ x"$(PICFLAG)" != x ]; then \
+ $(COMPILE.c) $(PICFLAG) $(srcdir)/pex-unix.c -o pic/$@; \
+ else true; fi
+@@ -1143,6 +1146,15 @@ $(CONFIGURED_OFILES): stamp-picdir stamp
+ else true; fi
+ $(COMPILE.c) $(srcdir)/physmem.c $(OUTPUT_OPTION)
+
++./prefix-map.$(objext): $(srcdir)/prefix-map.c config.h $(INCDIR)/prefix-map.h
++ if [ x"$(PICFLAG)" != x ]; then \
++ $(COMPILE.c) $(PICFLAG) $(srcdir)/prefix-map.c -o pic/$@; \
++ else true; fi
++ if [ x"$(NOASANFLAG)" != x ]; then \
++ $(COMPILE.c) $(PICFLAG) $(NOASANFLAG) $(srcdir)/prefix-map.c -o noasan/$@; \
++ else true; fi
++ $(COMPILE.c) $(srcdir)/prefix-map.c $(OUTPUT_OPTION)
++
+ ./putenv.$(objext): $(srcdir)/putenv.c config.h $(INCDIR)/ansidecl.h
+ if [ x"$(PICFLAG)" != x ]; then \
+ $(COMPILE.c) $(PICFLAG) $(srcdir)/putenv.c -o pic/$@; \
+@@ -1210,7 +1222,8 @@ $(CONFIGURED_OFILES): stamp-picdir stamp
+ else true; fi
+ $(COMPILE.c) $(srcdir)/safe-ctype.c $(OUTPUT_OPTION)
+
+-./setenv.$(objext): $(srcdir)/setenv.c config.h $(INCDIR)/ansidecl.h
++./setenv.$(objext): $(srcdir)/setenv.c config.h $(INCDIR)/ansidecl.h \
++ $(INCDIR)/environ.h
+ if [ x"$(PICFLAG)" != x ]; then \
+ $(COMPILE.c) $(PICFLAG) $(srcdir)/setenv.c -o pic/$@; \
+ else true; fi
+@@ -1661,7 +1674,7 @@ $(CONFIGURED_OFILES): stamp-picdir stamp
+ $(COMPILE.c) $(srcdir)/xexit.c $(OUTPUT_OPTION)
+
+ ./xmalloc.$(objext): $(srcdir)/xmalloc.c config.h $(INCDIR)/ansidecl.h \
+- $(INCDIR)/libiberty.h
++ $(INCDIR)/environ.h $(INCDIR)/libiberty.h
+ if [ x"$(PICFLAG)" != x ]; then \
+ $(COMPILE.c) $(PICFLAG) $(srcdir)/xmalloc.c -o pic/$@; \
+ else true; fi
+@@ -1719,3 +1732,4 @@ $(CONFIGURED_OFILES): stamp-picdir stamp
+ $(COMPILE.c) $(PICFLAG) $(NOASANFLAG) $(srcdir)/xvasprintf.c -o noasan/$@; \
+ else true; fi
+ $(COMPILE.c) $(srcdir)/xvasprintf.c $(OUTPUT_OPTION)
++
+Index: b/libiberty/prefix-map.c
+===================================================================
+--- /dev/null
++++ b/libiberty/prefix-map.c
+@@ -0,0 +1,215 @@
++/* Definitions for manipulating filename prefixes.
++
++ Copyright (C) 2017 Free Software Foundation, Inc.
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2, or (at your option)
++ any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software Foundation,
++ Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++
++#ifdef HAVE_STRING_H
++#include <string.h>
++#endif
++
++#ifdef HAVE_STDLIB_H
++#include <stdlib.h>
++#endif
++
++#include "filenames.h"
++#include "libiberty.h"
++#include "prefix-map.h"
++
++
++/* Add a new mapping.
++
++ The input strings are duplicated and a new prefix_map struct is allocated.
++ Ownership of the duplicates, as well as the new prefix_map, is the same as
++ the ownership of the old struct.
++
++ Returns 0 on failure and 1 on success. */
++int
++prefix_map_push (struct prefix_map **map_head,
++ const char *new_prefix, const char *old_prefix)
++{
++ struct prefix_map *map = XNEW (struct prefix_map);
++ if (!map)
++ goto rewind_0;
++
++ map->old_prefix = xstrdup (old_prefix);
++ if (!map->old_prefix)
++ goto rewind_1;
++ map->old_len = strlen (old_prefix);
++
++ map->new_prefix = xstrdup (new_prefix);
++ if (!map->new_prefix)
++ goto rewind_2;
++ map->new_len = strlen (new_prefix);
++
++ map->next = *map_head;
++ *map_head = map;
++ return 1;
++
++rewind_2:
++ free ((void *) map->old_prefix);
++rewind_1:
++ free (map);
++rewind_0:
++ return 0;
++}
++
++/* Rewind a prefix map.
++
++ Everything up to the given OLD_HEAD is freed. */
++void
++prefix_map_pop_until (struct prefix_map **map_head, struct prefix_map *old_head)
++{
++ struct prefix_map *map;
++ struct prefix_map *next;
++
++ for (map = *map_head; map != old_head; map = next)
++ {
++ free ((void *) map->old_prefix);
++ free ((void *) map->new_prefix);
++ next = map->next;
++ free (map);
++ }
++
++ *map_head = map;
++}
++
++
++/* Find a mapping suitable for the given OLD_NAME in the linked list MAP.\
++
++ If a mapping is found, writes a pointer to the non-matching suffix part of
++ OLD_NAME in SUFFIX, and its length in SUF_LEN.
++
++ Returns NULL if there was no suitable mapping. */
++struct prefix_map *
++prefix_map_find (struct prefix_map *map, const char *old_name,
++ const char **suffix, size_t *suf_len)
++{
++ for (; map; map = map->next)
++ if (filename_ncmp (old_name, map->old_prefix, map->old_len) == 0)
++ {
++ *suf_len = strlen (*suffix = old_name + map->old_len);
++ break;
++ }
++
++ return map;
++}
++
++/* Prepend a prefix map before a given SUFFIX.
++
++ The remapped name is written to NEW_NAME and returned as a const pointer. No
++ allocations are performed; the caller must ensure it can hold at least
++ MAP->NEW_LEN + SUF_LEN + 1 characters. */
++const char *
++prefix_map_prepend (struct prefix_map *map, char *new_name,
++ const char *suffix, size_t suf_len)
++{
++ memcpy (new_name, map->new_prefix, map->new_len);
++ memcpy (new_name + map->new_len, suffix, suf_len + 1);
++ return new_name;
++}
++
++
++/* Parse a single part of a single prefix-map pair.
++
++ Returns 0 on failure and 1 on success. */
++int
++prefix_map_parse_unquote (char *src)
++{
++ for (char *dest = src; 0 != (*dest = *src); ++dest, ++src)
++ switch (*src)
++ {
++ case ':':
++ case '=':
++ return 0; // should have been escaped
++ case '%':
++ switch (*(src + 1))
++ {
++ case '.':
++ *dest = ':';
++ goto unquoted;
++ case '+':
++ *dest = '=';
++ unquoted:
++ case '#':
++ ++src;
++ break;
++ default:
++ return 0; // invalid
++ }
++ }
++ return 1;
++}
++
++/* Parse a single prefix-map.
++
++ Returns 0 on failure and 1 on success. */
++int
++prefix_map_parse1 (struct prefix_map **map_head, char *arg)
++{
++ char *p;
++ p = strchr (arg, '=');
++ if (!p)
++ return 0;
++ *p = '\0';
++ if (!prefix_map_parse_unquote (arg))
++ return 0;
++ p++;
++ if (!prefix_map_parse_unquote (p))
++ return 0;
++
++ return prefix_map_push (map_head, arg, p);
++}
++
++/* Parse a prefix-map according to the BUILD_PATH_PREFIX_MAP standard.
++
++ The input string value is of the form
++
++ dst[0]=src[0]:dst[1]=src[1]...
++
++ Every dst[i] and src[i] has had "%", "=" and ":" characters replaced with
++ "%#", "%+", and "%." respectively; this function reverses this replacement.
++
++ Rightmost entries are stored at the head of the parsed structure.
++
++ Returns 0 on failure and 1 on success. */
++int
++prefix_map_parse (struct prefix_map **map_head, const char *arg)
++{
++ struct prefix_map *old_head = *map_head;
++
++ size_t len = strlen (arg);
++ char *copy = (char *) alloca (len + 1);
++ memcpy (copy, arg, len + 1);
++
++ const char *sep = ":";
++ char *end, *tok = strtok_r (copy, sep, &end);
++ while (tok != NULL)
++ {
++ if (!prefix_map_parse1 (map_head, tok))
++ {
++ prefix_map_pop_until (map_head, old_head);
++ return 0;
++ }
++
++ tok = strtok_r (NULL, sep, &end);
++ }
++
++ return 1;
++}
+Index: b/gcc/debug.h
+===================================================================
+--- a/gcc/debug.h
++++ b/gcc/debug.h
+@@ -236,6 +236,7 @@ extern void dwarf2out_switch_text_sectio
+
+ const char *remap_debug_filename (const char *);
+ void add_debug_prefix_map (const char *);
++void add_debug_prefix_map_from_envvar ();
+
+ /* For -fdump-go-spec. */
+
+Index: b/gcc/final.c
+===================================================================
+--- a/gcc/final.c
++++ b/gcc/final.c
+@@ -46,6 +46,7 @@ along with GCC; see the file COPYING3.
+ #define INCLUDE_ALGORITHM /* reverse */
+ #include "system.h"
+ #include "coretypes.h"
++#include "prefix-map.h"
+ #include "backend.h"
+ #include "target.h"
+ #include "rtl.h"
+@@ -1506,22 +1507,9 @@ asm_str_count (const char *templ)
+ return count;
+ }
+ \f
+-/* ??? This is probably the wrong place for these. */
+-/* Structure recording the mapping from source file and directory
+- names at compile time to those to be embedded in debug
+- information. */
+-struct debug_prefix_map
+-{
+- const char *old_prefix;
+- const char *new_prefix;
+- size_t old_len;
+- size_t new_len;
+- struct debug_prefix_map *next;
+-};
+-
+-/* Linked list of such structures. */
+-static debug_prefix_map *debug_prefix_maps;
+
++/* Linked list of `struct prefix_map'. */
++static prefix_map *debug_prefix_maps = NULL;
+
+ /* Record a debug file prefix mapping. ARG is the argument to
+ -fdebug-prefix-map and must be of the form OLD=NEW. */
+@@ -1529,7 +1517,7 @@ static debug_prefix_map *debug_prefix_ma
+ void
+ add_debug_prefix_map (const char *arg)
+ {
+- debug_prefix_map *map;
++ prefix_map *map;
+ const char *p;
+
+ p = strchr (arg, '=');
+@@ -1538,7 +1526,7 @@ add_debug_prefix_map (const char *arg)
+ error ("invalid argument %qs to -fdebug-prefix-map", arg);
+ return;
+ }
+- map = XNEW (debug_prefix_map);
++ map = XNEW (prefix_map);
+ map->old_prefix = xstrndup (arg, p - arg);
+ map->old_len = p - arg;
+ p++;
+@@ -1548,28 +1536,32 @@ add_debug_prefix_map (const char *arg)
+ debug_prefix_maps = map;
+ }
+
++/* Add debug-prefix-maps from BUILD_PATH_PREFIX_MAP environment variable. */
++
++void
++add_debug_prefix_map_from_envvar ()
++{
++ const char *arg = getenv ("BUILD_PATH_PREFIX_MAP");
++
++ if (!arg || prefix_map_parse (&debug_prefix_maps, arg))
++ return;
++
++ error ("environment variable BUILD_PATH_PREFIX_MAP is "
++ "not well formed; see the GCC documentation for more details.");
++}
++
+ /* Perform user-specified mapping of debug filename prefixes. Return
+ the new name corresponding to FILENAME. */
+
+ const char *
+ remap_debug_filename (const char *filename)
+ {
+- debug_prefix_map *map;
+- char *s;
+- const char *name;
+- size_t name_len;
+-
+- for (map = debug_prefix_maps; map; map = map->next)
+- if (filename_ncmp (filename, map->old_prefix, map->old_len) == 0)
+- break;
+- if (!map)
++ const char *name = prefix_map_remap_alloca (debug_prefix_maps, filename);
++
++ if (name == filename)
+ return filename;
+- name = filename + map->old_len;
+- name_len = strlen (name) + 1;
+- s = (char *) alloca (name_len + map->new_len);
+- memcpy (s, map->new_prefix, map->new_len);
+- memcpy (s + map->new_len, name, name_len);
+- return ggc_strdup (s);
++
++ return ggc_strdup (name);
+ }
+ \f
+ /* Return true if DWARF2 debug info can be emitted for DECL. */
+Index: b/gcc/opts-global.c
+===================================================================
+--- a/gcc/opts-global.c
++++ b/gcc/opts-global.c
+@@ -335,6 +335,8 @@ handle_common_deferred_options (void)
+ if (flag_opt_info)
+ opt_info_switch_p (NULL);
+
++ add_debug_prefix_map_from_envvar ();
++
+ FOR_EACH_VEC_ELT (v, i, opt)
+ {
+ switch (opt->opt_index)
+Index: b/gcc/testsuite/gcc.dg/debug/dwarf2/build_path_prefix_map-1.c
+===================================================================
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/debug/dwarf2/build_path_prefix_map-1.c
+@@ -0,0 +1,9 @@
++/* DW_AT_comp_dir should be relative if BUILD_PATH_PREFIX_MAP is a prefix of it. */
++/* { dg-do compile } */
++/* { dg-options "-gdwarf -dA" } */
++/* { dg-set-compiler-env-var BUILD_PATH_PREFIX_MAP "DWARF2TEST=[file dirname [pwd]]" } */
++/* { dg-final { scan-assembler "DW_AT_comp_dir: \"DWARF2TEST/gcc" } } */
++
++void func (void)
++{
++}
+Index: b/gcc/testsuite/gcc.dg/debug/dwarf2/build_path_prefix_map-2.c
+===================================================================
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/debug/dwarf2/build_path_prefix_map-2.c
+@@ -0,0 +1,8 @@
++/* DW_AT_comp_dir should be absolute if BUILD_PATH_PREFIX_MAP is not set. */
++/* { dg-do compile } */
++/* { dg-options "-gdwarf -dA" } */
++/* { dg-final { scan-assembler "DW_AT_comp_dir: \"/" } } */
++
++void func (void)
++{
++}
+Subject: [PATCH 2/3] Use BUILD_PATH_PREFIX_MAP envvar to transform __FILE__
+
+Use the BUILD_PATH_PREFIX_MAP environment variable when expanding the __FILE__
+macro, in the same way that debug-prefix-map works for debugging symbol paths.
+
+This patch follows similar lines to the earlier patch for SOURCE_DATE_EPOCH.
+Specifically, we read the environment variable not in libcpp but via a hook
+which has an implementation defined in gcc/c-family. However, to achieve this
+is more complex than the earlier patch: we need to share the prefix_map data
+structure and associated functions between libcpp and c-family. Therefore, we
+need to move these to libiberty. (For comparison, the SOURCE_DATE_EPOCH patch
+did not need this because time_t et. al. are in the standard C library.)
+
+Acknowledgements
+----------------
+
+Dhole <dhole@openmailbox.org> who wrote the earlier patch for SOURCE_DATE_EPOCH
+which saved me a lot of time on figuring out what to edit.
+
+ChangeLogs
+----------
+
+gcc/c-family/ChangeLog:
+
+2017-07-21 Ximin Luo <infinity0@pwned.gg>
+
+ * c-common.c (cb_get_build_path_prefix_map): Define new call target.
+ * c-common.h (cb_get_build_path_prefix_map): Declare call target.
+ * c-lex.c (init_c_lex): Set the get_build_path_prefix_map callback.
+
+libcpp/ChangeLog:
+
+2017-07-21 Ximin Luo <infinity0@pwned.gg>
+
+ * include/cpplib.h (cpp_callbacks): Add get_build_path_prefix_map
+ callback.
+ * init.c (cpp_create_reader): Initialise build_path_prefix_map field.
+ * internal.h (cpp_reader): Add new field build_path_prefix_map.
+ * macro.c (_cpp_builtin_macro_text): Set the build_path_prefix_map
+ field if unset and apply it when expanding __FILE__ macros.
+
+gcc/testsuite/ChangeLog:
+
+2017-07-21 Ximin Luo <infinity0@pwned.gg>
+
+ * gcc.dg/cpp/build_path_prefix_map-1.c: New test.
+ * gcc.dg/cpp/build_path_prefix_map-2.c: New test.
+
+Index: b/gcc/c-family/c-common.c
+===================================================================
+--- a/gcc/c-family/c-common.c
++++ b/gcc/c-family/c-common.c
+@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.
+
+ #include "config.h"
+ #include "system.h"
++#include "prefix-map.h"
+ #include "coretypes.h"
+ #include "target.h"
+ #include "function.h"
+@@ -7905,6 +7906,25 @@ cb_get_source_date_epoch (cpp_reader *pf
+ return (time_t) epoch;
+ }
+
++/* Read BUILD_PATH_PREFIX_MAP from environment to have deterministic relative
++ paths to replace embedded absolute paths to get reproducible results.
++ Returns NULL if BUILD_PATH_PREFIX_MAP is badly formed. */
++
++prefix_map **
++cb_get_build_path_prefix_map (cpp_reader *pfile ATTRIBUTE_UNUSED)
++{
++ prefix_map **map = XCNEW (prefix_map *);
++
++ const char *arg = getenv ("BUILD_PATH_PREFIX_MAP");
++ if (!arg || prefix_map_parse (map, arg))
++ return map;
++
++ free (map);
++ error_at (input_location, "environment variable BUILD_PATH_PREFIX_MAP is "
++ "not well formed; see the GCC documentation for more details.");
++ return NULL;
++}
++
+ /* Callback for libcpp for offering spelling suggestions for misspelled
+ directives. GOAL is an unrecognized string; CANDIDATES is a
+ NULL-terminated array of candidate strings. Return the closest
+Index: b/gcc/c-family/c-common.h
+===================================================================
+--- a/gcc/c-family/c-common.h
++++ b/gcc/c-family/c-common.h
+@@ -1084,6 +1084,11 @@ extern time_t cb_get_source_date_epoch (
+ __TIME__ can store. */
+ #define MAX_SOURCE_DATE_EPOCH HOST_WIDE_INT_C (253402300799)
+
++/* Read BUILD_PATH_PREFIX_MAP from environment to have deterministic relative
++ paths to replace embedded absolute paths to get reproducible results.
++ Returns NULL if BUILD_PATH_PREFIX_MAP is badly formed. */
++extern prefix_map **cb_get_build_path_prefix_map (cpp_reader *pfile);
++
+ /* Callback for libcpp for offering spelling suggestions for misspelled
+ directives. */
+ extern const char *cb_get_suggestion (cpp_reader *, const char *,
+Index: b/gcc/c-family/c-lex.c
+===================================================================
+--- a/gcc/c-family/c-lex.c
++++ b/gcc/c-family/c-lex.c
+@@ -81,6 +81,7 @@ init_c_lex (void)
+ cb->read_pch = c_common_read_pch;
+ cb->has_attribute = c_common_has_attribute;
+ cb->get_source_date_epoch = cb_get_source_date_epoch;
++ cb->get_build_path_prefix_map = cb_get_build_path_prefix_map;
+ cb->get_suggestion = cb_get_suggestion;
+
+ /* Set the debug callbacks if we can use them. */
+Index: b/libcpp/include/cpplib.h
+===================================================================
+--- a/libcpp/include/cpplib.h
++++ b/libcpp/include/cpplib.h
+@@ -607,6 +607,9 @@ struct cpp_callbacks
+ /* Callback to parse SOURCE_DATE_EPOCH from environment. */
+ time_t (*get_source_date_epoch) (cpp_reader *);
+
++ /* Callback to parse BUILD_PATH_PREFIX_MAP from environment. */
++ struct prefix_map **(*get_build_path_prefix_map) (cpp_reader *);
++
+ /* Callback for providing suggestions for misspelled directives. */
+ const char *(*get_suggestion) (cpp_reader *, const char *, const char *const *);
+
+Index: b/libcpp/init.c
+===================================================================
+--- a/libcpp/init.c
++++ b/libcpp/init.c
+@@ -261,6 +261,9 @@ cpp_create_reader (enum c_lang lang, cpp
+ /* Initialize source_date_epoch to -2 (not yet set). */
+ pfile->source_date_epoch = (time_t) -2;
+
++ /* Initialize build_path_prefix_map to NULL (not yet set). */
++ pfile->build_path_prefix_map = NULL;
++
+ /* The expression parser stack. */
+ _cpp_expand_op_stack (pfile);
+
+Index: b/libcpp/internal.h
+===================================================================
+--- a/libcpp/internal.h
++++ b/libcpp/internal.h
+@@ -507,6 +507,11 @@ struct cpp_reader
+ set to -1 to disable it or to a non-negative value to enable it. */
+ time_t source_date_epoch;
+
++ /* Externally set prefix-map to transform absolute paths, useful for
++ reproducibility. It should be initialized to NULL (not yet set or
++ disabled) or to a `struct prefix_map` double pointer to enable it. */
++ struct prefix_map **build_path_prefix_map;
++
+ /* EOF token, and a token forcing paste avoidance. */
+ cpp_token avoid_paste;
+ cpp_token eof;
+Index: b/libcpp/macro.c
+===================================================================
+--- a/libcpp/macro.c
++++ b/libcpp/macro.c
+@@ -26,6 +26,7 @@ along with this program; see the file CO
+ #include "system.h"
+ #include "cpplib.h"
+ #include "internal.h"
++#include "prefix-map.h"
+
+ typedef struct macro_arg macro_arg;
+ /* This structure represents the tokens of a macro argument. These
+@@ -291,7 +292,17 @@ _cpp_builtin_macro_text (cpp_reader *pfi
+ unsigned int len;
+ const char *name;
+ uchar *buf;
++ prefix_map **map = pfile->build_path_prefix_map;
+
++ /* Set a prefix-map for __FILE__ if BUILD_PATH_PREFIX_MAP is defined. */
++ if (map == NULL && pfile->cb.get_build_path_prefix_map != NULL)
++ {
++ map = pfile->cb.get_build_path_prefix_map (pfile);
++ if (map == NULL)
++ abort ();
++ pfile->build_path_prefix_map = map;
++ }
++
+ if (node->value.builtin == BT_FILE)
+ name = linemap_get_expansion_filename (pfile->line_table,
+ pfile->line_table->highest_line);
+@@ -301,6 +312,11 @@ _cpp_builtin_macro_text (cpp_reader *pfi
+ if (!name)
+ abort ();
+ }
++
++ /* Apply the prefix-map for deterministic path output. */
++ if (map != NULL)
++ name = prefix_map_remap_alloca (*map, name);
++
+ len = strlen (name);
+ buf = _cpp_unaligned_alloc (pfile, len * 2 + 3);
+ result = buf;
+Index: b/gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-1.c
+===================================================================
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-1.c
+@@ -0,0 +1,11 @@
++/* __FILE__ should strip BUILD_PATH_PREFIX_MAP if the latter is a prefix. */
++/* { dg-do run } */
++/* { dg-set-compiler-env-var BUILD_PATH_PREFIX_MAP "MACROTEST=$srcdir" } */
++
++int
++main ()
++{
++ if (__builtin_strcmp (__FILE__, "MACROTEST/gcc.dg/cpp/build_path_prefix_map-1.c") != 0)
++ __builtin_abort ();
++ return 0;
++}
+Index: b/gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-2.c
+===================================================================
+--- /dev/null
++++ b/gcc/testsuite/gcc.dg/cpp/build_path_prefix_map-2.c
+@@ -0,0 +1,12 @@
++/* __FILE__ should not be relative if BUILD_PATH_PREFIX_MAP is not set, and gcc is
++ asked to compile an absolute filename as is the case with this test. */
++/* { dg-do run } */
++/* { dg-set-compiler-env-var BUILD_PATH_PREFIX_MAP } */
++
++int
++main ()
++{
++ if (__builtin_strcmp (__FILE__, "./gcc.dg/cpp/build_path_prefix_map-2.c") == 0)
++ __builtin_abort ();
++ return 0;
++}
+Subject: [PATCH 3/3] When remapping paths, only match whole path components
+
+Change the remapping algorithm so that each old_prefix only matches paths that
+have old_prefix as a whole path component prefix. (A whole path component is a
+part of a path that begins and ends at a directory separator or at either end
+of the path string.)
+
+This remapping algorithm is more predictable than the old algorithm, because
+there is no chance of mappings for one directory interfering with mappings for
+other directories. It contains less corner cases and is therefore nicer for
+clients to use. For these reasons, in our BUILD_PATH_PREFIX_MAP specification
+we recommend this algorithm, and it would be good for GCC to follow suit.
+
+This does technically break backwards compatibility but I don't think anyone
+would be reasonably depending on the corner cases of the previous algorithm,
+which are surprising and counterintuitive.
+
+Acknowledgements
+----------------
+
+Discussions with Michael Woerister and other members of the Rust compiler team
+on Github, and discussions with Daniel Shahaf on the rb-general@ mailing list
+on lists.reproducible-builds.org.
+
+ChangeLogs
+----------
+
+gcc/ChangeLog:
+
+2017-03-27 Ximin Luo <infinity0@pwned.gg>
+
+ * doc/invoke.texi (Environment Variables): Document form and behaviour
+ of BUILD_PATH_PREFIX_MAP.
+
+libiberty/ChangeLog:
+
+2017-03-27 Ximin Luo <infinity0@pwned.gg>
+
+ * prefix-map.c: When remapping paths, only match whole path components.
+
+Index: b/libiberty/prefix-map.c
+===================================================================
+--- a/libiberty/prefix-map.c
++++ b/libiberty/prefix-map.c
+@@ -101,12 +101,22 @@ struct prefix_map *
+ prefix_map_find (struct prefix_map *map, const char *old_name,
+ const char **suffix, size_t *suf_len)
+ {
++ size_t len;
++
+ for (; map; map = map->next)
+- if (filename_ncmp (old_name, map->old_prefix, map->old_len) == 0)
+- {
+- *suf_len = strlen (*suffix = old_name + map->old_len);
+- break;
+- }
++ {
++ len = map->old_len;
++ /* Ignore trailing path separators at the end of old_prefix */
++ while (len > 0 && IS_DIR_SEPARATOR (map->old_prefix[len-1])) len--;
++ /* Check if old_name matches old_prefix at a path component boundary */
++ if (! filename_ncmp (old_name, map->old_prefix, len)
++ && (IS_DIR_SEPARATOR (old_name[len])
++ || old_name[len] == '\0'))
++ {
++ *suf_len = strlen (*suffix = old_name + len);
++ break;
++ }
++ }
+
+ return map;
+ }
--
Jan Nieuwenhuizen <janneke@gnu.org> | GNU LilyPond http://lilypond.org
Freelance IT http://JoyofSource.com | Avatar® http://AvatarAcademy.com
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: gcc-ddc.diff --]
[-- Type: text/x-patch, Size: 8281 bytes --]
$ ./pre-inst-env guix build gcc-ddc@4.7.4
process 11900 acquired build slot '/var/guix/offload/192.168.32.121/0'
load on machine '192.168.32.121' is 0.0 (normalized: 0.0)
process 11900 acquired build slot '/var/guix/offload/192.168.32.122/0'
load on machine '192.168.32.122' is 0.07 (normalized: 0.023333333333333334)
@ build-started /gnu/store/sb9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv - x86_64-linux /var/log/guix/drvs/sb//9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv.bz2
sending 0 store items to '192.168.32.121'...
offloading '/gnu/store/sb9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv' to '192.168.32.121'...
@ build-remote /gnu/store/sb9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv 192.168.32.121
substitute: updating list of substitutes from 'http://guix2.oban.verum.com:8181'... 100.0%
substitute: updating list of substitutes from 'https://mirror.guixsd.org'... 100.0%
@ build-started /gnu/store/sb9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv - x86_64-linux /var/log/guix/drvs/sb//9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv.bz2
--- /gnu/store/zw672zcmykdwzm4x7l098hb94c34ak85-repro-gcc-4.7.4/bin/gcc
+++ /gnu/store/jhcf91y94nfnr5hmmxj7jn3whq1gm009-repr2-gcc-4.7.4/bin/gcc
??? objdump --line-numbers --disassemble --demangle --section=.text {}
? @@ -363,31 +363,31 @@
? 402da3: 0f 84 50 0e 00 00 je 403bf9 <main+0x1429>
? 402da9: 4c 8b 25 a0 51 28 00 mov 0x2851a0(%rip),%r12
? 402db0: 4c 89 e7 mov %r12,%rdi
? 402db3: e8 08 f5 ff ff callq 4022c0 <strlen@plt>
? 402db8: 48 83 c0 68 add $0x68,%rax
? 402dbc: 49 b8 2f 67 6e 75 2f movabs $0x6f74732f756e672f,%r8
? 402dc3: 73 74 6f
? - 402dc6: 49 b9 72 65 2f 7a 77 movabs $0x323736777a2f6572,%r9
? - 402dcd: 36 37 32
? + 402dc6: 49 b9 72 65 2f 6a 68 movabs $0x396663686a2f6572,%r9
? + 402dcd: 63 66 39
? 402dd0: 48 83 e0 f0 and $0xfffffffffffffff0,%rax
? - 402dd4: 48 bf 6b 38 35 2d 72 movabs $0x727065722d35386b,%rdi
? + 402dd4: 48 bf 30 30 39 2d 72 movabs $0x727065722d393030,%rdi
? 402ddb: 65 70 72
? - 402dde: 48 ba 6d 34 78 37 6c movabs $0x3839306c3778346d,%rdx
? - 402de5: 30 39 38
? + 402dde: 48 ba 35 68 6d 6d 78 movabs $0x6a376a786d6d6835,%rdx
? + 402de5: 6a 37 6a
? 402de8: 48 29 c4 sub %rax,%rsp
? - 402deb: 48 be 68 62 39 34 63 movabs $0x6134336334396268,%rsi
? - 402df2: 33 34 61
? - 402df5: 48 b8 7a 63 6d 79 6b movabs $0x7a77646b796d637a,%rax
? - 402dfc: 64 77 7a
? + 402deb: 48 be 6e 33 77 68 71 movabs $0x6d6731716877336e,%rsi
? + 402df2: 31 67 6d
? + 402df5: 48 b8 31 79 39 34 6e movabs $0x726e666e34397931,%rax
? + 402dfc: 66 6e 72
? 402dff: 48 8d 5c 24 0f lea 0xf(%rsp),%rbx
? 402e04: 48 83 e3 f0 and $0xfffffffffffffff0,%rbx
? 402e08: 4c 89 03 mov %r8,(%rbx)
? 402e0b: 4c 89 4b 08 mov %r9,0x8(%rbx)
? - 402e0f: 49 b8 6f 2d 67 63 63 movabs $0x2e342d6363672d6f,%r8
? + 402e0f: 49 b8 32 2d 67 63 63 movabs $0x2e342d6363672d32,%r8
? 402e16: 2d 34 2e
? 402e19: 49 b9 37 2e 34 2f 6c movabs $0x2f62696c2f342e37,%r9
? 402e20: 69 62 2f
? 402e23: 48 89 7b 28 mov %rdi,0x28(%rbx)
? 402e27: 48 8d 7b 44 lea 0x44(%rbx),%rdi
? 402e2b: 48 89 53 18 mov %rdx,0x18(%rbx)
? 402e2f: 48 89 73 20 mov %rsi,0x20(%rbx)
??? readelf --wide --decompress --hex-dump=.rodata {}
? @@ -48,27 +48,27 @@
? 0x0043e990 653d2a3a 253e6d74 756e653d 6e617469 e=*:%>mtune=nati
? 0x0043e9a0 76652025 3a6c6f63 616c5f63 70755f64 ve %:local_cpu_d
? 0x0043e9b0 65746563 74287475 6e65297d 7d20257b etect(tune)}} %{
? 0x0043e9c0 6d74756e 653d6e61 74697665 3a253e6d mtune=native:%>m
? 0x0043e9d0 74756e65 3d6e6174 69766520 253a6c6f tune=native %:lo
? 0x0043e9e0 63616c5f 6370755f 64657465 63742874 cal_cpu_detect(t
? 0x0043e9f0 756e6529 7d000000 2f676e75 2f73746f
? - 0x0043ea00 72652f7a 77363732 7a636d79 6b64777a
? - 0x0043ea10 6d347837 6c303938 68623934 63333461
? - 0x0043ea20 6b38352d 72657072 6f2d6763 632d342e
? + 0x0043ea00 72652f6a 68636639 31793934 6e666e72 re/jhcf91y94nfnr
? + 0x0043ea10 35686d6d 786a376a 6e337768 7131676d 5hmmxj7jn3whq1gm
? + 0x0043ea20 3030392d 72657072 322d6763 632d342e 009-repr2-gcc-4.
? 0x0043ea30 372e342f 6c69622f 6763632f 00000000 7.4/lib/gcc/....
? - 0x0043ea40 2f676e75 2f73746f 72652f7a 77363732 /gnu/store/zw672
? - 0x0043ea50 7a636d79 6b64777a 6d347837 6c303938 zcmykdwzm4x7l098
? - 0x0043ea60 68623934 63333461 6b38352d 72657072 hb94c34ak85-repr
? - 0x0043ea70 6f2d6763 632d342e 372e342f 6c696265 o-gcc-4.7.4/libe
? + 0x0043ea40 2f676e75 2f73746f 72652f6a 68636639 /gnu/store/jhcf9
? + 0x0043ea50 31793934 6e666e72 35686d6d 786a376a 1y94nfnr5hmmxj7j
? + 0x0043ea60 6e337768 7131676d 3030392d 72657072 n3whq1gm009-repr
? + 0x0043ea70 322d6763 632d342e 372e342f 6c696265 2-gcc-4.7.4/libe
? 0x0043ea80 7865632f 6763632f 00000000 00000000 xec/gcc/........
? - 0x0043ea90 2f676e75 2f73746f 72652f7a 77363732
? - 0x0043eaa0 7a636d79 6b64777a 6d347837 6c303938
? - 0x0043eab0 68623934 63333461 6b38352d 72657072
? - 0x0043eac0 6f2d6763 632d342e 372e342f 62696e2f
? + 0x0043ea90 2f676e75 2f73746f 72652f6a 68636639 /gnu/store/jhcf9
? + 0x0043eaa0 31793934 6e666e72 35686d6d 786a376a 1y94nfnr5hmmxj7j
? + 0x0043eab0 6e337768 7131676d 3030392d 72657072 n3whq1gm009-repr
? + 0x0043eac0 322d6763 632d342e 372e342f 62696e2f 2-gcc-4.7.4/bin/
? 0x0043ead0 00000000 00000000 2d706970 65206967 ........-pipe ig
? 0x0043eae0 6e6f7265 64206265 63617573 65202d73 nored because -s
? 0x0043eaf0 6176652d 74656d70 73207370 65636966 ave-temps specif
? 0x0043eb00 69656400 00000000 253c2d78 20257325 ied.....%<-x %s%
? 0x0043eb10 3e206166 74657220 6c617374 20696e70 > after last inp
? 0x0043eb20 75742066 696c6520 68617320 6e6f2065 ut file has no e
? 0x0043eb30 66666563 74000000 25717320 69732061 ffect...%qs is a
? @@ -1553,18 +1553,18 @@
? 0x004447a0 bffc4000 00000000 f6fd4000 00000000 ..@.......@.....
? 0x004447b0 bffc4000 00000000 bffc4000 00000000 ..@.......@.....
? 0x004447c0 bffc4000 00000000 f6fd4000 00000000 ..@.......@.....
? 0x004447d0 00000000 00000000 00000000 00000000 ................
? 0x004447e0 01000000 02000000 03000000 0e000000 ................
? 0x004447f0 0e000000 0e000000 0e000000 0e000000 ................
? 0x00444800 0e000000 0e000000 0e000000 07000000 ................
? - 0x00444810 2f676e75 2f73746f 72652f7a 77363732 /gnu/store/zw672
? - 0x00444820 7a636d79 6b64777a 6d347837 6c303938 zcmykdwzm4x7l098
? - 0x00444830 68623934 63333461 6b38352d 72657072 hb94c34ak85-repr
? - 0x00444840 6f2d6763 632d342e 372e3400 5f524f4f o-gcc-4.7.4._ROO
? + 0x00444810 2f676e75 2f73746f 72652f6a 68636639 /gnu/store/jhcf9
? + 0x00444820 31793934 6e666e72 35686d6d 786a376a 1y94nfnr5hmmxj7j
? + 0x00444830 6e337768 7131676d 3030392d 72657072 n3whq1gm009-repr
? + 0x00444840 322d6763 632d342e 372e3400 5f524f4f 2-gcc-4.7.4._ROO
? 0x00444850 54002e2e 2f2e2e2f 6763632d 342e372e T.../../gcc-4.7.
? 0x00444860 342f6763 632f7061 72616d73 2e630069 4/gcc/params.c.i
? 0x00444870 6e76616c 69642070 6172616d 65746572 nvalid parameter
? 0x00444880 20257173 00707265 64696374 61626c65 %qs.predictable
? 0x00444890 2d627261 6e63682d 6f757463 6f6d6500 -branch-outcome.
? 0x004448a0 6d61782d 696e6c69 6e652d69 6e736e73 max-inline-insns
? 0x004448b0 2d73696e 676c6500 6d61782d 696e6c69 -single.max-inli
builder for `/gnu/store/sb9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv' failed with exit code 1
@ build-failed /gnu/store/sb9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv - 1 builder for `/gnu/store/sb9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv' failed with exit code 1
derivation '/gnu/store/sb9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv' offloaded to '192.168.32.121' failed: build of `/gnu/store/sb9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv' failed
@ build-failed /gnu/store/sb9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv - 1 builder for `/gnu/store/sb9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv' failed with exit code 100
guix build: error: build failed: build of `/gnu/store/sb9drfd3n8pqc1ch0yffqccpgchc3jll-gcc-ddc-4.7.4.drv' failed
[-- Attachment #4: Type: text/plain, Size: 152 bytes --]
--
Jan Nieuwenhuizen <janneke@gnu.org> | GNU LilyPond http://lilypond.org
Freelance IT http://JoyofSource.com | Avatar® http://AvatarAcademy.com
next prev parent reply other threads:[~2017-11-10 19:20 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-11-01 16:46 diverse double compilation: using $ORIGIN? Ricardo Wurmus
2017-11-02 8:41 ` Fwd: " Ricardo Wurmus
2017-11-02 8:46 ` [bootstrappable] " Jan Nieuwenhuizen
2017-11-05 16:09 ` Ludovic Courtès
2017-11-05 16:27 ` Jan Nieuwenhuizen
2017-11-10 19:19 ` Jan Nieuwenhuizen [this message]
2017-11-05 16:11 ` Ludovic Courtès
2017-11-10 4:53 ` Chris Marusich
2017-11-11 21:56 ` Ludovic Courtès
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://guix.gnu.org/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87efp6x7pm.fsf@gnu.org \
--to=janneke@gnu.org \
--cc=bootstrappable@freelists.org \
--cc=guix-devel@gnu.org \
--cc=ludo@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/guix.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).