aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/config/utility.hxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2021-04-07 11:33:05 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2021-04-07 11:43:04 +0200
commite9f69e067da3e096e1e64be70ec2b6de30f71d2c (patch)
tree478c9f0ec86a225398424bcc9305270ca6800339 /libbuild2/config/utility.hxx
parent5e51d523e71231cb190e9ed981962df527f4ee7e (diff)
Register environment variables for hermetic build configurations
Diffstat (limited to 'libbuild2/config/utility.hxx')
-rw-r--r--libbuild2/config/utility.hxx83
1 files changed, 81 insertions, 2 deletions
diff --git a/libbuild2/config/utility.hxx b/libbuild2/config/utility.hxx
index 45fdaba..382c22f 100644
--- a/libbuild2/config/utility.hxx
+++ b/libbuild2/config/utility.hxx
@@ -36,6 +36,9 @@ namespace build2
(*config_save_variable) (scope&, const variable&, optional<uint64_t>);
LIBBUILD2_SYMEXPORT extern void
+ (*config_save_environment) (scope&, const char*);
+
+ LIBBUILD2_SYMEXPORT extern void
(*config_save_module) (scope&, const char*, int);
LIBBUILD2_SYMEXPORT extern const string&
@@ -53,7 +56,7 @@ namespace build2
namespace config
{
- // Mark the variable to be saved during configuration.
+ // Mark a variable to be saved during configuration.
//
const uint64_t save_default_commented = 0x01; // Based on value::extra.
const uint64_t save_null_omitted = 0x02; // Treat NULL as undefined.
@@ -67,7 +70,7 @@ namespace build2
config_save_variable (rs, var, flags);
}
- // Mark the variable as "unsaved" (always transient).
+ // Mark a variable as "unsaved" (always transient).
//
// Such variables are not very common and are usually used to control the
// process of configuration itself.
@@ -79,6 +82,82 @@ namespace build2
config_save_variable (rs, var, nullopt);
}
+ // Mark an environment variable to be saved during hermetic configuration.
+ //
+ // Some notes/suggestions on saving environment variables for tools (e.g.,
+ // compilers, etc):
+ //
+ // 1. We want to save variables that affect the result (e.g., build
+ // output) rather than byproducts (e.g., diagnostics).
+ //
+ // 2. Environment variables are often poorly documented (and not always in
+ // the ENVIRONMENT section; sometimes they are mentioned together with
+ // the corresponding option). A sensible approach in this case is to
+ // save documented (and perhaps well-known undocumented) variables --
+ // the user can always save additional variables if necessary. The way
+ // to discover undocumented environment variables is to grep the source
+ // code.
+ //
+ // 3. Sometime environment variables only affect certain modes of a tool.
+ // If such modes are not used, then there is no need to save the
+ // corresponding variables.
+ //
+ // 4. Finally, there could be environment variables that are incompatible
+ // with what we are doing (e.g., they change the mode of operation or
+ // some such; see GCC's DEPENDENCIES_OUTPUT for example). While they
+ // can be cleared for each invocation, this is burdensome and it is
+ // often easier to just unset them for the entire build system process
+ // if we can be reasonable sure that there can be no plausible use for
+ // this variable (e.g., by another module or by the buildfile
+ // directly). The module's load() function is a natural place to do
+ // that.
+ //
+ inline void
+ save_environment (scope& rs, const string& var)
+ {
+ if (config_save_environment != nullptr)
+ config_save_environment (rs, var.c_str ());
+ }
+
+ inline void
+ save_environment (scope& rs, const char* var)
+ {
+ if (config_save_environment != nullptr)
+ config_save_environment (rs, var);
+ }
+
+ inline void
+ save_environment (scope& rs, initializer_list<const char*> vars)
+ {
+ if (config_save_environment != nullptr)
+ {
+ for (const char* var: vars)
+ config_save_environment (rs, var);
+ }
+ }
+
+ inline void
+ save_environment (scope& rs, const strings& vars)
+ {
+ if (config_save_environment != nullptr)
+ {
+ for (const string& var: vars)
+ config_save_environment (rs, var.c_str ());
+ }
+ }
+
+ // A NULL-terminated list of variables.
+ //
+ inline void
+ save_environment (scope& rs, const char* const* vars)
+ {
+ if (vars != nullptr && config_save_environment != nullptr)
+ {
+ for (; *vars != nullptr; ++vars)
+ config_save_environment (rs, *vars);
+ }
+ }
+
// Establish module save order/priority with INT32_MIN being the highest.
// Modules with the same priority are saved in the order inserted.
//