summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt30
-rwxr-xr-xscripts/invoke-with-relative-paths.pl95
2 files changed, 125 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ba5e60f6146..154273576d7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -263,6 +263,36 @@ IF (ENABLE_GCOV AND NOT WIN32 AND NOT APPLE)
SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -fprofile-arcs -ftest-coverage -lgcov")
ENDIF()
+IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
+ OPTION(REPRODUCIBLE_BUILD "Take extra pains to make build result independent of build location and time" OFF)
+ENDIF()
+IF(REPRODUCIBLE_BUILD)
+ SET(DEBUG_PREFIX_FLAGS
+ "-fdebug-prefix-map=${CMAKE_SOURCE_DIR}/=./ -fdebug-prefix-map=${CMAKE_CURRENT_BINARY_DIR}=./obj")
+
+ # See if -fdebug-prefix= commands are included in the debug output,
+ # making the build unreproducible with switches recorded.
+ # See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69821.
+ EXECUTE_PROCESS(COMMAND ${CMAKE_C_COMPILER} -g3 -x c -S -fdebug-prefix-map=foo=bar -o - -
+ INPUT_FILE /dev/null OUTPUT_VARIABLE DEBUG_PREFIX_MAP_RESULT)
+ IF(DEBUG_PREFIX_MAP_RESULT MATCHES "foo=bar")
+ SET(DEBUG_PREFIX_FLAGS "${DEBUG_PREFIX_FLAGS} -gno-record-gcc-switches")
+ ENDIF()
+
+ SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${DEBUG_PREFIX_FLAGS}")
+ SET(CMAKE_C_FLAGS_RELWITHDEBINFO
+ "${CMAKE_C_FLAGS_RELWITHDEBINFO} ${DEBUG_PREFIX_FLAGS}")
+ SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${DEBUG_PREFIX_FLAGS}")
+ SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO
+ "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${DEBUG_PREFIX_FLAGS}")
+
+ SET(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,--build-id=none")
+ SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,--build-id=none")
+
+ set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE
+ "${CMAKE_SOURCE_DIR}/scripts/invoke-with-relative-paths.pl")
+ENDIF()
+
OPTION(ENABLED_LOCAL_INFILE
"If we should should enable LOAD DATA LOCAL by default" ${IF_WIN})
MARK_AS_ADVANCED(ENABLED_LOCAL_INFILE)
diff --git a/scripts/invoke-with-relative-paths.pl b/scripts/invoke-with-relative-paths.pl
new file mode 100755
index 00000000000..97480330b7f
--- /dev/null
+++ b/scripts/invoke-with-relative-paths.pl
@@ -0,0 +1,95 @@
+#! /usr/bin/perl
+#
+# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+#
+# 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; version 2 of the License.
+#
+# 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,
+# 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
+#
+
+#
+# Take the given GCC command line and run it with all absolute paths
+# changed to relative paths. This makes sure that no part of the build
+# path leaks into the .o files, which it normally would through the
+# contents of __FILE__. (Debug information is also affected, but that
+# is already fixed through -fdebug-prefix-map=.)
+#
+# A more elegant solution would be -ffile-prefix-map=, but this is
+# not currently supported in GCC; see
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70268.
+#
+
+use strict;
+use warnings;
+use Cwd;
+
+my $cwd = getcwd();
+
+my @newarg = ();
+for my $i (0..$#ARGV) {
+ my $arg = $ARGV[$i];
+ if ($arg =~ /-I(.+)$/) {
+ $arg = '-I' . relativize($1, $cwd);
+ } elsif ($arg =~ /^\//) {
+ $arg = relativize($arg, $cwd);
+ }
+ push @newarg, $arg;
+}
+
+exec(@newarg);
+
+# /a/b/c/foo from /a/b/d = ../c/foo
+sub relativize {
+ my ($dir1, $dir2) = @_;
+
+ if ($dir1 !~ /^\//) {
+ # Not an absolute path.
+ return $dir1;
+ }
+
+ if (! -e $dir1) {
+# print STDERR "Unknown file/directory $dir1.\n";
+ return $dir1;
+ }
+ # Resolve symlinks and such, because getcwd() does.
+ $dir1 = Cwd::abs_path($dir1);
+
+ if ($dir1 =~ /^\/(lib|tmp|usr)/) {
+ # Not related to our source code.
+ return $dir1;
+ }
+
+ if ($dir1 eq $dir2) {
+ return ".";
+ }
+
+ my (@dir1_components) = split /\//, $dir1;
+ my (@dir2_components) = split /\//, $dir2;
+
+ # Remove common leading components.
+ while (scalar @dir1_components > 0 && scalar @dir2_components > 0 &&
+ $dir1_components[0] eq $dir2_components[0]) {
+ shift @dir1_components;
+ shift @dir2_components;
+ }
+
+ my $ret = "";
+ for my $i (0..$#dir2_components) {
+ $ret .= '../';
+ }
+ $ret .= join('/', @dir1_components);
+
+ # print STDERR "[$dir1] from [$dir2] => [$ret]\n";
+
+ return $ret;
+}
+