aboutsummaryrefslogtreecommitdiff
path: root/build2/cc
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-02-07 08:09:53 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-02-13 12:42:42 +0200
commit7b9eb752cad04aaadc4552d0f26d307b04af1869 (patch)
treed19cdb450ddec384ec41d9129f8d4afecc14acb7 /build2/cc
parentbe773edfa2c8f8f3230509bbd713542d20fbb37e (diff)
Pass const target& to recipes
Diffstat (limited to 'build2/cc')
-rw-r--r--build2/cc/common24
-rw-r--r--build2/cc/common.cxx26
-rw-r--r--build2/cc/compile16
-rw-r--r--build2/cc/compile.cxx67
-rw-r--r--build2/cc/install7
-rw-r--r--build2/cc/install.cxx30
-rw-r--r--build2/cc/link39
-rw-r--r--build2/cc/link.cxx122
-rw-r--r--build2/cc/msvc.cxx2
-rw-r--r--build2/cc/utility9
-rw-r--r--build2/cc/utility.cxx31
-rw-r--r--build2/cc/utility.ixx4
-rw-r--r--build2/cc/windows-manifest.cxx2
-rw-r--r--build2/cc/windows-rpath.cxx29
14 files changed, 244 insertions, 164 deletions
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<bool (file&, bool)>&,
- const function<void (file*, const string&, bool)>&,
- const function<void (file&,
- const string&,
- bool,
- bool)>&,
- bool = false) const;
+ process_libraries (
+ const scope&,
+ lorder,
+ const dir_paths&,
+ const file&,
+ bool,
+ const function<bool (const file&, bool)>&,
+ const function<void (const file*, const string&, bool)>&,
+ const function<void (const file&, const string&, bool, bool)>&,
+ 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<bool (file&,
+ const function<bool (const file&,
bool la)>& proc_impl, // Implementation?
- const function<void (file*, // Can be NULL.
+ const function<void (const file*, // Can be NULL.
const string& path, // Library path.
bool sys)>& proc_lib, // True if system library.
- const function<void (file&,
+ const function<void (const file&,
const string& type, // cc.type
bool com, // cc. or x.
bool exp)>& 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<liba> ()) != nullptr)
|| (f = p->is_a<libs> ()) != 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<lib> ())
+ if (const lib* l = xt->is_a<lib> ())
xt = &link_member (*l, lo); // Pick liba{} or libs{}.
- return static_cast<file&> (*xt);
+ return static_cast<const file&> (*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 <foo/bar>) for auto-
// generated headers to directories where they will be generated.
@@ -58,7 +64,7 @@ namespace build2
using prefix_map = butl::dir_path_map<dir_path>;
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<void (file&, const string&, bool, bool)> optf (opt);
+ const function<void (const file&, const string&, bool, bool)> 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<lib> ())
+ if (const lib* l = pt->is_a<lib> ())
a = (pt = &link_member (*l, lo))->is_a<liba> ();
else if (!(a = pt->is_a<liba> ()) && !pt->is_a<libs> ())
continue;
process_libraries (bs, lo, sys_lib_dirs,
- static_cast<file&> (*pt), a,
+ static_cast<const file&> (*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<void (file&, const string&, bool, bool)> optf (opt);
+ const function<void (const file&, const string&, bool, bool)> 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<lib> ())
+ if (const lib* l = pt->is_a<lib> ())
a = (pt = &link_member (*l, lo))->is_a<liba> ();
else if (!(a = pt->is_a<liba> ()) && !pt->is_a<libs> ())
continue;
process_libraries (bs, lo, sys_lib_dirs,
- static_cast<file&> (*pt), a,
+ static_cast<const file&> (*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<void (file&, const string&, bool, bool)> optf (opt);
+ const function<void (const file&, const string&, bool, bool)> optf (opt);
for (prerequisite& p: group_prerequisites (t))
{
@@ -192,7 +198,7 @@ namespace build2
continue;
process_libraries (bs, lo, sys_lib_dirs,
- static_cast<file&> (*pt), a,
+ static_cast<const file&> (*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<file&> (xt));
+ const file& t (static_cast<const file&> (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<file> (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<file&> (xt));
+ const file& t (static_cast<const file&> (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<libs> ()) != 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<libs> () && 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<link::libs_paths> ());
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 = &in;}
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<link::libs_paths> ());
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<windows_dll>;
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<file&> (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<libs> ())
- f = static_cast<file*> (f->member);
+ f = static_cast<const file*> (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<libs> () ? l.group : &l)
+ if (const target* g = exp && l.is_a<libs> () ? 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<libs> ())
- f = static_cast<file*> (f->member);
+ f = static_cast<const file*> (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<libs> () ? l.group : &l)
+ if (const target* g = exp && l.is_a<libs> () ? 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<bool (file&, bool)> impf (imp);
- const function<void (file*, const string&, bool)> libf (lib);
+ const function<bool (const file&, bool)> impf (imp);
+ const function<void (const file*, const string&, bool)> 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<liba> ()) ||
(f = pt->is_a<libs> ()))
@@ -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<file&> (xt));
+ const file& t (static_cast<const file&> (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<libs_paths> ());
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<obje> ()) ||
(f = pt->is_a<obja> ()) ||
@@ -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<file*> (t.member));
- out2 = "/IMPLIB:" + relative (imp->path ()).string ();
+ auto& imp (static_cast<const file&> (*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<file*> (
- lt == otype::e ? t.member : t.member->member));
- out1 = "/PDB:" + relative (pdb->path ()).string ();
+ auto& pdb (
+ static_cast<const file&> (
+ 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<file*> (t.member));
- out = "-Wl,--out-implib=" + relative (imp->path ()).string ();
+ auto& imp (static_cast<const file&> (*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<obje> ()) ||
(f = pt->is_a<obja> ()) ||
@@ -1600,11 +1603,13 @@ namespace build2
}
};
+ const libs_paths& paths (t.data<libs_paths> ());
+
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 = &in;}
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<file&> (xt));
-
- libs_paths paths;
+ const file& t (static_cast<const file&> (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<libs_paths> ());
+
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<file*> (t.member)->path ().leaf ());
+ path imp (static_cast<const file&> (*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<string> (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<target*> (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<bin::obje> () ? otype::e :
@@ -16,7 +16,7 @@ namespace build2
}
inline otype
- link_type (target& t)
+ link_type (const target& t)
{
return
t.is_a<exe> () ? 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<liba> ()) ||
(f = pt->is_a<libs> ()))
@@ -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<file&> (*l->member->member).path ().string ()
+ ? &static_cast<const file&> (
+ *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<liba> ()) ||
(f = pt->is_a<libs> ()))
@@ -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,