// file : bpkg/package-configuration.hxx -*- C++ -*- // license : MIT; see accompanying LICENSE file #ifndef BPKG_PACKAGE_CONFIGURATION_HXX #define BPKG_PACKAGE_CONFIGURATION_HXX #include // build2::names #include // build2::config::variable_origin #include #include #include using namespace std; namespace bpkg { class package_skeleton; // Serialize the variable value as a command line override. // string serialize_cmdline (const string& name, const optional& value); struct config_variable_value { string name; // The variable_origin values have the following meaning: // // default -- default value from the config directive // buildfile -- dependent configuration (config_source::dependent) // override -- user configuration (config_source::user) // undefined -- none of the above // build2::config::variable_origin origin; // Variable type name with absent signifying untyped. // optional type; // If origin is not undefined, then this is the reversed variable value // with absent signifying NULL. // optional value; // If origin is buildfile, then this is the "originating dependent" which // first set this variable to this value. // optional dependent; // If origin is buildfile, then this flag indicates whether the // originating dependent has been encountered during the negotiation // retry. // bool confirmed; // If origin is buildfile and the originating dependent has been // encountered during the negotiation, then this flag indicates whether // this dependent has another dependency alternative. // // @@ Strictly speaking this is a property of the dependent and // duplicating it here for each variable is quite dirty (and requires // us to drag this through skeleton calls). Doing this properly, // however, will likely require another map with the dependent as a // key. Maybe one day. // bool has_alternative; public: void undefine () { origin = build2::config::variable_origin::undefined; value = nullopt; dependent = nullopt; confirmed = false; has_alternative = false; } string serialize_cmdline () const { return bpkg::serialize_cmdline (name, value); } }; void to_checksum (sha256&, const config_variable_value&); // A subset of config_variable_value for variable values set by the // dependents (origin is buildfile). Used to track change history. // struct dependent_config_variable_value { string name; optional value; package_key dependent; bool has_alternative; public: string serialize_cmdline () const { return bpkg::serialize_cmdline (name, value); } }; inline bool operator== (const dependent_config_variable_value& x, const dependent_config_variable_value& y) { return x.name == y.name && x.value == y.value && x.dependent == y.dependent; } class dependent_config_variable_values: public small_vector { public: const dependent_config_variable_value* find (const string& name) const { auto i (find_if (begin (), end (), [&name] (const dependent_config_variable_value& v) { return v.name == name; })); return i != end () ? &*i : nullptr; } }; class package_configuration: public vector { public: package_key package; bool system = false; // True if system package without skeleton info. explicit package_configuration (package_key p): package (move (p)) {} config_variable_value* find (const string& name) { auto i (find_if (begin (), end (), [&name] (const config_variable_value& v) { return v.name == name; })); return i != end () ? &*i : nullptr; } const config_variable_value* find (const string& name) const { auto i (find_if (begin (), end (), [&name] (const config_variable_value& v) { return v.name == name; })); return i != end () ? &*i : nullptr; } // Print buildfile and override configuration variable values as command // line overrides one per line with the specified indentation. After each // variable also print in parenthesis its origin. If overrides is not // NULL, then it is used to override the value/dependent information. // void print (diag_record&, const char* indent, const dependent_config_variable_values* overrides = nullptr) const; }; class package_configurations: public small_vector { public: // Note: may invalidate references. // package_configuration& operator[] (const package_key& p) { auto i (find_if (begin (), end (), [&p] (const package_configuration& pc) { return pc.package == p; })); if (i != end ()) return *i; push_back (package_configuration (p)); return back (); } void clear () { small_vector::clear (); change_history_.clear (); } // Implementation details. // public: // Note: dependent_config_variable_values must be sorted by name. // small_vector change_history_; }; // Negotiate the configuration for the specified dependencies of the // specified dependent. Return true if the configuration has changed. // Return absent if has_alternative is true and no acceptable configuration // could be negotiated. // optional negotiate_configuration ( package_configurations&, package_skeleton& dependent, pair position, const small_vector, 1>& dependencies, bool has_alternative); } #endif // BPKG_PACKAGE_CONFIGURATION_HXX