aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build2/algorithm27
-rw-r--r--build2/algorithm.cxx21
-rw-r--r--build2/algorithm.ixx19
-rw-r--r--build2/b.cxx16
-rw-r--r--build2/buildfile2
-rw-r--r--build2/cc/common8
-rw-r--r--build2/cc/common.cxx10
-rw-r--r--build2/cc/compile10
-rw-r--r--build2/cc/compile.cxx36
-rw-r--r--build2/cc/link12
-rw-r--r--build2/cc/link.cxx20
-rw-r--r--build2/cc/pkgconfig.cxx2
-rw-r--r--build2/cc/utility2
-rw-r--r--build2/cc/utility.cxx2
-rw-r--r--build2/cc/windows-manifest.cxx2
-rw-r--r--build2/cc/windows-rpath.cxx10
-rw-r--r--build2/cli/rule.cxx2
-rw-r--r--build2/config/init.cxx7
-rw-r--r--build2/config/operation.cxx95
-rw-r--r--build2/context4
-rw-r--r--build2/context.cxx22
-rw-r--r--build2/dist/operation.cxx6
-rw-r--r--build2/file10
-rw-r--r--build2/file.cxx36
-rw-r--r--build2/install/rule.cxx7
-rw-r--r--build2/operation6
-rw-r--r--build2/operation.cxx4
-rw-r--r--build2/parser.cxx2
-rw-r--r--build2/prerequisite6
-rw-r--r--build2/rule-map5
-rw-r--r--build2/scope86
-rw-r--r--build2/scope.cxx9
-rw-r--r--build2/scope.ixx42
-rw-r--r--build2/target16
-rw-r--r--build2/target-type16
-rw-r--r--build2/target.cxx19
-rw-r--r--build2/target.txx4
-rw-r--r--build2/test/rule.cxx2
-rw-r--r--build2/test/target.cxx2
-rw-r--r--build2/variable2
-rw-r--r--unit-tests/function/driver.cxx2
41 files changed, 392 insertions, 219 deletions
diff --git a/build2/algorithm b/build2/algorithm
index 5cd31fe..742b2e9 100644
--- a/build2/algorithm
+++ b/build2/algorithm
@@ -45,7 +45,7 @@ namespace build2
const dir_path& out,
const string& name,
const optional<string>& ext,
- scope*,
+ const scope*,
const optional<string>& proj = nullopt);
// As above but specify the target type as template argument.
@@ -56,14 +56,14 @@ namespace build2
const dir_path& out,
const string& name,
const optional<string>& ext,
- scope*);
+ const scope*);
// Search for a target identified by the name. The semantics is "as if" we
// first created a prerequisite based on this name in exactly the same way
// as the parser would and then searched based on this prerequisite.
//
target&
- search (name, scope&);
+ search (name, const scope&);
// As above but only search for an already existing target. Unlike the
// above version, this one can be called during the execute phase.
@@ -72,7 +72,9 @@ namespace build2
// unknown target types.
//
target*
- search_existing (const name&, scope&, const dir_path& out = dir_path ());
+ search_existing (const name&,
+ const scope&,
+ const dir_path& out = dir_path ());
// Match and apply a rule to the action/target with ambiguity detection.
// Increment the target's dependents count, which means that you should call
@@ -105,8 +107,9 @@ namespace build2
match_delegate (slock&, action, target&, const rule&);
// The standard prerequisite search and match implementations. They call
- // search_and_match_*() versions below passing non-empty directory for
- // the clean operation.
+ // search() and then match() for each prerequisite in a loop omitting out of
+ // project prerequisites for the clean operation. If this target is a member
+ // of a group, then they first do this to the group's prerequisites.
//
void
search_and_match_prerequisites (slock&, action, target&);
@@ -117,20 +120,14 @@ namespace build2
void
search_and_match_prerequisite_members (slock&, action, target&);
- // The actual prerequisite search and match implementations. They call
- // search() and then match() for each prerequisite in a loop. If this
- // target is a member of a group, then they first do this to the group's
- // prerequisites.
- //
- // If the directory argument is not empty, then they ignore (do not
- // match) prerequisites that are not in the same or its subdirectory.
+ // As above but omit prerequisites that are not in the specified scope.
//
void
- search_and_match_prerequisites (slock&, action, target&, const dir_path&);
+ search_and_match_prerequisites (slock&, action, target&, const scope&);
void
search_and_match_prerequisite_members (
- slock&, action, target&, const dir_path&);
+ slock&, action, target&, const scope&);
// Unless already available, match, and, if necessary, execute the group
// in order to obtain its members list. Note that even after that the
diff --git a/build2/algorithm.cxx b/build2/algorithm.cxx
index 1e7a1b8..e8e7777 100644
--- a/build2/algorithm.cxx
+++ b/build2/algorithm.cxx
@@ -37,7 +37,7 @@ namespace build2
}
target&
- search (name n, scope& s)
+ search (name n, const scope& s)
{
assert (phase == run_phase::search_match);
@@ -57,7 +57,7 @@ namespace build2
}
target*
- search_existing (const name& cn, scope& s, const dir_path& out)
+ search_existing (const name& cn, const scope& s, const dir_path& out)
{
assert (phase == run_phase::search_match || phase == run_phase::execute);
@@ -116,7 +116,7 @@ namespace build2
//
action ra (a.meta_operation (), io, o != oo ? 0 : oo);
- scope& bs (t.base_scope ());
+ const scope& bs (t.base_scope ());
for (auto tt (&t.type ()); tt != nullptr; tt = tt->base)
{
@@ -310,7 +310,10 @@ namespace build2
}
void
- search_and_match_prerequisites (slock& ml, action a, target& t, scope* s)
+ search_and_match_prerequisites (slock& ml,
+ action a,
+ target& t,
+ const scope* s)
{
for (prerequisite& p: group_prerequisites (t))
{
@@ -325,8 +328,10 @@ namespace build2
}
void
- search_and_match_prerequisite_members (
- slock& ml, action a, target& t, scope* s)
+ search_and_match_prerequisite_members (slock& ml,
+ action a,
+ target& t,
+ const scope* s)
{
for (prerequisite_member p: group_prerequisite_members (ml, a, t))
{
@@ -345,8 +350,8 @@ namespace build2
{
tracer trace ("inject_fsdir");
- scope& bs (t.base_scope ());
- scope* rs (bs.root_scope ());
+ const scope& bs (t.base_scope ());
+ const scope* rs (bs.root_scope ());
// Handle the outside of any project case. Note that we also used to bail
// our of this is the root of the project. But that proved not to be such
diff --git a/build2/algorithm.ixx b/build2/algorithm.ixx
index ec06ddf..365a5c4 100644
--- a/build2/algorithm.ixx
+++ b/build2/algorithm.ixx
@@ -33,7 +33,7 @@ namespace build2
const dir_path& out,
const string& name,
const optional<string>& ext,
- scope* scope,
+ const scope* scope,
const optional<string>& proj)
{
return search (
@@ -46,7 +46,7 @@ namespace build2
const dir_path& out,
const string& name,
const optional<string>& ext,
- scope* scope)
+ const scope* scope)
{
return static_cast<T&> (
search (T::static_type, dir, out, name, ext, scope));
@@ -118,10 +118,10 @@ namespace build2
}
void
- search_and_match_prerequisites (slock&, action, target&, scope*);
+ search_and_match_prerequisites (slock&, action, target&, const scope*);
void
- search_and_match_prerequisite_members (slock&, action, target&, scope*);
+ search_and_match_prerequisite_members (slock&, action, target&, const scope*);
inline void
search_and_match_prerequisites (slock& ml, action a, target& t)
@@ -147,14 +147,19 @@ namespace build2
}
inline void
- search_and_match_prerequisites (slock& ml, action a, target& t, scope& s)
+ search_and_match_prerequisites (slock& ml,
+ action a,
+ target& t,
+ const scope& s)
{
search_and_match_prerequisites (ml, a, t, &s);
}
inline void
- search_and_match_prerequisite_members (
- slock& ml, action a, target& t, scope& s)
+ search_and_match_prerequisite_members (slock& ml,
+ action a,
+ target& t,
+ const scope& s)
{
search_and_match_prerequisite_members (ml, a, t, &s);
}
diff --git a/build2/b.cxx b/build2/b.cxx
index 341554f..0ad404a 100644
--- a/build2/b.cxx
+++ b/build2/b.cxx
@@ -52,11 +52,21 @@ using namespace std;
#include <build2/install/init>
#include <build2/pkgconfig/init>
-using namespace build2;
+namespace build2
+{
+ int
+ main (int argc, char* argv[]);
+}
int
main (int argc, char* argv[])
{
+ return build2::main (argc, argv);
+}
+
+int build2::
+main (int argc, char* argv[])
+{
// This is a little hack to make out baseutils for Windows work when called
// with absolute path. In a nutshell, MSYS2's exec*p() doesn't search in the
// parent's executable directory, only in PATH. And since we are running
@@ -563,7 +573,7 @@ main (int argc, char* argv[])
// be of use to the bootstrap files (other than src-root.build,
// which, BTW, doesn't need to exist if src_root == out_root).
//
- scope& rs (create_root (out_root, src_root));
+ scope& rs (create_root (*scope::global_, out_root, src_root));
bool bootstrapped (build2::bootstrapped (rs));
@@ -980,7 +990,7 @@ main (int argc, char* argv[])
// building before we know how to for all the targets in this
// operation batch.
//
- scope& bs (scopes.find (ts.out_base));
+ const scope& bs (scopes.find (ts.out_base));
// Find the target type and extract the extension.
//
diff --git a/build2/buildfile b/build2/buildfile
index 1ee7063..80d72a2 100644
--- a/build2/buildfile
+++ b/build2/buildfile
@@ -30,7 +30,7 @@ exe{b}: \
{hxx cxx}{ rule } \
{hxx }{ rule-map } \
{hxx txx cxx}{ scheduler } \
- {hxx cxx}{ scope } \
+ {hxx ixx cxx}{ scope } \
{hxx cxx}{ search } \
{hxx cxx}{ spec } \
{hxx ixx txx cxx}{ target } \
diff --git a/build2/cc/common b/build2/cc/common
index c11e733..06df4c3 100644
--- a/build2/cc/common
+++ b/build2/cc/common
@@ -184,7 +184,7 @@ namespace build2
//
public:
void
- process_libraries (scope&,
+ process_libraries (const scope&,
lorder,
const dir_paths&,
file&,
@@ -210,7 +210,7 @@ namespace build2
private:
file&
- resolve_library (scope&,
+ resolve_library (const scope&,
name,
lorder,
const dir_paths&,
@@ -222,10 +222,10 @@ namespace build2
const prerequisite_key&) const;
dir_paths
- extract_library_dirs (scope&) const;
+ extract_library_dirs (const scope&) const;
bool
- pkgconfig_extract (scope&,
+ pkgconfig_extract (const scope&,
bin::lib&,
bin::liba*,
bin::libs*,
diff --git a/build2/cc/common.cxx b/build2/cc/common.cxx
index aa0a45b..e7b26a1 100644
--- a/build2/cc/common.cxx
+++ b/build2/cc/common.cxx
@@ -46,7 +46,7 @@ namespace build2
//
void common::
process_libraries (
- scope& top_bs,
+ const scope& top_bs,
lorder top_lo,
const dir_paths& top_sysd,
file& l,
@@ -183,7 +183,7 @@ namespace build2
proc_lib (&l, p, s);
}
- scope& bs (t == nullptr || cc ? top_bs : l.base_scope ());
+ const scope& bs (t == nullptr || cc ? top_bs : l.base_scope ());
optional<lorder> lo; // Calculate lazily.
const dir_paths* sysd (nullptr); // Resolve lazily.
@@ -386,7 +386,7 @@ namespace build2
// that's the only way to guarantee it will be up-to-date.
//
file& common::
- resolve_library (scope& s,
+ resolve_library (const scope& s,
name n,
lorder lo,
const dir_paths& sysd,
@@ -657,7 +657,7 @@ namespace build2
//
if (cid == "msvc")
{
- scope& rs (*p.scope->root_scope ());
+ const scope& rs (*p.scope->root_scope ());
const process_path& ld (cast<process_path> (rs["bin.ld.path"]));
if (s == nullptr && !sn.empty ())
@@ -821,7 +821,7 @@ namespace build2
}
dir_paths common::
- extract_library_dirs (scope& bs) const
+ extract_library_dirs (const scope& bs) const
{
dir_paths r;
diff --git a/build2/cc/compile b/build2/cc/compile
index 11b3919..b6fc7d6 100644
--- a/build2/cc/compile
+++ b/build2/cc/compile
@@ -40,10 +40,10 @@ namespace build2
private:
void
- append_lib_options (scope&, cstrings&, target&, lorder) const;
+ append_lib_options (const scope&, cstrings&, target&, lorder) const;
void
- hash_lib_options (scope&, sha256&, target&, lorder) const;
+ hash_lib_options (const scope&, sha256&, target&, lorder) const;
// Mapping of include prefixes (e.g., foo in <foo/bar>) for auto-
// generated headers to directories where they will be generated.
@@ -61,15 +61,15 @@ namespace build2
append_prefixes (prefix_map&, target&, const variable&) const;
void
- append_lib_prefixes (scope&, prefix_map&, target&, lorder) const;
+ append_lib_prefixes (const scope&, prefix_map&, target&, lorder) const;
prefix_map
- build_prefix_map (scope&, target&, lorder) const;
+ build_prefix_map (const scope&, target&, lorder) const;
// Reverse-lookup target type from extension.
//
const target_type*
- map_extension (scope&, const string&, const string&) const;
+ map_extension (const scope&, const string&, const string&) const;
// Header dependency injection.
//
diff --git a/build2/cc/compile.cxx b/build2/cc/compile.cxx
index bc35272..2176b82 100644
--- a/build2/cc/compile.cxx
+++ b/build2/cc/compile.cxx
@@ -76,7 +76,10 @@ namespace build2
// (first one is cc.export.*) recursively, prerequisite libraries first.
//
void compile::
- append_lib_options (scope& bs, cstrings& args, target& t, lorder lo) const
+ append_lib_options (const scope& bs,
+ cstrings& args,
+ target& t,
+ lorder lo) const
{
auto opt = [&args, this] (file& l, const string& t, bool com, bool exp)
{
@@ -117,7 +120,7 @@ namespace build2
}
void compile::
- hash_lib_options (scope& bs, sha256& cs, target& t, lorder lo) const
+ hash_lib_options (const scope& bs, sha256& cs, target& t, lorder lo) const
{
auto opt = [&cs, this] (file& l, const string& t, bool com, bool exp)
{
@@ -156,7 +159,10 @@ namespace build2
// recursively, prerequisite libraries first.
//
void compile::
- append_lib_prefixes (scope& bs, prefix_map& m, target& t, lorder lo) const
+ append_lib_prefixes (const scope& bs,
+ prefix_map& m,
+ target& t,
+ lorder lo) const
{
auto opt = [&m, this] (file& l, const string& t, bool com, bool exp)
{
@@ -199,8 +205,8 @@ namespace build2
file& t (static_cast<file&> (xt));
const match_data& md (t.data<match_data> ());
- scope& bs (t.base_scope ());
- scope& rs (*bs.root_scope ());
+ const scope& bs (t.base_scope ());
+ const scope& rs (*bs.root_scope ());
otype ct (compile_type (t));
// Derive file name from target name.
@@ -405,7 +411,7 @@ namespace build2
// Reverse-lookup target type from extension.
//
const target_type* compile::
- map_extension (scope& s, const string& n, const string& e) const
+ map_extension (const scope& s, const string& n, const string& e) const
{
// We will just have to try all of the possible ones, in the "most
// likely to match" order.
@@ -442,7 +448,7 @@ namespace build2
// "imported as installed" library), then it can't possibly
// generate any headers for us.
//
- scope* rs (t.base_scope ().root_scope ());
+ const scope* rs (t.base_scope ().root_scope ());
if (rs == nullptr)
return;
@@ -526,7 +532,9 @@ namespace build2
}
auto compile::
- build_prefix_map (scope& bs, target& t, lorder lo) const -> prefix_map
+ build_prefix_map (const scope& bs,
+ target& t,
+ lorder lo) const -> prefix_map
{
prefix_map m;
@@ -737,8 +745,8 @@ namespace build2
info << "while extracting header dependencies from " << src;
}));
- scope& bs (t.base_scope ());
- scope& rs (*bs.root_scope ());
+ const scope& bs (t.base_scope ());
+ const scope& rs (*bs.root_scope ());
// Initialize lazily, only if required.
//
@@ -937,8 +945,8 @@ namespace build2
//
dir_path out;
- scope& bs (scopes.find (d));
- if (scope* rs = bs.root_scope ())
+ const scope& bs (scopes.find (d));
+ if (const scope* rs = bs.root_scope ())
{
tt = map_extension (bs, n, e);
@@ -1403,8 +1411,8 @@ namespace build2
return p.second;
}
- scope& bs (t.base_scope ());
- scope& rs (*bs.root_scope ());
+ const scope& bs (t.base_scope ());
+ const scope& rs (*bs.root_scope ());
otype ct (compile_type (t));
lorder lo (link_order (bs, ct));
diff --git a/build2/cc/link b/build2/cc/link
index 5f28204..d1b0e7a 100644
--- a/build2/cc/link
+++ b/build2/cc/link
@@ -71,13 +71,13 @@ namespace build2
// Library handling.
//
void
- append_libraries (strings&, file&, bool, scope&, lorder) const;
+ append_libraries (strings&, file&, bool, const scope&, lorder) const;
void
- hash_libraries (sha256&, file&, bool, scope&, lorder) const;
+ hash_libraries (sha256&, file&, bool, const scope&, lorder) const;
void
- rpath_libraries (strings&, target&, scope&, lorder, bool) const;
+ rpath_libraries (strings&, target&, const scope&, lorder, bool) const;
// Windows rpath emulation (windows-rpath.cxx).
//
@@ -93,13 +93,13 @@ namespace build2
using windows_dlls = std::set<windows_dll>;
timestamp
- windows_rpath_timestamp (file&, scope&, lorder) const;
+ windows_rpath_timestamp (file&, const scope&, lorder) const;
windows_dlls
- windows_rpath_dlls (file&, scope&, lorder) const;
+ windows_rpath_dlls (file&, const scope&, lorder) const;
void
- windows_rpath_assembly (file&, scope&, lorder,
+ windows_rpath_assembly (file&, const scope&, lorder,
const string&,
timestamp,
bool) const;
diff --git a/build2/cc/link.cxx b/build2/cc/link.cxx
index 6de294a..d85faed 100644
--- a/build2/cc/link.cxx
+++ b/build2/cc/link.cxx
@@ -322,8 +322,8 @@ namespace build2
file& t (static_cast<file&> (xt));
- scope& bs (t.base_scope ());
- scope& rs (*bs.root_scope ());
+ const scope& bs (t.base_scope ());
+ const scope& rs (*bs.root_scope ());
otype lt (link_type (t));
lorder lo (link_order (bs, lt));
@@ -657,7 +657,7 @@ namespace build2
void link::
append_libraries (strings& args,
file& l, bool la,
- scope& bs, lorder lo) const
+ const scope& bs, lorder lo) const
{
// Note: lack of the "small function object" optimization will really
// kill us here since we are called in a loop.
@@ -704,7 +704,11 @@ namespace build2
}
void link::
- hash_libraries (sha256& cs, file& l, bool la, scope& bs, lorder lo) const
+ hash_libraries (sha256& cs,
+ file& l,
+ bool la,
+ const scope& bs,
+ lorder lo) const
{
bool win (tclass == "windows");
@@ -747,7 +751,9 @@ namespace build2
void link::
rpath_libraries (strings& args,
- target& t, scope& bs, lorder lo,
+ target& t,
+ const scope& bs,
+ lorder lo,
bool for_install) const
{
// Use -rpath-link on targets that support it (Linux, *BSD). Note
@@ -887,8 +893,8 @@ namespace build2
file& t (static_cast<file&> (xt));
- scope& bs (t.base_scope ());
- scope& rs (*bs.root_scope ());
+ const scope& bs (t.base_scope ());
+ const scope& rs (*bs.root_scope ());
otype lt (link_type (t));
lorder lo (link_order (bs, lt));
diff --git a/build2/cc/pkgconfig.cxx b/build2/cc/pkgconfig.cxx
index 6c8159f..d32cd61 100644
--- a/build2/cc/pkgconfig.cxx
+++ b/build2/cc/pkgconfig.cxx
@@ -37,7 +37,7 @@ namespace build2
// search_library() POV.
//
bool common::
- pkgconfig_extract (scope& s,
+ pkgconfig_extract (const scope& s,
lib& lt,
liba* at,
libs* st,
diff --git a/build2/cc/utility b/build2/cc/utility
index b481202..050b645 100644
--- a/build2/cc/utility
+++ b/build2/cc/utility
@@ -37,7 +37,7 @@ namespace build2
// same directory have to have the same link order.
//
lorder
- link_order (scope& base, otype);
+ link_order (const scope& base, otype);
// Given the link order return the library member (liba or libs) to link.
//
diff --git a/build2/cc/utility.cxx b/build2/cc/utility.cxx
index f8a0afc..5c5d1fe 100644
--- a/build2/cc/utility.cxx
+++ b/build2/cc/utility.cxx
@@ -18,7 +18,7 @@ namespace build2
using namespace bin;
lorder
- link_order (scope& bs, otype ot)
+ link_order (const scope& bs, otype ot)
{
// Initialize to suppress 'may be used uninitialized' warning produced
// by MinGW GCC 5.4.0.
diff --git a/build2/cc/windows-manifest.cxx b/build2/cc/windows-manifest.cxx
index 44d8f7b..b0b0feb 100644
--- a/build2/cc/windows-manifest.cxx
+++ b/build2/cc/windows-manifest.cxx
@@ -43,7 +43,7 @@ namespace build2
{
tracer trace (x, "windows_manifest");
- scope& rs (t.root_scope ());
+ const scope& rs (t.root_scope ());
const char* pa (windows_manifest_arch (cast<string> (rs[x_target_cpu])));
diff --git a/build2/cc/windows-rpath.cxx b/build2/cc/windows-rpath.cxx
index 35d83cc..00911d4 100644
--- a/build2/cc/windows-rpath.cxx
+++ b/build2/cc/windows-rpath.cxx
@@ -46,7 +46,7 @@ namespace build2
// adding to the assembly or timestamp_nonexistent if there aren't any.
//
timestamp link::
- windows_rpath_timestamp (file& t, scope& bs, lorder lo) const
+ windows_rpath_timestamp (file& t, const scope& bs, lorder lo) const
{
timestamp r (timestamp_nonexistent);
@@ -116,7 +116,9 @@ namespace build2
// duplicates).
//
auto link::
- windows_rpath_dlls (file& t, scope& bs, lorder lo) const -> windows_dlls
+ windows_rpath_dlls (file& t,
+ const scope& bs,
+ lorder lo) const -> windows_dlls
{
windows_dlls r;
@@ -204,7 +206,7 @@ namespace build2
//
void link::
windows_rpath_assembly (file& t,
- scope& bs,
+ const scope& bs,
lorder lo,
const string& tcpu,
timestamp ts,
@@ -276,7 +278,7 @@ namespace build2
<< " processorArchitecture='" << pa << "'\n"
<< " version='0.0.0.0'/>\n";
- scope& as (*t.root_scope ().weak_scope ()); // Amalgamation scope.
+ const scope& as (*t.root_scope ().weak_scope ()); // Amalgamation.
auto link = [&as, &ad] (const path& f, const path& l)
{
diff --git a/build2/cli/rule.cxx b/build2/cli/rule.cxx
index 8cef1f5..773d00c 100644
--- a/build2/cli/rule.cxx
+++ b/build2/cli/rule.cxx
@@ -250,7 +250,7 @@ namespace build2
path relo (relative (t.dir));
path rels (relative (s->path ()));
- scope& rs (t.root_scope ());
+ const scope& rs (t.root_scope ());
const process_path& cli (cast<process_path> (rs["cli.path"]));
diff --git a/build2/config/init.cxx b/build2/config/init.cxx
index a73c394..682d817 100644
--- a/build2/config/init.cxx
+++ b/build2/config/init.cxx
@@ -75,7 +75,7 @@ namespace build2
{
// Assume missing version is 0.
//
- auto p (extract_variable (f, c_v));
+ auto p (extract_variable (rs, f, c_v));
uint64_t v (p.second ? cast<uint64_t> (p.first) : 0);
if (v != module::version)
@@ -127,9 +127,10 @@ namespace build2
//
{
// We need this rule for out-of-any-project dependencies (e.g.,
- // libraries imported from /usr/lib).
+ // libraries imported from /usr/lib). Registring it on the global
+ // scope smells a bit but seems harmless.
//
- global_scope->rules.insert<file> (
+ rs.global ().rules.insert<file> (
configure_id, 0, "config.file", file_rule::instance);
auto& r (rs.rules);
diff --git a/build2/config/operation.cxx b/build2/config/operation.cxx
index 63e6d9b..75f5abc 100644
--- a/build2/config/operation.cxx
+++ b/build2/config/operation.cxx
@@ -61,8 +61,10 @@ namespace build2
}
}
+ using project_set = set<const scope*>; // Use pointers to get comparison.
+
static void
- save_config (scope& root, const set<scope*>& projects)
+ save_config (const scope& root, const project_set& projects)
{
const dir_path& out_root (root.out_path ());
path f (out_root / config_file);
@@ -137,7 +139,7 @@ namespace build2
// root.
//
bool found (false);
- scope* r (&root);
+ const scope* r (&root);
while ((r = r->parent_scope ()->root_scope ()) != nullptr)
{
if (l.belongs (*r))
@@ -282,7 +284,7 @@ namespace build2
}
static void
- configure_project (action a, scope& root, set<scope*>& projects)
+ configure_project (action a, const scope& root, project_set& projects)
{
tracer trace ("configure_project");
@@ -331,7 +333,7 @@ namespace build2
{
const dir_path& pd (p.second);
dir_path out_nroot (out_root / pd);
- scope& nroot (scopes.find (out_nroot));
+ const scope& nroot (scopes.find (out_nroot));
// @@ Strictly speaking we need to check whether the config
// module was loaded for this subproject.
@@ -358,7 +360,7 @@ namespace build2
// callbacks here since the meta operation is configure and we
// know what we are doing.
//
- set<scope*> projects;
+ project_set projects;
// Note that we cannot do this in parallel. We cannot parallelize the
// outer loop because we should match for a single action at a time.
@@ -371,7 +373,7 @@ namespace build2
for (void* v: ts)
{
target& t (*static_cast<target*> (v));
- scope* rs (t.base_scope ().root_scope ());
+ const scope* rs (t.base_scope ().root_scope ());
if (rs == nullptr)
fail << "out of project target " << t;
@@ -423,7 +425,45 @@ namespace build2
}
static void
- disfigure_load (scope&,
+ load_project (scope& root)
+ {
+ if (auto l = root.vars[var_subprojects])
+ {
+ const dir_path& out_root (root.out_path ());
+ const dir_path& src_root (root.src_path ());
+
+ for (auto p: cast<subprojects> (l))
+ {
+ const dir_path& pd (p.second);
+
+ // Create and bootstrap subproject's root scope.
+ //
+ dir_path out_nroot (out_root / pd);
+
+ // The same logic for src_root as in create_bootstrap_inner().
+ //
+ scope& nroot (create_root (root, out_nroot, dir_path ()));
+
+ if (!bootstrapped (nroot))
+ {
+ bootstrap_out (nroot);
+
+ value& val (nroot.assign (var_src_root));
+
+ if (!val)
+ val = is_src_root (out_nroot) ? out_nroot : (src_root / pd);
+
+ setup_root (nroot);
+ bootstrap_src (nroot);
+ }
+
+ load_project (nroot);
+ }
+ }
+ }
+
+ static void
+ disfigure_load (scope& root,
const path& bf,
const dir_path&,
const dir_path&,
@@ -431,17 +471,23 @@ namespace build2
{
tracer trace ("disfigure_load");
l6 ([&]{trace << "skipping " << bf;});
+
+ // Since we don't load buildfiles during disfigure but still want to
+ // disfigure all the subprojects (see disfigure_project() below), we
+ // bootstrap all known subprojects.
+ //
+ load_project (root);
}
static void
- disfigure_search (scope& root,
+ disfigure_search (const scope& root,
const target_key&,
const location&,
action_targets& ts)
{
tracer trace ("disfigure_search");
l6 ([&]{trace << "collecting " << root.out_path ();});
- ts.push_back (&root);
+ ts.push_back (const_cast<scope*> (&root)); //@@ MT TMP action_targets
}
static void
@@ -450,7 +496,7 @@ namespace build2
}
static bool
- disfigure_project (action a, scope& root, set<scope*>& projects)
+ disfigure_project (action a, const scope& root, project_set& projects)
{
tracer trace ("disfigure_project");
@@ -473,27 +519,9 @@ namespace build2
for (auto p: cast<subprojects> (l))
{
const dir_path& pd (p.second);
-
- // Create and bootstrap subproject's root scope.
- //
dir_path out_nroot (out_root / pd);
-
- // The same logic for src_root as in create_bootstrap_inner().
- //
- scope& nroot (create_root (out_nroot, dir_path ()));
-
- if (!bootstrapped (nroot))
- {
- bootstrap_out (nroot);
-
- value& val (nroot.assign (var_src_root));
-
- if (!val)
- val = is_src_root (out_nroot) ? out_nroot : (src_root / pd);
-
- setup_root (nroot);
- bootstrap_src (nroot);
- }
+ const scope& nroot (scopes.find (out_nroot));
+ assert (nroot.out_path () == out_nroot); // See disfigure_load().
m = disfigure_project (a, nroot, projects) || m;
@@ -565,13 +593,14 @@ namespace build2
{
tracer trace ("disfigure_execute");
- set<scope*> projects;
+ project_set projects;
- // Note: doing everything in the load phase.
+ // Note: doing everything in the load phase (disfigure_project () does
+ // modify the model).
//
for (void* v: ts)
{
- scope& root (*static_cast<scope*> (v));
+ const scope& root (*static_cast<const scope*> (v));
if (!disfigure_project (a, root, projects))
{
diff --git a/build2/context b/build2/context
index c443a7a..d6f79af 100644
--- a/build2/context
+++ b/build2/context
@@ -268,14 +268,14 @@ namespace build2
// passed directory should be a sub-directory of out/src_root.
//
dir_path
- src_out (const dir_path& out, scope& root);
+ src_out (const dir_path& out, const scope& root);
dir_path
src_out (const dir_path& out,
const dir_path& out_root, const dir_path& src_root);
dir_path
- out_src (const dir_path& src, scope& root);
+ out_src (const dir_path& src, const scope& root);
dir_path
out_src (const dir_path& src,
diff --git a/build2/context.cxx b/build2/context.cxx
index 466db0d..e15294a 100644
--- a/build2/context.cxx
+++ b/build2/context.cxx
@@ -71,13 +71,14 @@ namespace build2
l6 ([&]{trace << "resetting build state";});
auto& vp (variable_pool::instance);
+ auto& sm (scope_map::instance);
variable_overrides vos;
var_override_cache.clear ();
targets.clear ();
- scopes.clear ();
+ sm.clear ();
vp.clear ();
// Reset meta/operation tables. Note that the order should match the id
@@ -101,13 +102,16 @@ namespace build2
// Create global scope. Note that the empty path is a prefix for any other
// path. See the comment in <butl/prefix-map> for details.
//
+ auto make_global_scope = [&sm] () -> scope&
{
- auto i (scopes.insert (dir_path (), false));
- global_scope = &i->second;
- global_scope->out_path_ = &i->first;
- }
+ auto i (sm.insert (dir_path (), false));
+ scope& r (i->second);
+ r.out_path_ = &i->first;
+ global_scope = scope::global_ = &r;
+ return r;
+ };
- scope& gs (*global_scope);
+ scope& gs (make_global_scope ());
// Parse and enter the command line variables. We do it before entering
// any other variables so that all the variables that are overriden are
@@ -215,7 +219,7 @@ namespace build2
//
if (c == '!' || !dir.empty ())
{
- scope& s (c == '!' ? gs : scopes.insert (dir, false)->second);
+ scope& s (c == '!' ? gs : sm.insert (dir, false)->second);
auto p (s.vars.insert (*o));
if (!p.second)
@@ -377,14 +381,14 @@ namespace build2
}
dir_path
- src_out (const dir_path& out, scope& r)
+ src_out (const dir_path& out, const scope& r)
{
assert (r.root ());
return src_out (out, r.out_path (), r.src_path ());
}
dir_path
- out_src (const dir_path& src, scope& r)
+ out_src (const dir_path& src, const scope& r)
{
assert (r.root ());
return out_src (src, r.out_path (), r.src_path ());
diff --git a/build2/dist/operation.cxx b/build2/dist/operation.cxx
index c7fe83b..1f9fbbd 100644
--- a/build2/dist/operation.cxx
+++ b/build2/dist/operation.cxx
@@ -62,7 +62,7 @@ namespace build2
// For now we assume all the targets are from the same project.
//
target& t (*static_cast<target*> (ts[0]));
- scope* rs (t.base_scope ().root_scope ());
+ const scope* rs (t.base_scope ().root_scope ());
if (rs == nullptr)
fail << "out of project target " << t;
@@ -162,7 +162,7 @@ namespace build2
// ignored on the next step if the user explicitly marked them
// nodist.
//
- auto add_adhoc = [&trace] (scope& rs, const path& f)
+ auto add_adhoc = [&trace] (const scope& rs, const path& f)
{
path p (rs.src_path () / f);
if (exists (p))
@@ -194,7 +194,7 @@ namespace build2
{
const dir_path& pd (p.second);
dir_path out_nroot (out_root / pd);
- scope& nrs (scopes.find (out_nroot));
+ const scope& nrs (scopes.find (out_nroot));
if (nrs.out_path () != out_nroot) // This subproject not loaded.
continue;
diff --git a/build2/file b/build2/file
index adfd884..696c5d7 100644
--- a/build2/file
+++ b/build2/file
@@ -70,10 +70,11 @@ namespace build2
source_once (scope& root, scope& base, const path&, scope& once);
// Create project's root scope. Only set the src_root variable if the
- // passed src_root value is not empty.
+ // passed src_root value is not empty. The scope argument is only used
+ // as proof of lock.
//
scope&
- create_root (const dir_path& out_root, const dir_path& src_root);
+ create_root (scope&, const dir_path& out_root, const dir_path& src_root);
// Setup root scope. Note that it assume the src_root variable
// has already been set.
@@ -140,10 +141,11 @@ namespace build2
// Extract the specified variable value from a buildfile. It is expected to
// be the first non-comment line and not to rely on any variable expansion
// other than those from the global scope or any variable overrides. Return
- // an indication of whether the variable was found.
+ // an indication of whether the variable was found. The scope is only used
+ // as proof of lock (though we don't modify anything).
//
pair<value, bool>
- extract_variable (const path&, const variable&);
+ extract_variable (scope&, const path&, const variable&);
// Import has two phases: the first is triggered by the import
// directive in the buildfile. It will try to find and load the
diff --git a/build2/file.cxx b/build2/file.cxx
index 755ff0f..3da1d35 100644
--- a/build2/file.cxx
+++ b/build2/file.cxx
@@ -133,12 +133,12 @@ namespace build2
}
scope&
- create_root (const dir_path& out_root, const dir_path& src_root)
+ create_root (scope& l, const dir_path& out_root, const dir_path& src_root)
{
- auto i (scopes.insert (out_root, true));
+ auto i (scopes.rw (l).insert (out_root, true));
scope& rs (i->second);
- // Set out_path. src_path is set in setup_root() below.
+ // Set out_path. Note that src_path is set in setup_root() below.
//
if (rs.out_path_ != &i->first)
{
@@ -260,7 +260,7 @@ namespace build2
// First, enter the scope into the map and see if it is in any project. If
// it is not, then there is nothing else to do.
//
- auto i (scopes.insert (p, false));
+ auto i (scopes.rw (root).insert (p, false));
scope& base (i->second);
scope* rs (base.root_scope ());
@@ -317,7 +317,7 @@ namespace build2
// other than those from the global scope or any variable overrides.
//
pair<value, bool>
- extract_variable (const path& bf, const variable& var)
+ extract_variable (scope& s, const path& bf, const variable& var)
{
try
{
@@ -336,7 +336,7 @@ namespace build2
}
parser p;
- temp_scope tmp (*global_scope);
+ temp_scope tmp (s.global ());
p.parse_variable (lex, tmp, var, tt);
value* v (tmp.vars.find (var));
@@ -357,7 +357,8 @@ namespace build2
// Extract the project name from bootstrap.build.
//
static string
- find_project_name (const dir_path& out_root,
+ find_project_name (scope& s,
+ const dir_path& out_root,
const dir_path& fallback_src_root,
bool* src_hint = nullptr)
{
@@ -380,7 +381,7 @@ namespace build2
src_root = &fallback_src_root;
else
{
- auto p (extract_variable (f, *var_src_root));
+ auto p (extract_variable (s, f, *var_src_root));
if (!p.second)
fail << "variable 'src_root' expected as first line in " << f;
@@ -395,7 +396,7 @@ namespace build2
string name;
{
path f (*src_root / bootstrap_file);
- auto p (extract_variable (f, *var_project));
+ auto p (extract_variable (s, f, *var_project));
if (!p.second)
fail << "variable '" << var_project->name << "' expected "
@@ -414,7 +415,8 @@ namespace build2
// Otherwise, scan the subdirectory recursively.
//
static void
- find_subprojects (subprojects& sps,
+ find_subprojects (scope& s,
+ subprojects& sps,
const dir_path& d,
const dir_path& root,
bool out)
@@ -460,7 +462,7 @@ namespace build2
// Load its name. Note that here we don't use fallback src_root
// since this function is used to scan both out_root and src_root.
//
- string name (find_project_name (sd, dir_path (), &src));
+ string name (find_project_name (s, sd, dir_path (), &src));
// If the name is empty, then is is an unnamed project. While the
// 'project' variable stays empty, here we come up with a surrogate
@@ -619,13 +621,13 @@ namespace build2
if (exists (out_root))
{
l5 ([&]{trace << "looking for subprojects in " << out_root;});
- find_subprojects (sps, out_root, out_root, true);
+ find_subprojects (root, sps, out_root, out_root, true);
}
if (out_root != src_root)
{
l5 ([&]{trace << "looking for subprojects in " << src_root;});
- find_subprojects (sps, src_root, src_root, false);
+ find_subprojects (root, sps, src_root, src_root, false);
}
if (!sps.empty ()) // Keep it NULL if no subprojects.
@@ -695,7 +697,7 @@ namespace build2
// was specified by the user so it is most likely in our
// src.
//
- n = find_project_name (out_root / d, src_root / d);
+ n = find_project_name (root, out_root / d, src_root / d);
// See find_subprojects() for details on unnamed projects.
//
@@ -750,7 +752,7 @@ namespace build2
// explicitly configured by the user. After that, #2 followed
// by #1 seems reasonable.
//
- scope& rs (create_root (out_root, dir_path ()));
+ scope& rs (create_root (root, out_root, dir_path ()));
if (!bootstrapped (rs))
{
@@ -796,7 +798,7 @@ namespace build2
// The same logic to src_root as in create_bootstrap_outer().
//
- scope& rs (create_root (out_root, dir_path ()));
+ scope& rs (create_root (root, out_root, dir_path ()));
if (!bootstrapped (rs))
{
@@ -1037,7 +1039,7 @@ namespace build2
for (;;)
{
src_root = is_src_root (out_root) ? out_root : dir_path ();
- root = &create_root (out_root, src_root);
+ root = &create_root (iroot, out_root, src_root);
if (!bootstrapped (*root))
{
diff --git a/build2/install/rule.cxx b/build2/install/rule.cxx
index 13c93a7..8c21dc1 100644
--- a/build2/install/rule.cxx
+++ b/build2/install/rule.cxx
@@ -278,7 +278,10 @@ namespace build2
// empty add it to install_dirs. Return the new last element.
//
static install_dir&
- resolve_subdir (install_dirs& rs, target& t, scope& s, const lookup& l)
+ resolve_subdir (install_dirs& rs,
+ target& t,
+ const scope& s,
+ const lookup& l)
{
// Find the scope from which this value came and use as a base
// to calculate the subdirectory.
@@ -338,7 +341,7 @@ namespace build2
}
install_dir* r (&rs.back ());
- scope& s (t.base_scope ());
+ const scope& s (t.base_scope ());
// Override components in install_dir if we have our own.
//
diff --git a/build2/operation b/build2/operation
index 22bb8a7..4af306d 100644
--- a/build2/operation
+++ b/build2/operation
@@ -173,7 +173,7 @@ namespace build2
// Normally a list of resolved and matched targets to execute. But
// can be something else, depending on the meta-operation.
//
- typedef vector<void*> action_targets;
+ typedef vector<void*> action_targets; //@@ MT TMP: make const void*
struct meta_operation_info
{
@@ -204,7 +204,7 @@ namespace build2
const dir_path& src_base,
const location&);
- void (*search) (scope& root,
+ void (*search) (const scope& root,
const target_key&,
const location&,
action_targets&);
@@ -239,7 +239,7 @@ namespace build2
// that does just that and adds a pointer to the target to the list.
//
void
- search (scope&, const target_key&, const location&, action_targets&);
+ search (const scope&, const target_key&, const location&, action_targets&);
void
match (action, action_targets&);
diff --git a/build2/operation.cxx b/build2/operation.cxx
index 6e8511d..4e65783 100644
--- a/build2/operation.cxx
+++ b/build2/operation.cxx
@@ -58,7 +58,7 @@ namespace build2
// Create the base scope. Note that its existence doesn't mean it was
// already setup as a base scope; it can be the same as root.
//
- auto i (scopes.insert (out_base, false));
+ auto i (scopes.rw (root).insert (out_base, false));
scope& base (setup_base (i, out_base, src_base));
// Load the buildfile unless it has already been loaded.
@@ -67,7 +67,7 @@ namespace build2
}
void
- search (scope&,
+ search (const scope&,
const target_key& tk,
const location& l,
action_targets& ts)
diff --git a/build2/parser.cxx b/build2/parser.cxx
index 7f6b940..c48159a 100644
--- a/build2/parser.cxx
+++ b/build2/parser.cxx
@@ -3280,7 +3280,7 @@ namespace build2
lexer l (is, *path_, "\'\"\\$(", &paren_processor);
lexer_ = &l;
target_ = nullptr;
- scope_ = root_ = global_scope;
+ scope_ = root_ = scope::global_;
// Turn on the value mode/pairs recognition with '@' as the pair separator
// (e.g., src_root/@out_root/exe{foo bar}).
diff --git a/build2/prerequisite b/build2/prerequisite
index abfb2c1..a6d3632 100644
--- a/build2/prerequisite
+++ b/build2/prerequisite
@@ -33,7 +33,7 @@ namespace build2
const optional<string>& proj;
target_key tk; // The .dir and .out members can be relative.
- scope_type* scope; // Can be NULL if tk.dir is absolute.
+ const scope_type* scope; // Can be NULL if tk.dir is absolute.
static const optional<string> nullproj;
@@ -69,7 +69,7 @@ namespace build2
const dir_path out; // Empty, normalized absolute, or relative.
const string name;
const optional<string> ext; // Absent if unspecified.
- scope_type& scope;
+ const scope_type& scope;
target_type* target; // NULL if not yet resolved. Note that this
// should always be the "primary target", not
@@ -82,7 +82,7 @@ namespace build2
dir_path o,
string n,
optional<string> e,
- scope_type& s)
+ const scope_type& s)
: proj (move (p)),
type (t),
dir (move (d)),
diff --git a/build2/rule-map b/build2/rule-map
index b7397a0..d7748b6 100644
--- a/build2/rule-map
+++ b/build2/rule-map
@@ -26,6 +26,9 @@ namespace build2
// This is an "indexed map" with operation_id being the index. Entry
// with id 0 is a wildcard.
//
+ // Note that while we may resize some vectors during non-serial load, this
+ // is MT-safe since we never cache any references to their elements.
+ //
class operation_rule_map
{
public:
@@ -63,6 +66,8 @@ namespace build2
// allocation for the common cases since most rules will be registered
// for perform, at least on non-root scopes.
//
+ // @@ Redo using small_vector?
+ //
class rule_map
{
public:
diff --git a/build2/scope b/build2/scope
index 8c5ec00..64aaf24 100644
--- a/build2/scope
+++ b/build2/scope
@@ -39,16 +39,16 @@ namespace build2
bool
root () const {return root_ == this;}
- scope*
- parent_scope () const {return parent_;}
+ scope* parent_scope () {return parent_;}
+ const scope* parent_scope () const {return parent_;}
// Root scope of this scope or NULL if this scope is not (yet)
// in any (known) project. Note that if the scope itself is
// root, then this function return this. To get to the outer
// root, query the root scope of the parent.
//
- scope*
- root_scope () const {return root_;}
+ scope* root_scope () {return root_;}
+ const scope* root_scope () const {return root_;}
// Root scope of a strong amalgamation of this scope or NULL if
// this scope is not (yet) in any (known) project. If there is
@@ -56,27 +56,16 @@ namespace build2
// scope of the project (in other words, in this case a project
// is treated as its own strong amalgamation).
//
- scope*
- strong_scope () const
- {
- return root_ != nullptr
- ? root_->strong_ != nullptr ? root_->strong_ : root_
- : nullptr;
- }
+ scope* strong_scope ();
+ const scope* strong_scope () const;
// Root scope of the outermost amalgamation or NULL if this scope is not
// (yet) in any (known) project. If there is no amalgamation, then this
// function returns the root scope of the project (in other words, in this
// case a project is treated as its own amalgamation).
//
- scope*
- weak_scope () const
- {
- scope* r (root_);
- if (r != nullptr)
- for (; r->parent_->root_ != nullptr; r = r->parent_->root_) ;
- return r;
- }
+ scope* weak_scope ();
+ const scope* weak_scope () const;
// Variables.
//
@@ -244,7 +233,27 @@ namespace build2
public:
loaded_module_map modules; // Only on root scope.
+ public:
+ // Proof of lock for RW access.
+ //
+ scope&
+ rw (const ulock&) const {return const_cast<scope&> (*this);}
+
+ // RW access to global scope (RO via global global_scope below).
+ //
+ scope&
+ global () {return *global_;}
+
+ private:
+ static scope* global_;
+
+ // Entities that can access bypassing the lock proof.
+ //
+ friend int main (int, char*[]);
+ friend variable_overrides reset (const strings&);
+
private:
+ friend class parser;
friend class scope_map;
friend class temp_scope;
@@ -302,11 +311,14 @@ namespace build2
// Find the most qualified scope that encompasses this path.
//
- scope&
- find (const dir_path&);
+ const scope&
+ find (const dir_path& d) const
+ {
+ return const_cast<scope_map*> (this)->find (d);
+ }
- scope&
- find (const path& p)
+ const scope&
+ find (const path& p) const
{
// Natural thing to do here would be to call find (p.directory ()).
// However, there could be a situation where the passed path is a
@@ -315,10 +327,34 @@ namespace build2
//
return find (path_cast<dir_path> (p));
}
+
+ // Proof of lock for RW access.
+ //
+ public:
+ scope_map&
+ rw (ulock&) const {return const_cast<scope_map&> (*this);}
+
+ scope_map&
+ rw (scope&) const {return const_cast<scope_map&> (*this);}
+
+ private:
+ static scope_map instance;
+
+ // Entities that can access bypassing the lock proof.
+ //
+ friend variable_overrides reset (const strings&);
+
+ scope&
+ find (const dir_path&);
+
+ public:
+ static const scope_map& cinstance; // For var_pool initialization.
};
- extern scope_map scopes;
- extern scope* global_scope;
+ extern const scope_map& scopes;
+ extern const scope* global_scope;
}
+#include <build2/scope.ixx>
+
#endif // BUILD2_SCOPE
diff --git a/build2/scope.cxx b/build2/scope.cxx
index 9514817..0c80052 100644
--- a/build2/scope.cxx
+++ b/build2/scope.cxx
@@ -691,10 +691,15 @@ namespace build2
pr.first->second.get (), pr.second);
}
+ scope* scope::global_;
+
// scope_map
//
- scope_map scopes;
- scope* global_scope;
+ scope_map scope_map::instance;
+ const scope_map& scope_map::cinstance = scope_map::instance;
+ const scope_map& scopes = scope_map::cinstance;
+
+ const scope* global_scope;
auto scope_map::
insert (const dir_path& k, bool root) -> iterator
diff --git a/build2/scope.ixx b/build2/scope.ixx
new file mode 100644
index 0000000..46eea3d
--- /dev/null
+++ b/build2/scope.ixx
@@ -0,0 +1,42 @@
+// file : build2/scope.ixx -*- C++ -*-
+// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+namespace build2
+{
+ // scope
+ //
+ inline scope* scope::
+ strong_scope ()
+ {
+ return root_ != nullptr
+ ? root_->strong_ != nullptr ? root_->strong_ : root_
+ : nullptr;
+ }
+
+ inline const scope* scope::
+ strong_scope () const
+ {
+ return root_ != nullptr
+ ? root_->strong_ != nullptr ? root_->strong_ : root_
+ : nullptr;
+ }
+
+ inline scope* scope::
+ weak_scope ()
+ {
+ scope* r (root_);
+ if (r != nullptr)
+ for (; r->parent_->root_ != nullptr; r = r->parent_->root_) ;
+ return r;
+ }
+
+ inline const scope* scope::
+ weak_scope () const
+ {
+ const scope* r (root_);
+ if (r != nullptr)
+ for (; r->parent_->root_ != nullptr; r = r->parent_->root_) ;
+ return r;
+ }
+}
diff --git a/build2/target b/build2/target
index 30dffab..05e4281 100644
--- a/build2/target
+++ b/build2/target
@@ -256,7 +256,7 @@ namespace build2
public:
// Most qualified scope that contains this target.
//
- scope&
+ const scope&
base_scope () const;
// Root scope of a project that contains this target. Note that
@@ -264,19 +264,19 @@ namespace build2
// this function asserts. If you need to detect this situation,
// then use base_scope().root_scope() expression instead.
//
- scope&
+ const scope&
root_scope () const;
// Root scope of a strong amalgamation that contains this target.
// The same notes as to root_scope() apply.
//
- scope&
+ const scope&
strong_scope () const {return *root_scope ().strong_scope ();}
// Root scope of the outermost amalgamation that contains this target.
// The same notes as to root_scope() apply.
//
- scope&
+ const scope&
weak_scope () const {return *root_scope ().weak_scope ();}
bool
@@ -1356,24 +1356,24 @@ namespace build2
//
template <const char* ext>
optional<string>
- target_extension_fix (const target_key&, scope&, bool);
+ target_extension_fix (const target_key&, const scope&, bool);
// Get the extension from the variable or use the default if none set. If
// the default is NULL, then return NULL.
//
template <const char* var, const char* def>
optional<string>
- target_extension_var (const target_key&, scope&, bool);
+ target_extension_var (const target_key&, const scope&, bool);
// Always return NULL extension.
//
optional<string>
- target_extension_null (const target_key&, scope&, bool);
+ target_extension_null (const target_key&, const scope&, bool);
// Assert if called.
//
optional<string>
- target_extension_assert (const target_key&, scope&, bool);
+ target_extension_assert (const target_key&, const scope&, bool);
// Target print functions.
//
diff --git a/build2/target-type b/build2/target-type
index cddb9e2..ab21aa0 100644
--- a/build2/target-type
+++ b/build2/target-type
@@ -40,11 +40,21 @@ namespace build2
{
const char* name;
const target_type* base;
- target* (*factory) (
- const target_type&, dir_path, dir_path, string, optional<string>);
- optional<string> (*extension) (const target_key&, scope&, bool search);
+
+ target* (*factory) (const target_type&,
+ dir_path,
+ dir_path,
+ string,
+ optional<string>);
+
+ optional<string> (*extension) (const target_key&,
+ const scope&,
+ bool search);
+
void (*print) (ostream&, const target_key&);
+
target* (*search) (const prerequisite_key&);
+
bool see_through; // A group with the default "see through" semantics.
template <typename T>
diff --git a/build2/target.cxx b/build2/target.cxx
index f04e26f..30e580a 100644
--- a/build2/target.cxx
+++ b/build2/target.cxx
@@ -110,7 +110,7 @@ namespace build2
return group_view {nullptr, 0};
}
- scope& target::
+ const scope& target::
base_scope () const
{
// If this target is from the src tree, use its out directory to find
@@ -119,12 +119,12 @@ namespace build2
return scopes.find (out_dir ());
}
- scope& target::
+ const scope& target::
root_scope () const
{
// This is tricky to cache so we do the lookup for now.
//
- scope* r (base_scope ().root_scope ());
+ const scope* r (base_scope ().root_scope ());
assert (r != nullptr);
return *r;
}
@@ -458,13 +458,13 @@ namespace build2
}
optional<string>
- target_extension_null (const target_key&, scope&, bool)
+ target_extension_null (const target_key&, const scope&, bool)
{
return nullopt;
}
optional<string>
- target_extension_assert (const target_key&, scope&, bool)
+ target_extension_assert (const target_key&, const scope&, bool)
{
assert (false); // Attempt to obtain the default extension.
throw failed ();
@@ -605,7 +605,7 @@ namespace build2
{
// Note: this code is a custom version of parser::parse_include().
- scope& s (*pk.scope);
+ const scope& s (*pk.scope);
// Calculate the new out_base.
//
@@ -633,7 +633,8 @@ namespace build2
model_rlock rl;
phase_guard pg (run_phase::load);
- pair<scope&, scope*> sp (switch_scope (*s.root_scope (), out_base));
+ pair<scope&, scope*> sp (
+ switch_scope (*s.rw (rl).root_scope (), out_base));
if (sp.second != nullptr) // Ignore scopes out of any project.
{
@@ -689,7 +690,7 @@ namespace build2
};
static optional<string>
- exe_extension (const target_key&, scope&, bool search)
+ exe_extension (const target_key&, const scope&, bool search)
{
// If we are searching for an executable that is not a target, then
// use the build machine executable extension. Otherwise, if this is
@@ -731,7 +732,7 @@ namespace build2
}
static optional<string>
- buildfile_target_extension (const target_key& tk, scope&, bool)
+ buildfile_target_extension (const target_key& tk, const scope&, bool)
{
// If the name is special 'buildfile', then there is no extension,
// otherwise it is .build.
diff --git a/build2/target.txx b/build2/target.txx
index 5519126..ea7bca7 100644
--- a/build2/target.txx
+++ b/build2/target.txx
@@ -34,14 +34,14 @@ namespace build2
//
template <const char* ext>
optional<string>
- target_extension_fix (const target_key&, scope&, bool)
+ target_extension_fix (const target_key&, const scope&, bool)
{
return string (ext);
}
template <const char* var, const char* def>
optional<string>
- target_extension_var (const target_key& tk, scope& s, bool)
+ target_extension_var (const target_key& tk, const scope& s, bool)
{
// Include target type/pattern-specific variables.
//
diff --git a/build2/test/rule.cxx b/build2/test/rule.cxx
index 6b06dca..05d5eac 100644
--- a/build2/test/rule.cxx
+++ b/build2/test/rule.cxx
@@ -270,7 +270,7 @@ namespace build2
// Resolve them to targets, which normally would be existing files
// but could also be targets that need updating.
//
- scope& bs (t.base_scope ());
+ const scope& bs (t.base_scope ());
// @@ OUT: what if this is a @-qualified pair or names?
//
diff --git a/build2/test/target.cxx b/build2/test/target.cxx
index 44f65aa..a5801e8 100644
--- a/build2/test/target.cxx
+++ b/build2/test/target.cxx
@@ -25,7 +25,7 @@ namespace build2
}
static optional<string>
- testscript_target_extension (const target_key& tk, scope&, bool)
+ testscript_target_extension (const target_key& tk, const scope&, bool)
{
// If the name is special 'testscript', then there is no extension,
// otherwise it is .test.
diff --git a/build2/variable b/build2/variable
index 33d33a7..aa554fe 100644
--- a/build2/variable
+++ b/build2/variable
@@ -934,7 +934,7 @@ namespace build2
const variable_visibility* = nullptr,
const bool* = nullptr) const;
- // Entities that can access bypassing the lock.
+ // Entities that can access bypassing the lock proof.
//
friend class parser;
friend class scope;
diff --git a/unit-tests/function/driver.cxx b/unit-tests/function/driver.cxx
index 2f605b0..70fd69e 100644
--- a/unit-tests/function/driver.cxx
+++ b/unit-tests/function/driver.cxx
@@ -92,7 +92,7 @@ namespace build2
try
{
- scope& s (*global_scope);
+ scope& s (*scope::global_);
parser p;
p.parse_buildfile (cin, path ("buildfile"), s, s);