diff options
Diffstat (limited to 'libbuild2/config')
-rw-r--r-- | libbuild2/config/init.cxx | 1 | ||||
-rw-r--r-- | libbuild2/config/module.cxx | 7 | ||||
-rw-r--r-- | libbuild2/config/module.hxx | 9 | ||||
-rw-r--r-- | libbuild2/config/utility.cxx | 1 | ||||
-rw-r--r-- | libbuild2/config/utility.hxx | 83 |
5 files changed, 99 insertions, 2 deletions
diff --git a/libbuild2/config/init.cxx b/libbuild2/config/init.cxx index 950579a..7b810bd 100644 --- a/libbuild2/config/init.cxx +++ b/libbuild2/config/init.cxx @@ -549,6 +549,7 @@ namespace build2 // Initialize the config entry points in the build system core. // config_save_variable = &module::save_variable; + config_save_environment = &module::save_environment; config_save_module = &module::save_module; config_preprocess_create = &preprocess_create; config_configure_post = &module::configure_post; diff --git a/libbuild2/config/module.cxx b/libbuild2/config/module.cxx index c84b1fa..713d30c 100644 --- a/libbuild2/config/module.cxx +++ b/libbuild2/config/module.cxx @@ -56,6 +56,13 @@ namespace build2 m->save_variable (var, flags); } + void module:: + save_environment (scope& rs, const char* var) + { + if (module* m = rs.find_module<module> (module::name)) + m->save_environment (var); + } + bool module:: save_module (const char* name, int prio) { diff --git a/libbuild2/config/module.hxx b/libbuild2/config/module.hxx index 92fed32..543c486 100644 --- a/libbuild2/config/module.hxx +++ b/libbuild2/config/module.hxx @@ -173,6 +173,15 @@ namespace build2 return nullptr; } + void + save_environment (const char* var) + { + saved_environment.insert (var); + } + + static void + save_environment (scope&, const char*); + config::saved_environment saved_environment; strings old_environment; diff --git a/libbuild2/config/utility.cxx b/libbuild2/config/utility.cxx index f777c08..1f1ac08 100644 --- a/libbuild2/config/utility.cxx +++ b/libbuild2/config/utility.cxx @@ -8,6 +8,7 @@ using namespace std; namespace build2 { void (*config_save_variable) (scope&, const variable&, optional<uint64_t>); + void (*config_save_environment) (scope&, const char*); void (*config_save_module) (scope&, const char*, int); const string& (*config_preprocess_create) (context&, values&, 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. // |