aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/cc/module.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2/cc/module.cxx')
-rw-r--r--libbuild2/cc/module.cxx495
1 files changed, 327 insertions, 168 deletions
diff --git a/libbuild2/cc/module.cxx b/libbuild2/cc/module.cxx
index 8241a01..cf6c6e4 100644
--- a/libbuild2/cc/module.cxx
+++ b/libbuild2/cc/module.cxx
@@ -11,10 +11,7 @@
#include <libbuild2/bin/target.hxx>
-#include <libbuild2/cc/target.hxx> // pc*
-
#include <libbuild2/config/utility.hxx>
-#include <libbuild2/install/utility.hxx>
#include <libbuild2/cc/guess.hxx>
@@ -30,6 +27,8 @@ namespace build2
{
tracer trace (x, "guess_init");
+ context& ctx (rs.ctx);
+
bool cc_loaded (cast_false<bool> (rs["cc.core.guess.loaded"]));
// Adjust module priority (compiler). Also order cc module before us
@@ -41,7 +40,10 @@ namespace build2
config::save_module (rs, x, 250);
- auto& vp (rs.var_pool ());
+ // All the variables we enter are qualified so go straight for the
+ // public variable pool.
+ //
+ auto& vp (rs.var_pool (true /* public */));
// Must already exist.
//
@@ -55,7 +57,7 @@ namespace build2
// config.x
//
- strings mode;
+ strings omode; // Original mode.
{
// Normally we will have a persistent configuration and computing the
// default value every time will be a waste. So try without a default
@@ -139,22 +141,37 @@ namespace build2
fail << "invalid path '" << s << "' in " << config_x;
}
- mode.assign (++v.begin (), v.end ());
+ omode.assign (++v.begin (), v.end ());
// Save original path/mode in *.config.path/mode.
//
rs.assign (x_c_path) = xc;
- rs.assign (x_c_mode) = mode;
+ rs.assign (x_c_mode) = omode;
+
+ // Merge the configured mode options into user-specified (which must
+ // be done before loading the *.guess module).
+ //
+ // In particular, this ability to specify the compiler mode in a
+ // buildfile is useful in embedded development where the project may
+ // need to hardcode things like -target, -nostdinc, etc.
+ //
+ const strings& mode (cast<strings> (rs.assign (x_mode) += omode));
// Figure out which compiler we are dealing with, its target, etc.
//
// Note that we could allow guess() to modify mode to support
// imaginary options (such as /MACHINE for cl.exe). Though it's not
// clear what cc.mode would contain (original or modified). Note that
- // we are now folding *.std options into mode options.
+ // we are now adding *.std options into mode options.
+ //
+ // @@ But can't the language standard options alter things like search
+ // directories?
//
x_info = &build2::cc::guess (
- x, x_lang, move (xc),
+ ctx,
+ x, x_lang,
+ rs.root_extra->environment_checksum,
+ move (xc),
cast_null<string> (lookup_config (rs, config_x_id)),
cast_null<string> (lookup_config (rs, config_x_version)),
cast_null<string> (lookup_config (rs, config_x_target)),
@@ -178,7 +195,8 @@ namespace build2
if (config_sub)
{
- ct = run<string> (3,
+ ct = run<string> (ctx,
+ 3,
*config_sub,
xi.target.c_str (),
[] (string& l, bool) {return move (l);});
@@ -202,10 +220,24 @@ namespace build2
}
}
+ // Hash the environment (used for change detection).
+ //
+ // Note that for simplicity we use the combined checksum for both
+ // compilation and linking (which may compile, think LTO).
+ //
+ {
+ sha256 cs;
+ hash_environment (cs, xi.compiler_environment);
+ hash_environment (cs, xi.platform_environment);
+ env_checksum = cs.string ();
+ }
+
// Assign values to variables that describe the compiler.
//
- rs.assign (x_path) = process_path_ex (xi.path, x_name, xi.checksum);
- const strings& xm (cast<strings> (rs.assign (x_mode) = move (mode)));
+ // Note: x_mode is dealt with above.
+ //
+ rs.assign (x_path) = process_path_ex (
+ xi.path, x_name, xi.checksum, env_checksum);
rs.assign (x_id) = xi.id.string ();
rs.assign (x_id_type) = to_string (xi.id.type);
@@ -250,9 +282,9 @@ namespace build2
//
if (!cc_loaded)
{
- // Prepare configuration hints.
+ // Prepare configuration hints (pretend it belongs to root scope).
//
- variable_map h (rs.ctx);
+ variable_map h (rs);
// Note that all these variables have already been registered.
//
@@ -263,8 +295,8 @@ namespace build2
if (!xi.pattern.empty ())
h.assign ("config.cc.pattern") = xi.pattern;
- if (!xm.empty ())
- h.assign ("config.cc.mode") = xm;
+ if (!omode.empty ())
+ h.assign ("config.cc.mode") = move (omode);
h.assign (c_runtime) = xi.runtime;
h.assign (c_stdlib) = xi.c_stdlib;
@@ -335,6 +367,8 @@ namespace build2
# ifdef __APPLE__
static const dir_path a_usr_inc (
"/Library/Developer/CommandLineTools/SDKs/MacOSX*.sdk/usr/include");
+ static const dir_path a_usr_lib (
+ "/Library/Developer/CommandLineTools/SDKs/MacOSX*.sdk/usr/lib");
# endif
#endif
@@ -344,7 +378,7 @@ namespace build2
struct search_dirs
{
pair<dir_paths, size_t> lib;
- pair<dir_paths, size_t> inc;
+ pair<dir_paths, size_t> hdr;
};
static global_cache<search_dirs> dirs_cache;
@@ -357,6 +391,20 @@ namespace build2
const compiler_info& xi (*x_info);
const target_triplet& tt (cast<target_triplet> (rs[x_target]));
+ // Load cc.core.config.
+ //
+ if (!cast_false<bool> (rs["cc.core.config.loaded"]))
+ {
+ // Prepare configuration hints (pretend it belongs to root scope).
+ //
+ variable_map h (rs);
+
+ if (!xi.bin_pattern.empty ())
+ h.assign ("config.bin.pattern") = xi.bin_pattern;
+
+ init_module (rs, rs, "cc.core.config", loc, false, h);
+ }
+
// Configuration.
//
using config::lookup_config;
@@ -426,20 +474,114 @@ namespace build2
translate_std (xi, tt, rs, mode, v);
}
- // config.x.translatable_header
+ // config.x.internal.scope
+ //
+ // Note: save omitted.
+ //
+ // The effective internal_scope value is chosen based on the following
+ // priority list:
+ //
+ // 1. config.x.internal.scope
+ //
+ // 2. config.cc.internal.scope
+ //
+ // 3. effective value from bundle amalgamation
+ //
+ // 4. x.internal.scope
+ //
+ // 5. cc.internal.scope
+ //
+ // Note also that we only update x.internal.scope (and not cc.*) to
+ // reflect the effective value.
+ //
+ const string* iscope_str (nullptr);
+ {
+ if (lookup l = lookup_config (rs, config_x_internal_scope)) // 1
+ {
+ iscope_str = &cast<string> (l);
+
+ if (*iscope_str == "current")
+ fail << "'current' value in " << config_x_internal_scope;
+ }
+ else if (lookup l = rs["config.cc.internal.scope"]) // 2
+ {
+ iscope_str = &cast<string> (l);
+ }
+ else // 3
+ {
+ const scope& as (*rs.bundle_scope ());
+
+ if (as != rs)
+ {
+ // Only use the value if the corresponding module is loaded.
+ //
+ bool xl (cast_false<bool> (as[string (x) + ".config.loaded"]));
+ if (xl)
+ iscope_str = cast_null<string> (as[x_internal_scope]);
+
+ if (iscope_str == nullptr)
+ {
+ if (xl || cast_false<bool> (as["cc.core.config.loaded"]))
+ iscope_str = cast_null<string> (as["cc.internal.scope"]);
+ }
+
+ if (iscope_str != nullptr && *iscope_str == "current")
+ iscope_current = &as;
+ }
+ }
+
+ lookup l;
+ if (iscope_str == nullptr)
+ {
+ iscope_str = cast_null<string> (l = rs[x_internal_scope]); // 4
+
+ if (iscope_str == nullptr)
+ iscope_str = cast_null<string> (rs["cc.internal.scope"]); // 5
+ }
+
+ if (iscope_str != nullptr)
+ {
+ const string& s (*iscope_str);
+
+ // Assign effective.
+ //
+ if (!l)
+ rs.assign (x_internal_scope) = s;
+
+ if (s == "current")
+ {
+ iscope = internal_scope::current;
+
+ if (iscope_current == nullptr)
+ iscope_current = &rs;
+ }
+ else if (s == "base") iscope = internal_scope::base;
+ else if (s == "root") iscope = internal_scope::root;
+ else if (s == "bundle") iscope = internal_scope::bundle;
+ else if (s == "strong") iscope = internal_scope::strong;
+ else if (s == "weak") iscope = internal_scope::weak;
+ else if (s == "global")
+ ; // Nothing to translate;
+ else
+ fail << "invalid " << x_internal_scope << " value '" << s << "'";
+ }
+ }
+
+ // config.x.translate_include
//
// It's still fuzzy whether specifying (or maybe tweaking) this list in
// the configuration will be a common thing to do so for now we use
- // omitted. It's also probably too early to think whether we should have
- // the cc.* version and what the semantics should be.
+ // omitted.
//
- if (x_translatable_headers != nullptr)
+ if (x_translate_include != nullptr)
{
- lookup l (lookup_config (rs, *config_x_translatable_headers));
-
- // @@ MODHDR: if(modules) ?
- //
- rs.assign (x_translatable_headers) += cast_null<strings> (l);
+ if (lookup l = lookup_config (rs, *config_x_translate_include))
+ {
+ // @@ MODHDR: if(modules) ? Yes.
+ //
+ rs.assign (x_translate_include).prepend (
+ cast<translatable_headers> (l));
+ }
}
// Extract system header/library search paths from the compiler and
@@ -448,13 +590,13 @@ namespace build2
// Note that for now module search paths only come from compiler_info.
//
pair<dir_paths, size_t> lib_dirs;
- pair<dir_paths, size_t> inc_dirs;
+ pair<dir_paths, size_t> hdr_dirs;
const optional<pair<dir_paths, size_t>>& mod_dirs (xi.sys_mod_dirs);
- if (xi.sys_lib_dirs && xi.sys_inc_dirs)
+ if (xi.sys_lib_dirs && xi.sys_hdr_dirs)
{
lib_dirs = *xi.sys_lib_dirs;
- inc_dirs = *xi.sys_inc_dirs;
+ hdr_dirs = *xi.sys_hdr_dirs;
}
else
{
@@ -481,27 +623,27 @@ namespace build2
switch (xi.class_)
{
case compiler_class::gcc:
- lib_dirs = gcc_library_search_dirs (xi.path, rs);
+ lib_dirs = gcc_library_search_dirs (xi, rs);
break;
case compiler_class::msvc:
- lib_dirs = msvc_library_search_dirs (xi.path, rs);
+ lib_dirs = msvc_library_search_dirs (xi, rs);
break;
}
}
- if (xi.sys_inc_dirs)
- inc_dirs = *xi.sys_inc_dirs;
+ if (xi.sys_hdr_dirs)
+ hdr_dirs = *xi.sys_hdr_dirs;
else if (sd != nullptr)
- inc_dirs = sd->inc;
+ hdr_dirs = sd->hdr;
else
{
switch (xi.class_)
{
case compiler_class::gcc:
- inc_dirs = gcc_header_search_dirs (xi.path, rs);
+ hdr_dirs = gcc_header_search_dirs (xi, rs);
break;
case compiler_class::msvc:
- inc_dirs = msvc_header_search_dirs (xi.path, rs);
+ hdr_dirs = msvc_header_search_dirs (xi, rs);
break;
}
}
@@ -510,17 +652,17 @@ namespace build2
{
search_dirs sd;
if (!xi.sys_lib_dirs) sd.lib = lib_dirs;
- if (!xi.sys_inc_dirs) sd.inc = inc_dirs;
+ if (!xi.sys_hdr_dirs) sd.hdr = hdr_dirs;
dirs_cache.insert (move (key), move (sd));
}
}
sys_lib_dirs_mode = lib_dirs.second;
- sys_inc_dirs_mode = inc_dirs.second;
+ sys_hdr_dirs_mode = hdr_dirs.second;
sys_mod_dirs_mode = mod_dirs ? mod_dirs->second : 0;
- sys_lib_dirs_extra = lib_dirs.first.size ();
- sys_inc_dirs_extra = inc_dirs.first.size ();
+ sys_lib_dirs_extra = 0;
+ sys_hdr_dirs_extra = 0;
#ifndef _WIN32
// Add /usr/local/{include,lib}. We definitely shouldn't do this if we
@@ -536,11 +678,11 @@ namespace build2
// on the next invocation.
//
{
- auto& is (inc_dirs.first);
+ auto& hs (hdr_dirs.first);
auto& ls (lib_dirs.first);
- bool ui (find (is.begin (), is.end (), usr_inc) != is.end ());
- bool uli (find (is.begin (), is.end (), usr_loc_inc) != is.end ());
+ bool ui (find (hs.begin (), hs.end (), usr_inc) != hs.end ());
+ bool uli (find (hs.begin (), hs.end (), usr_loc_inc) != hs.end ());
#ifdef __APPLE__
// On Mac OS starting from 10.14 there is no longer /usr/include.
@@ -563,15 +705,28 @@ namespace build2
//
// Is Apple's /usr/include.
//
- if (!ui && !uli)
+ // Also, it appears neither Clang nor GCC report MacOSX*.sdk/usr/lib
+ // with -print-search-dirs but they do search in there. So we add it
+ // to our list if we see MacOSX*.sdk/usr/include.
+ //
+ auto aui (find_if (hs.begin (), hs.end (),
+ [] (const dir_path& d)
+ {
+ return path_match (d, a_usr_inc);
+ }));
+
+ if (aui != hs.end ())
{
- for (const dir_path& d: is)
+ if (!ui)
+ ui = true;
+
+ if (find_if (ls.begin (), ls.end (),
+ [] (const dir_path& d)
+ {
+ return path_match (d, a_usr_lib);
+ }) == ls.end ())
{
- if (path_match (d, a_usr_inc))
- {
- ui = true;
- break;
- }
+ ls.push_back (aui->directory () /= "lib");
}
}
#endif
@@ -579,18 +734,29 @@ namespace build2
{
bool ull (find (ls.begin (), ls.end (), usr_loc_lib) != ls.end ());
- // Many platforms don't search in /usr/local/lib by default (but do
- // for headers in /usr/local/include). So add it as the last option.
+ // Many platforms don't search in /usr/local/lib by default but do
+ // for headers in /usr/local/include.
+ //
+ // Note that customarily /usr/local/include is searched before
+ // /usr/include so we add /usr/local/lib before built-in entries
+ // (there isn't really a way to add it after since all we can do is
+ // specify it with -L).
//
if (!ull && exists (usr_loc_lib, true /* ignore_error */))
- ls.push_back (usr_loc_lib);
+ {
+ ls.insert (ls.begin () + sys_lib_dirs_mode, usr_loc_lib);
+ ++sys_lib_dirs_extra;
+ }
// FreeBSD is at least consistent: it searches in neither. Quoting
// its wiki: "FreeBSD can't even find libraries that it installed."
// So let's help it a bit.
//
if (!uli && exists (usr_loc_inc, true /* ignore_error */))
- is.push_back (usr_loc_inc);
+ {
+ hs.insert (hs.begin () + sys_hdr_dirs_mode, usr_loc_inc);
+ ++sys_hdr_dirs_extra;
+ }
}
}
#endif
@@ -632,7 +798,7 @@ namespace build2
if (xi.variant_version)
{
- dr << " variant: " << '\n'
+ dr << " variant:" << '\n'
<< " version " << xi.variant_version->string << '\n'
<< " major " << xi.variant_version->major << '\n'
<< " minor " << xi.variant_version->minor << '\n'
@@ -667,9 +833,19 @@ namespace build2
}
auto& mods (mod_dirs ? mod_dirs->first : dir_paths ());
- auto& incs (inc_dirs.first);
+ auto& incs (hdr_dirs.first);
auto& libs (lib_dirs.first);
+ if (verb >= 3 && iscope)
+ {
+ dr << "\n int scope ";
+
+ if (*iscope == internal_scope::current)
+ dr << iscope_current->out_path ();
+ else
+ dr << *iscope_str;
+ }
+
if (verb >= 3 && !mods.empty ())
{
dr << "\n mod dirs";
@@ -681,11 +857,14 @@ namespace build2
if (verb >= 3 && !incs.empty ())
{
- dr << "\n inc dirs";
+ dr << "\n hdr dirs";
for (size_t i (0); i != incs.size (); ++i)
{
- if (i == sys_inc_dirs_extra)
+ if ((sys_hdr_dirs_mode != 0 && i == sys_hdr_dirs_mode) ||
+ (sys_hdr_dirs_extra != 0 &&
+ i == sys_hdr_dirs_extra + sys_hdr_dirs_mode))
dr << "\n --";
+
dr << "\n " << incs[i];
}
}
@@ -695,31 +874,36 @@ namespace build2
dr << "\n lib dirs";
for (size_t i (0); i != libs.size (); ++i)
{
- if (i == sys_lib_dirs_extra)
+ if ((sys_lib_dirs_mode != 0 && i == sys_lib_dirs_mode) ||
+ (sys_lib_dirs_extra != 0 &&
+ i == sys_lib_dirs_extra + sys_lib_dirs_mode))
dr << "\n --";
+
dr << "\n " << libs[i];
}
}
}
rs.assign (x_sys_lib_dirs) = move (lib_dirs.first);
- rs.assign (x_sys_inc_dirs) = move (inc_dirs.first);
+ rs.assign (x_sys_hdr_dirs) = move (hdr_dirs.first);
- // Load cc.core.config.
- //
- if (!cast_false<bool> (rs["cc.core.config.loaded"]))
- {
- variable_map h (rs.ctx);
-
- if (!xi.bin_pattern.empty ())
- h.assign ("config.bin.pattern") = xi.bin_pattern;
-
- init_module (rs, rs, "cc.core.config", loc, false, h);
- }
+ config::save_environment (rs, xi.compiler_environment);
+ config::save_environment (rs, xi.platform_environment);
}
+ // Global cache of ad hoc importable headers.
+ //
+ // The key is a hash of the system header search directories
+ // (sys_hdr_dirs) where we search for the headers.
+ //
+ static map<string, importable_headers> importable_headers_cache;
+ static mutex importable_headers_mutex;
+
void module::
- init (scope& rs, const location& loc, const variable_map&)
+ init (scope& rs,
+ const location& loc,
+ const variable_map&,
+ const compiler_info& xi)
{
tracer trace (x, "init");
@@ -740,110 +924,82 @@ namespace build2
//
load_module (rs, rs, "cc.core", loc);
- // Process, sort, and cache (in this->xlate_hdr) translatable headers.
- // Keep the cache NULL if unused or empty.
- //
- // @@ MODHDR TODO: support exclusions entries (e.g., -<stdio.h>)?
+ // Search include translation headers and groups.
//
- if (modules && x_translatable_headers != nullptr)
+ if (modules)
{
- strings* ih (cast_null<strings> (rs.assign (x_translatable_headers)));
+ {
+ sha256 k;
+ for (const dir_path& d: sys_hdr_dirs)
+ k.append (d.string ());
+
+ mlock l (importable_headers_mutex);
+ importable_headers = &importable_headers_cache[k.string ()];
+ }
+
+ auto& hs (*importable_headers);
+
+ ulock ul (hs.mutex);
- if (ih != nullptr && !ih->empty ())
+ if (hs.group_map.find (header_group_std) == hs.group_map.end ())
+ guess_std_importable_headers (xi, sys_hdr_dirs, hs);
+
+ // Process x.translate_include.
+ //
+ const variable& var (*x_translate_include);
+ if (auto* v = cast_null<translatable_headers> (rs[var]))
{
- // Translate <>-style header names to absolute paths using the
- // compiler's include search paths. Otherwise complete and normalize
- // since when searching in this list we always use the absolute and
- // normalized header target path.
- //
- for (string& h: *ih)
+ for (const auto& p: *v)
{
- if (h.empty ())
- continue;
+ const string& k (p.first);
- path f;
- if (h.front () == '<' && h.back () == '>')
+ if (k.front () == '<' && k.back () == '>')
{
- h.pop_back ();
- h.erase (0, 1);
+ if (path_pattern (k))
+ {
+ size_t n (hs.insert_angle_pattern (sys_hdr_dirs, k));
- for (const dir_path& d: sys_inc_dirs)
+ l5 ([&]{trace << "pattern " << k << " searched to " << n
+ << " headers";});
+ }
+ else
{
- if (file_exists ((f = d, f /= h),
- true /* follow_symlinks */,
- true /* ignore_errors */))
- goto found;
+ // What should we do if not found? While we can fail, this
+ // could be too drastic if, for example, the header is
+ // "optional" and may or may not be present/used. So for now
+ // let's ignore (we could have also removed it from the map as
+ // an indication).
+ //
+ const auto* r (hs.insert_angle (sys_hdr_dirs, k));
+
+ l5 ([&]{trace << "header " << k << " searched to "
+ << (r ? r->first.string ().c_str () : "<none>");});
}
-
- // What should we do if not found? While we can fail, this could
- // be too drastic if, for example, the header is "optional" and
- // may or may not be present/used. So for now let's restore the
- // original form to aid debugging (it can't possibly match any
- // absolute path).
+ }
+ else if (path_traits::find_separator (k) == string::npos)
+ {
+ // Group name.
//
- h.insert (0, 1, '<');
- h.push_back ('>');
- continue;
-
- found:
- ; // Fall through.
+ if (k != header_group_all_importable &&
+ k != header_group_std_importable &&
+ k != header_group_all &&
+ k != header_group_std)
+ fail (loc) << "unknown header group '" << k << "' in " << var;
}
else
{
- f = path (move (h));
-
- if (f.relative ())
- f.complete ();
+ // Absolute and normalized header path.
+ //
+ if (!path_traits::absolute (k))
+ fail (loc) << "relative header path '" << k << "' in " << var;
}
-
- // @@ MODHDR: should we use the more elaborate but robust
- // normalize/realize scheme so the we get the same
- // path? Feels right.
- f.normalize ();
- h = move (f).string ();
}
-
- sort (ih->begin (), ih->end ());
- xlate_hdr = ih;
}
}
// Register target types and configure their "installability".
//
- bool install_loaded (cast_false<bool> (rs["install.loaded"]));
-
- {
- using namespace install;
-
- rs.insert_target_type (x_src);
-
- auto insert_hdr = [&rs, install_loaded] (const target_type& tt)
- {
- rs.insert_target_type (tt);
-
- // Install headers into install.include.
- //
- if (install_loaded)
- install_path (rs, tt, dir_path ("include"));
- };
-
- // Note: module (x_mod) is in x_hdr.
- //
- for (const target_type* const* ht (x_hdr); *ht != nullptr; ++ht)
- insert_hdr (**ht);
-
- // Also register the C header for C-derived languages.
- //
- if (*x_hdr != &h::static_type)
- insert_hdr (h::static_type);
-
- rs.insert_target_type<pc> ();
- rs.insert_target_type<pca> ();
- rs.insert_target_type<pcs> ();
-
- if (install_loaded)
- install_path<pc> (rs, dir_path ("pkgconfig"));
- }
+ load_module (rs, rs, (string (x) += ".types"), loc);
// Register rules.
//
@@ -941,34 +1097,37 @@ namespace build2
// them in case they depend on stuff that we need to install (see the
// install rule implementations for details).
//
- if (install_loaded)
+ if (cast_false<bool> (rs["install.loaded"]))
{
+ // Note: we rely quite heavily in these rule implementations that
+ // these are the only target types they are registered for.
+
const install_rule& ir (*this);
- r.insert<exe> (perform_install_id, x_install, ir);
- r.insert<exe> (perform_uninstall_id, x_uninstall, ir);
+ r.insert<exe> (perform_install_id, x_install, ir);
+ r.insert<exe> (perform_uninstall_id, x_install, ir);
- r.insert<liba> (perform_install_id, x_install, ir);
- r.insert<liba> (perform_uninstall_id, x_uninstall, ir);
+ r.insert<liba> (perform_install_id, x_install, ir);
+ r.insert<liba> (perform_uninstall_id, x_install, ir);
if (s)
{
- r.insert<libs> (perform_install_id, x_install, ir);
- r.insert<libs> (perform_uninstall_id, x_uninstall, ir);
+ r.insert<libs> (perform_install_id, x_install, ir);
+ r.insert<libs> (perform_uninstall_id, x_install, ir);
}
const libux_install_rule& lr (*this);
- r.insert<libue> (perform_install_id, x_install, lr);
- r.insert<libue> (perform_uninstall_id, x_uninstall, lr);
+ r.insert<libue> (perform_install_id, x_install, lr);
+ r.insert<libue> (perform_uninstall_id, x_install, lr);
- r.insert<libua> (perform_install_id, x_install, lr);
- r.insert<libua> (perform_uninstall_id, x_uninstall, lr);
+ r.insert<libua> (perform_install_id, x_install, lr);
+ r.insert<libua> (perform_uninstall_id, x_install, lr);
if (s)
{
- r.insert<libus> (perform_install_id, x_install, lr);
- r.insert<libus> (perform_uninstall_id, x_uninstall, lr);
+ r.insert<libus> (perform_install_id, x_install, lr);
+ r.insert<libus> (perform_uninstall_id, x_install, lr);
}
}
}