From 7b9eb752cad04aaadc4552d0f26d307b04af1869 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 7 Feb 2017 08:09:53 +0200 Subject: Pass const target& to recipes --- build2/cc/common | 24 ++++---- build2/cc/common.cxx | 26 ++++----- build2/cc/compile | 16 ++++-- build2/cc/compile.cxx | 67 ++++++++++++---------- build2/cc/install | 7 ++- build2/cc/install.cxx | 30 ++++++++-- build2/cc/link | 39 +++++++------ build2/cc/link.cxx | 122 +++++++++++++++++++++-------------------- build2/cc/msvc.cxx | 2 +- build2/cc/utility | 9 ++- build2/cc/utility.cxx | 31 +++++++++++ build2/cc/utility.ixx | 4 +- build2/cc/windows-manifest.cxx | 2 +- build2/cc/windows-rpath.cxx | 29 +++++----- 14 files changed, 244 insertions(+), 164 deletions(-) (limited to 'build2/cc') diff --git a/build2/cc/common b/build2/cc/common index 06df4c3..860913e 100644 --- a/build2/cc/common +++ b/build2/cc/common @@ -184,18 +184,16 @@ namespace build2 // public: void - process_libraries (const scope&, - lorder, - const dir_paths&, - file&, - bool, - const function&, - const function&, - const function&, - bool = false) const; + process_libraries ( + const scope&, + lorder, + const dir_paths&, + const file&, + bool, + const function&, + const function&, + const function&, + bool = false) const; target* search_library (const dir_paths& sysd, @@ -209,7 +207,7 @@ namespace build2 } private: - file& + const file& resolve_library (const scope&, name, lorder, diff --git a/build2/cc/common.cxx b/build2/cc/common.cxx index e7b26a1..62a4ab2 100644 --- a/build2/cc/common.cxx +++ b/build2/cc/common.cxx @@ -49,14 +49,14 @@ namespace build2 const scope& top_bs, lorder top_lo, const dir_paths& top_sysd, - file& l, + const file& l, bool la, - const function& proc_impl, // Implementation? - const function& proc_lib, // True if system library. - const function& proc_opt, // *.export. @@ -213,10 +213,10 @@ namespace build2 // if (impl && !c_e_libs.defined () && !x_e_libs.defined ()) { - for (target* p: l.prerequisite_targets) + for (const target* p: l.prerequisite_targets) { bool a; - file* f; + const file* f; if ((a = (f = p->is_a ()) != nullptr) || (f = p->is_a ()) != nullptr) @@ -287,7 +287,7 @@ namespace build2 if (sysd == nullptr) find_sysd (); if (!lo) find_lo (); - file& t (resolve_library (bs, n, *lo, *sysd, usrd)); + const file& t (resolve_library (bs, n, *lo, *sysd, usrd)); if (proc_lib) { @@ -385,7 +385,7 @@ namespace build2 // will select exactly the same target as the library's matched rule and // that's the only way to guarantee it will be up-to-date. // - file& common:: + const file& common:: resolve_library (const scope& s, name n, lorder lo, @@ -395,7 +395,7 @@ namespace build2 if (n.type != "lib" && n.type != "liba" && n.type != "libs") fail << "target name " << n << " is not a library"; - target* xt (nullptr); + const target* xt (nullptr); if (n.dir.absolute () && !n.qualified ()) { @@ -422,12 +422,12 @@ namespace build2 // dir_path out; prerequisite_key pk {n.proj, {tt, &n.dir, &out, &n.value, ext}, &s}; - xt = search_library (sysd, usrd, pk); + xt = search_library (sysd, usrd, pk); //@@ TM const if (xt == nullptr) { if (n.qualified ()) - xt = &import (pk); + xt = &import (pk); //@@ TM const else fail << "unable to find library " << pk; } @@ -435,10 +435,10 @@ namespace build2 // If this is lib{}, pick appropriate member. // - if (lib* l = xt->is_a ()) + if (const lib* l = xt->is_a ()) xt = &link_member (*l, lo); // Pick liba{} or libs{}. - return static_cast (*xt); + return static_cast (*xt); } // Note that pk's scope should not be NULL (even if dir is absolute). If diff --git a/build2/cc/compile b/build2/cc/compile index b6fc7d6..63ce286 100644 --- a/build2/cc/compile +++ b/build2/cc/compile @@ -33,17 +33,23 @@ namespace build2 apply (slock&, action, target&) const override; target_state - perform_update (action, target&) const; + perform_update (action, const target&) const; target_state - perform_clean (action, target&) const; + perform_clean (action, const target&) const; private: void - append_lib_options (const scope&, cstrings&, target&, lorder) const; + append_lib_options (const scope&, + cstrings&, + const target&, + lorder) const; void - hash_lib_options (const scope&, sha256&, target&, lorder) const; + hash_lib_options (const scope&, + sha256&, + const target&, + lorder) const; // Mapping of include prefixes (e.g., foo in ) for auto- // generated headers to directories where they will be generated. @@ -58,7 +64,7 @@ namespace build2 using prefix_map = butl::dir_path_map; void - append_prefixes (prefix_map&, target&, const variable&) const; + append_prefixes (prefix_map&, const target&, const variable&) const; void append_lib_prefixes (const scope&, prefix_map&, target&, lorder) const; diff --git a/build2/cc/compile.cxx b/build2/cc/compile.cxx index 66ea9bd..98d1218 100644 --- a/build2/cc/compile.cxx +++ b/build2/cc/compile.cxx @@ -78,10 +78,11 @@ namespace build2 void compile:: append_lib_options (const scope& bs, cstrings& args, - target& t, + const target& t, lorder lo) const { - auto opt = [&args, this] (file& l, const string& t, bool com, bool exp) + auto opt = [&args, this] ( + const file& l, const string& t, bool com, bool exp) { // Note that in our model *.export.poptions are always "interface", // even if set on liba{}/libs{}, unlike loptions. @@ -98,31 +99,35 @@ namespace build2 // In case we don't have the "small function object" optimization. // - const function optf (opt); + const function optf (opt); // Note that here we don't need to see group members (see apply()). // - for (prerequisite& p: group_prerequisites (t)) + for (const prerequisite& p: const_group_prerequisites (t)) { - target* pt (p.target); // Already searched and matched. + const target* pt (p.target); // Already searched and matched. bool a; - if (lib* l = pt->is_a ()) + if (const lib* l = pt->is_a ()) a = (pt = &link_member (*l, lo))->is_a (); else if (!(a = pt->is_a ()) && !pt->is_a ()) continue; process_libraries (bs, lo, sys_lib_dirs, - static_cast (*pt), a, + static_cast (*pt), a, nullptr, nullptr, optf); } } void compile:: - hash_lib_options (const scope& bs, sha256& cs, target& t, lorder lo) const + hash_lib_options (const scope& bs, + sha256& cs, + const target& t, + lorder lo) const { - auto opt = [&cs, this] (file& l, const string& t, bool com, bool exp) + auto opt = [&cs, this] ( + const file& l, const string& t, bool com, bool exp) { assert (exp); @@ -136,21 +141,21 @@ namespace build2 // In case we don't have the "small function object" optimization. // - const function optf (opt); + const function optf (opt); - for (prerequisite& p: group_prerequisites (t)) + for (const prerequisite& p: const_group_prerequisites (t)) { - target* pt (p.target); // Already searched and matched. + const target* pt (p.target); // Already searched and matched. bool a; - if (lib* l = pt->is_a ()) + if (const lib* l = pt->is_a ()) a = (pt = &link_member (*l, lo))->is_a (); else if (!(a = pt->is_a ()) && !pt->is_a ()) continue; process_libraries (bs, lo, sys_lib_dirs, - static_cast (*pt), a, + static_cast (*pt), a, nullptr, nullptr, optf); } } @@ -164,7 +169,8 @@ namespace build2 target& t, lorder lo) const { - auto opt = [&m, this] (file& l, const string& t, bool com, bool exp) + auto opt = [&m, this] ( + const file& l, const string& t, bool com, bool exp) { assert (exp); @@ -178,7 +184,7 @@ namespace build2 // In case we don't have the "small function object" optimization. // - const function optf (opt); + const function optf (opt); for (prerequisite& p: group_prerequisites (t)) { @@ -192,7 +198,7 @@ namespace build2 continue; process_libraries (bs, lo, sys_lib_dirs, - static_cast (*pt), a, + static_cast (*pt), a, nullptr, nullptr, optf); } } @@ -399,12 +405,15 @@ namespace build2 switch (a) { - case perform_update_id: - return [this] (action a, target& t) {return perform_update (a, t);}; - case perform_clean_id: - return [this] (action a, target& t) {return perform_clean (a, t);}; - default: - return noop_recipe; // Configure update. + case perform_update_id: return [this] (action a, const target& t) + { + return perform_update (a, t); + }; + case perform_clean_id: return [this] (action a, const target& t) + { + return perform_clean (a, t); + }; + default: return noop_recipe; // Configure update. } } @@ -440,7 +449,7 @@ namespace build2 } void compile:: - append_prefixes (prefix_map& m, target& t, const variable& var) const + append_prefixes (prefix_map& m, const target& t, const variable& var) const { tracer trace (x, "append_prefixes"); @@ -1394,15 +1403,15 @@ namespace build2 msvc_filter_cl (ifdstream&, const path& src); target_state compile:: - perform_update (action a, target& xt) const + perform_update (action a, const target& xt) const { - file& t (static_cast (xt)); + const file& t (static_cast (xt)); // Update prerequisites and determine if any relevant ones render us // out-of-date. Note that currently we treat all the prerequisites // as potentially affecting the result (for simplicity/performance). // - file* s; + const file* s; { auto p (execute_prerequisites (x_src, a, t, t.mtime ())); @@ -1621,9 +1630,9 @@ namespace build2 } target_state compile:: - perform_clean (action a, target& xt) const + perform_clean (action a, const target& xt) const { - file& t (static_cast (xt)); + const file& t (static_cast (xt)); if (cid == "msvc") return clean_extra (a, t, {".d", ".idb", ".pdb"}); diff --git a/build2/cc/install b/build2/cc/install index ff7af4d..f676d72 100644 --- a/build2/cc/install +++ b/build2/cc/install @@ -30,11 +30,14 @@ namespace build2 virtual match_result match (slock&, action, target&, const string&) const override; + virtual recipe + apply (slock&, action, target&) const override; + virtual void - install_extra (file&, const install_dir&) const override; + install_extra (const file&, const install_dir&) const override; virtual bool - uninstall_extra (file&, const install_dir&) const override; + uninstall_extra (const file&, const install_dir&) const override; private: const link& link_; diff --git a/build2/cc/install.cxx b/build2/cc/install.cxx index 074654b..f022a92 100644 --- a/build2/cc/install.cxx +++ b/build2/cc/install.cxx @@ -66,17 +66,35 @@ namespace build2 // ones building this target. So first run link's match(). // match_result r (link_.match (ml, a, t, hint)); - return r ? install::file_rule::match (ml, a, t, "") : r; + return r ? file_rule::match (ml, a, t, "") : r; + } + + recipe install:: + apply (slock& s, action a, target& t) const + { + recipe r (file_rule::apply (s, a, t)); + + // Derive shared library paths and cache them in the target's aux + // storage if we are (un)installing (used in *_extra() functions below). + // + if (a.operation () == install_id || a.operation () == uninstall_id) + { + file* f; + if ((f = t.is_a ()) != nullptr && tclass != "windows") + t.data (link_.derive_libs_paths (*f)); + } + + return r; } void install:: - install_extra (file& t, const install_dir& id) const + install_extra (const file& t, const install_dir& id) const { if (t.is_a () && tclass != "windows") { // Here we may have a bunch of symlinks that we need to install. // - link::libs_paths lp (link_.derive_libs_paths (t)); + auto& lp (t.data ()); auto ln = [&id, this] (const path& f, const path& l) { @@ -87,7 +105,7 @@ namespace build2 const path& so (lp.soname); const path& in (lp.interm); - const path* f (lp.real); + const path* f (&lp.real); if (!in.empty ()) {ln (*f, in); f = ∈} if (!so.empty ()) {ln (*f, so); f = &so;} @@ -96,7 +114,7 @@ namespace build2 } bool install:: - uninstall_extra (file& t, const install_dir& id) const + uninstall_extra (const file& t, const install_dir& id) const { bool r (false); @@ -104,7 +122,7 @@ namespace build2 { // Here we may have a bunch of symlinks that we need to uninstall. // - link::libs_paths lp (link_.derive_libs_paths (t)); + auto& lp (t.data ()); auto rm = [&id, this] (const path& l) { diff --git a/build2/cc/link b/build2/cc/link index d1b0e7a..c787015 100644 --- a/build2/cc/link +++ b/build2/cc/link @@ -31,10 +31,10 @@ namespace build2 apply (slock&, action, target&) const override; target_state - perform_update (action, target&) const; + perform_update (action, const target&) const; target_state - perform_clean (action, target&) const; + perform_clean (action, const target&) const; private: friend class install; @@ -50,19 +50,16 @@ namespace build2 // The libs{} path is always the real path. On Windows the link path // is the import library. // - // @@ TODO: change real to reference, make other const once cache the - // object. - // - path link; // What we link: libfoo.so - path soname; // SONAME: libfoo-1.so, libfoo.so.1 - path interm; // Intermediate: libfoo.so.1.2 - const path* real; // Real: libfoo.so.1.2.3 + const path link; // What we link: libfoo.so + const path soname; // SONAME: libfoo-1.so, libfoo.so.1 + const path interm; // Intermediate: libfoo.so.1.2 + const path& real; // Real: libfoo.so.1.2.3 inline const path& effect_link () const {return link.empty () ? effect_soname () : link;} inline const path& - effect_soname () const {return soname.empty () ? *real : soname;} + effect_soname () const {return soname.empty () ? real : soname;} }; libs_paths @@ -71,13 +68,21 @@ namespace build2 // Library handling. // void - append_libraries (strings&, file&, bool, const scope&, lorder) const; + append_libraries (strings&, + const file&, bool, + const scope&, lorder) const; void - hash_libraries (sha256&, file&, bool, const scope&, lorder) const; + hash_libraries (sha256&, + const file&, bool, + const scope&, lorder) const; void - rpath_libraries (strings&, target&, const scope&, lorder, bool) const; + rpath_libraries (strings&, + const target&, + const scope&, + lorder, + bool) const; // Windows rpath emulation (windows-rpath.cxx). // @@ -93,13 +98,13 @@ namespace build2 using windows_dlls = std::set; timestamp - windows_rpath_timestamp (file&, const scope&, lorder) const; + windows_rpath_timestamp (const file&, const scope&, lorder) const; windows_dlls - windows_rpath_dlls (file&, const scope&, lorder) const; + windows_rpath_dlls (const file&, const scope&, lorder) const; void - windows_rpath_assembly (file&, const scope&, lorder, + windows_rpath_assembly (const file&, const scope&, lorder, const string&, timestamp, bool) const; @@ -107,7 +112,7 @@ namespace build2 // Windows-specific (windows-manifest.cxx). // path - windows_manifest (file&, bool rpath_assembly) const; + windows_manifest (const file&, bool rpath_assembly) const; private: const string rule_id; diff --git a/build2/cc/link.cxx b/build2/cc/link.cxx index 83a7c0d..7c946aa 100644 --- a/build2/cc/link.cxx +++ b/build2/cc/link.cxx @@ -266,7 +266,6 @@ namespace build2 // Now determine the paths. // path lk, so, in; - const path* re (nullptr); // We start with the basic path. // @@ -310,7 +309,7 @@ namespace build2 if (!v.empty ()) b += v; - re = &ls.derive_path (move (b)); + const path& re (ls.derive_path (move (b))); return libs_paths {move (lk), move (so), move (in), re}; } @@ -318,6 +317,9 @@ namespace build2 recipe link:: apply (slock& ml, action a, target& xt) const { + static_assert (sizeof (link::libs_paths) <= target::data_size, + "insufficient space"); + tracer trace (x, "link::apply"); file& t (static_cast (xt)); @@ -388,7 +390,7 @@ namespace build2 if (tclass == "windows") add_adhoc (t, "libi"); - derive_libs_paths (t); + t.data (derive_libs_paths (t)); // Cache in target. break; } } @@ -645,18 +647,21 @@ namespace build2 switch (a) { - case perform_update_id: - return [this] (action a, target& t) {return perform_update (a, t);}; - case perform_clean_id: - return [this] (action a, target& t) {return perform_clean (a, t);}; - default: - return noop_recipe; // Configure update. + case perform_update_id: return [this] (action a, const target& t) + { + return perform_update (a, t); + }; + case perform_clean_id: return [this] (action a, const target& t) + { + return perform_clean (a, t); + }; + default: return noop_recipe; // Configure update. } } void link:: append_libraries (strings& args, - file& l, bool la, + const file& l, bool la, const scope& bs, lorder lo) const { // Note: lack of the "small function object" optimization will really @@ -664,9 +669,9 @@ namespace build2 // bool win (tclass == "windows"); - auto imp = [] (file&, bool la) {return la;}; + auto imp = [] (const file&, bool la) {return la;}; - auto lib = [&args, win] (file* f, const string& p, bool) + auto lib = [&args, win] (const file* f, const string& p, bool) { if (f != nullptr) { @@ -675,7 +680,7 @@ namespace build2 // (see search_library() for details). // if (win && f->member != nullptr && f->is_a ()) - f = static_cast (f->member); + f = static_cast (f->member.get ()); args.push_back (relative (f->path ()).string ()); } @@ -683,11 +688,12 @@ namespace build2 args.push_back (p); }; - auto opt = [&args, this] (file& l, const string& t, bool com, bool exp) + auto opt = [&args, this] ( + const file& l, const string& t, bool com, bool exp) { // If we need an interface value, then use the group (lib{}). // - if (target* g = exp && l.is_a () ? l.group : &l) + if (const target* g = exp && l.is_a () ? l.group : &l) { const variable& var ( com @@ -705,16 +711,14 @@ namespace build2 void link:: hash_libraries (sha256& cs, - file& l, - bool la, - const scope& bs, - lorder lo) const + const file& l, bool la, + const scope& bs, lorder lo) const { bool win (tclass == "windows"); - auto imp = [] (file&, bool la) {return la;}; + auto imp = [] (const file&, bool la) {return la;}; - auto lib = [&cs, win] (file* f, const string& p, bool) + auto lib = [&cs, win] (const file* f, const string& p, bool) { if (f != nullptr) { @@ -723,7 +727,7 @@ namespace build2 // (see search_library() for details). // if (win && f->member != nullptr && f->is_a ()) - f = static_cast (f->member); + f = static_cast (f->member.get ()); cs.append (f->path ().string ()); } @@ -731,9 +735,10 @@ namespace build2 cs.append (p); }; - auto opt = [&cs, this] (file& l, const string& t, bool com, bool exp) + auto opt = [&cs, this] ( + const file& l, const string& t, bool com, bool exp) { - if (target* g = exp && l.is_a () ? l.group : &l) + if (const target* g = exp && l.is_a () ? l.group : &l) { const variable& var ( com @@ -751,7 +756,7 @@ namespace build2 void link:: rpath_libraries (strings& args, - target& t, + const target& t, const scope& bs, lorder lo, bool for_install) const @@ -765,7 +770,7 @@ namespace build2 return; } - auto imp = [for_install] (file&, bool la) + auto imp = [for_install] (const file&, bool la) { // If we are not installing, then we only need to rpath interface // libraries (they will include rpath's for their implementations). @@ -791,7 +796,7 @@ namespace build2 bool for_install; } d {args, for_install}; - auto lib = [&d, this] (file* l, const string& f, bool sys) + auto lib = [&d, this] (const file* l, const string& f, bool sys) { // We don't rpath system libraries. Why, you may ask? There are many // good reasons and I have them written on an napkin somewhere... @@ -845,13 +850,13 @@ namespace build2 // In case we don't have the "small function object" optimization. // - const function impf (imp); - const function libf (lib); + const function impf (imp); + const function libf (lib); - for (target* pt: t.prerequisite_targets) + for (const target* pt: t.prerequisite_targets) { - file* f; - liba* a; + const file* f; + const liba* a; if ((f = a = pt->is_a ()) || (f = pt->is_a ())) @@ -884,14 +889,14 @@ namespace build2 msvc_machine (const string& cpu); // msvc.cxx target_state link:: - perform_update (action a, target& xt) const + perform_update (action a, const target& xt) const { tracer trace (x, "link::perform_update"); auto oop (a.outer_operation ()); bool for_install (oop == install_id || oop == uninstall_id); - file& t (static_cast (xt)); + const file& t (static_cast (xt)); const scope& bs (t.base_scope ()); const scope& rs (*bs.root_scope ()); @@ -1071,10 +1076,6 @@ namespace build2 // cstrings args {nullptr}; // Reserve one for config.bin.ar/config.x. - libs_paths paths; - if (lt == otype::s) - paths = derive_libs_paths (t); - // Storage. // string soname1, soname2; @@ -1127,6 +1128,7 @@ namespace build2 // if (lt == otype::s) { + const libs_paths& paths (t.data ()); const string& leaf (paths.effect_soname ().leaf ().string ()); if (tclass == "macosx") @@ -1195,11 +1197,11 @@ namespace build2 { sha256 cs; - for (target* pt: t.prerequisite_targets) + for (const target* pt: t.prerequisite_targets) { - file* f; - liba* a (nullptr); - libs* s (nullptr); + const file* f; + const liba* a (nullptr); + const libs* s (nullptr); if ((f = pt->is_a ()) || (f = pt->is_a ()) || @@ -1367,8 +1369,8 @@ namespace build2 // derived from the import library by changing the extension. // Lucky for us -- there is no option to name it. // - auto imp (static_cast (t.member)); - out2 = "/IMPLIB:" + relative (imp->path ()).string (); + auto& imp (static_cast (*t.member)); + out2 = "/IMPLIB:" + relative (imp.path ()).string (); args.push_back (out2.c_str ()); } @@ -1377,9 +1379,10 @@ namespace build2 // if (find_option ("/DEBUG", args, true)) { - auto pdb (static_cast ( - lt == otype::e ? t.member : t.member->member)); - out1 = "/PDB:" + relative (pdb->path ()).string (); + auto& pdb ( + static_cast ( + lt == otype::e ? *t.member : *t.member->member)); + out1 = "/PDB:" + relative (pdb.path ()).string (); args.push_back (out1.c_str ()); } @@ -1412,8 +1415,8 @@ namespace build2 // On Windows libs{} is the DLL and its first ad hoc group // member is the import library. // - auto imp (static_cast (t.member)); - out = "-Wl,--out-implib=" + relative (imp->path ()).string (); + auto& imp (static_cast (*t.member)); + out = "-Wl,--out-implib=" + relative (imp.path ()).string (); args.push_back (out.c_str ()); } } @@ -1428,11 +1431,11 @@ namespace build2 args[0] = ld->recall_string (); - for (target* pt: t.prerequisite_targets) + for (const target* pt: t.prerequisite_targets) { - file* f; - liba* a (nullptr); - libs* s (nullptr); + const file* f; + const liba* a (nullptr); + const libs* s (nullptr); if ((f = pt->is_a ()) || (f = pt->is_a ()) || @@ -1600,11 +1603,13 @@ namespace build2 } }; + const libs_paths& paths (t.data ()); + const path& lk (paths.link); const path& so (paths.soname); const path& in (paths.interm); - const path* f (paths.real); + const path* f (&paths.real); if (!in.empty ()) {ln (f->leaf (), in); f = ∈} if (!so.empty ()) {ln (f->leaf (), so); f = &so;} @@ -1622,11 +1627,9 @@ namespace build2 } target_state link:: - perform_clean (action a, target& xt) const + perform_clean (action a, const target& xt) const { - file& t (static_cast (xt)); - - libs_paths paths; + const file& t (static_cast (xt)); switch (link_type (t)) { @@ -1666,7 +1669,8 @@ namespace build2 // Here we can have a bunch of symlinks that we need to remove. If // the paths are empty, then they will be ignored. // - paths = derive_libs_paths (t); + const libs_paths& paths (t.data ()); + return clean_extra (a, t, {".d", paths.link.string ().c_str (), paths.soname.string ().c_str (), diff --git a/build2/cc/msvc.cxx b/build2/cc/msvc.cxx index 4ac82a0..fc2979c 100644 --- a/build2/cc/msvc.cxx +++ b/build2/cc/msvc.cxx @@ -69,7 +69,7 @@ namespace build2 // if (lt == otype::s && l.compare (0, 3, " ") == 0) { - path imp (static_cast (t.member)->path ().leaf ()); + path imp (static_cast (*t.member).path ().leaf ()); if (l.find (imp.string ()) != string::npos && l.find (imp.base ().string () + ".exp") != string::npos) diff --git a/build2/cc/utility b/build2/cc/utility index 050b645..bb7ed34 100644 --- a/build2/cc/utility +++ b/build2/cc/utility @@ -22,10 +22,10 @@ namespace build2 // Compile/link output type. // otype - compile_type (target&); + compile_type (const target&); otype - link_type (target&); + link_type (const target&); // Library link order. // @@ -41,8 +41,13 @@ namespace build2 // Given the link order return the library member (liba or libs) to link. // + // Note that the const version assumes you have already called non-const. + // target& link_member (bin::lib&, lorder); + + const target& + link_member (const bin::lib&, lorder); } } diff --git a/build2/cc/utility.cxx b/build2/cc/utility.cxx index 5c5d1fe..4ccdcaf 100644 --- a/build2/cc/utility.cxx +++ b/build2/cc/utility.cxx @@ -38,6 +38,37 @@ namespace build2 : v.size () > 1 && v[1] == "shared" ? lorder::a_s : lorder::a; } + const target& + link_member (const bin::lib& l, lorder lo) + { + bool ls (true); + const string& at (cast (l["bin.lib"])); // Available members. + + switch (lo) + { + case lorder::a: + case lorder::a_s: + ls = false; // Fall through. + case lorder::s: + case lorder::s_a: + { + if (ls ? at == "static" : at == "shared") + { + if (lo == lorder::a_s || lo == lorder::s_a) + ls = !ls; + else + assert (false); + } + } + } + + target* r (ls ? static_cast (l.s) : l.a); + + assert (r != nullptr); + + return *r; + } + target& link_member (bin::lib& l, lorder lo) { diff --git a/build2/cc/utility.ixx b/build2/cc/utility.ixx index 8695a8e..bc9cd05 100644 --- a/build2/cc/utility.ixx +++ b/build2/cc/utility.ixx @@ -7,7 +7,7 @@ namespace build2 namespace cc { inline otype - compile_type (target& t) + compile_type (const target& t) { return t.is_a () ? otype::e : @@ -16,7 +16,7 @@ namespace build2 } inline otype - link_type (target& t) + link_type (const target& t) { return t.is_a () ? otype::e : diff --git a/build2/cc/windows-manifest.cxx b/build2/cc/windows-manifest.cxx index b0b0feb..0e38e7d 100644 --- a/build2/cc/windows-manifest.cxx +++ b/build2/cc/windows-manifest.cxx @@ -39,7 +39,7 @@ namespace build2 // file corresponding to the exe{} target. Return the manifest file path. // path link:: - windows_manifest (file& t, bool rpath_assembly) const + windows_manifest (const file& t, bool rpath_assembly) const { tracer trace (x, "windows_manifest"); diff --git a/build2/cc/windows-rpath.cxx b/build2/cc/windows-rpath.cxx index 00911d4..94b1145 100644 --- a/build2/cc/windows-rpath.cxx +++ b/build2/cc/windows-rpath.cxx @@ -46,16 +46,16 @@ namespace build2 // adding to the assembly or timestamp_nonexistent if there aren't any. // timestamp link:: - windows_rpath_timestamp (file& t, const scope& bs, lorder lo) const + windows_rpath_timestamp (const file& t, const scope& bs, lorder lo) const { timestamp r (timestamp_nonexistent); // We need to collect all the DLLs, so go into implementation of both // shared and static (in case they depend on shared). // - auto imp = [] (file&, bool) {return true;}; + auto imp = [] (const file&, bool) {return true;}; - auto lib = [&r] (file* l, const string& f, bool sys) + auto lib = [&r] (const file* l, const string& f, bool sys) { // We don't rpath system libraries. // @@ -97,10 +97,10 @@ namespace build2 r = t; }; - for (target* pt: t.prerequisite_targets) + for (const target* pt: t.prerequisite_targets) { - file* f; - liba* a; + const file* f; + const liba* a; if ((f = a = pt->is_a ()) || (f = pt->is_a ())) @@ -116,15 +116,15 @@ namespace build2 // duplicates). // auto link:: - windows_rpath_dlls (file& t, + windows_rpath_dlls (const file& t, const scope& bs, lorder lo) const -> windows_dlls { windows_dlls r; - auto imp = [] (file&, bool) {return true;}; + auto imp = [] (const file&, bool) {return true;}; - auto lib = [&r] (file* l, const string& f, bool sys) + auto lib = [&r] (const file* l, const string& f, bool sys) { if (sys) return; @@ -137,7 +137,8 @@ namespace build2 // const string* pdb ( l->member != nullptr && l->member->member != nullptr - ? &static_cast (*l->member->member).path ().string () + ? &static_cast ( + *l->member->member).path ().string () : nullptr); r.insert (windows_dll {f, pdb, string ()}); @@ -178,10 +179,10 @@ namespace build2 } }; - for (target* pt: t.prerequisite_targets) + for (const target* pt: t.prerequisite_targets) { - file* f; - liba* a; + const file* f; + const liba* a; if ((f = a = pt->is_a ()) || (f = pt->is_a ())) @@ -205,7 +206,7 @@ namespace build2 // manifest file. // void link:: - windows_rpath_assembly (file& t, + windows_rpath_assembly (const file& t, const scope& bs, lorder lo, const string& tcpu, -- cgit v1.1