===================================================================
@@ -27197,6 +27197,26 @@ Recognize EUCJP characters.
If @env{LANG} is not defined, or if it has some other value, then the
compiler uses @code{mblen} and @code{mbtowc} as defined by the default locale to
recognize and translate multibyte characters.
+
+@item BUILD_PATH_PREFIX_MAP
+@findex BUILD_PATH_PREFIX_MAP
+If this variable is set, it specifies an ordered map used to transform
+filepaths output in debugging symbols and expansions of the @code{__FILE__}
+macro. This may be used to achieve fully reproducible output. In the context
+of running GCC within a higher-level build tool, it is typically more reliable
+than setting command line arguments such as @option{-fdebug-prefix-map} or
+common environment variables such as @env{CFLAGS}, since the build tool may
+save these latter values into other output outside of GCC's control.
+
+The value is of the form
+@samp{@var{dst@r{[0]}}=@var{src@r{[0]}}:@var{dst@r{[1]}}=@var{src@r{[1]}}@r{@dots{}}}.
+If any @var{dst@r{[}i@r{]}} or @var{src@r{[}i@r{]}} contains @code{%}, @code{=}
+or @code{:} characters, they must be replaced with @code{%#}, @code{%+}, and
+@code{%.} respectively.
+
+Whenever GCC emits a filepath that starts with a whole path component matching
+@var{src@r{[}i@r{]}} for some @var{i}, with rightmost @var{i} taking priority,
+the matching part is replaced with @var{dst@r{[}i@r{]}} in the final output.
@end table
@noindent
===================================================================
@@ -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
===================================================================
@@ -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 *,
===================================================================
@@ -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. */
===================================================================
@@ -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 *);
===================================================================
@@ -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);
===================================================================
@@ -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;
===================================================================
@@ -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;
===================================================================
@@ -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;
+}
===================================================================
@@ -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;
+}