aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2018-05-14 16:39:45 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2018-05-14 16:39:45 +0200
commit5d54628076bd7fc97e90c81b6d0df0fef4ceae20 (patch)
tree98b786107baeb5b1bef4561a00cb7d50df48e561
parent74b1b8228d3e5916a838f5399211bf49e93b5a2c (diff)
Tolerate misconfigured src_root in info and disfigure meta-operations
-rw-r--r--build2/b.cxx71
-rw-r--r--build2/config/operation.cxx2
-rw-r--r--build2/dist/operation.cxx1
-rw-r--r--build2/file.cxx81
-rw-r--r--build2/file.hxx5
-rw-r--r--build2/operation.cxx3
-rw-r--r--build2/operation.hxx6
7 files changed, 126 insertions, 43 deletions
diff --git a/build2/b.cxx b/build2/b.cxx
index ba84b1c..70fb470 100644
--- a/build2/b.cxx
+++ b/build2/b.cxx
@@ -842,14 +842,30 @@ main (int argc, char* argv[])
// If we also have src_root specified by the user, make sure
// they match.
//
- const dir_path& p (cast<dir_path> (v));
+ dir_path& p (cast<dir_path> (v));
if (src_root.empty ())
src_root = p;
else if (src_root != p)
{
- fail << "bootstrapped src_root " << p << " does not match "
- << (forwarded ? "forwarded " : "specified ") << src_root;
+ // We used to fail here but that meant there were no way to
+ // actually fix the problem (i.e., remove a forward or
+ // reconfigure the out directory). So now we warn (unless
+ // quiet, which is helful to tools like the package manager
+ // that are running info underneath).
+ //
+ // We also save the old/new values since we may have to remap
+ // src_root for subprojects (amalgamations are handled by not
+ // loading outer project for disfigure and info).
+ //
+ if (verb)
+ warn << "configured src_root " << p << " does not match "
+ << (forwarded ? "forwarded " : "specified ")
+ << src_root;
+
+ new_src_root = src_root;
+ old_src_root = move (p);
+ p = src_root;
}
}
else
@@ -921,15 +937,6 @@ main (int argc, char* argv[])
}
}
- // Create and bootstrap outer roots if any. Loading is done
- // by load_root_pre() (that would normally be called by the
- // meta-operation's load() callback below).
- //
- create_bootstrap_outer (rs);
-
- if (!bstrapped)
- bootstrap_post (rs);
-
// The src bootstrap should have loaded all the modules that
// may add new meta/operations. So at this stage they should
// all be known. We store the combined action id in uint8_t;
@@ -976,7 +983,8 @@ main (int argc, char* argv[])
// If this is the first target in the meta-operation batch, then
// set the batch meta-operation id.
//
- if (mid == 0)
+ bool first (mid == 0);
+ if (first)
{
mid = m;
mif = rs.meta_operations[m];
@@ -984,18 +992,6 @@ main (int argc, char* argv[])
if (mif == nullptr)
fail (l) << "target " << tn << " does not support meta-"
<< "operation " << meta_operation_table[m].name;
-
- l5 ([&]{trace << "start meta-operation batch " << mif->name
- << ", id " << static_cast<uint16_t> (mid);});
-
- if (mif->meta_operation_pre != nullptr)
- mif->meta_operation_pre (mparams, l);
- else if (!mparams.empty ())
- fail (l) << "unexpected parameters for meta-operation "
- << mif->name;
-
- set_current_mif (*mif);
- dirty = true;
}
//
// Otherwise, check that all the targets in a meta-operation
@@ -1014,6 +1010,31 @@ main (int argc, char* argv[])
<< mif->name << " in the same meta-operation batch";
}
+ // Create and bootstrap outer roots if any. Loading is done by
+ // load_root() (that would be called by the meta-operation's
+ // load() callback below).
+ //
+ if (mif->bootstrap_outer)
+ create_bootstrap_outer (rs);
+
+ if (!bstrapped)
+ bootstrap_post (rs);
+
+ if (first)
+ {
+ l5 ([&]{trace << "start meta-operation batch " << mif->name
+ << ", id " << static_cast<uint16_t> (mid);});
+
+ if (mif->meta_operation_pre != nullptr)
+ mif->meta_operation_pre (mparams, l);
+ else if (!mparams.empty ())
+ fail (l) << "unexpected parameters for meta-operation "
+ << mif->name;
+
+ set_current_mif (*mif);
+ dirty = true;
+ }
+
// If this is the first target in the operation batch, then set
// the batch operation id.
//
diff --git a/build2/config/operation.cxx b/build2/config/operation.cxx
index cdf2f9a..54e3211 100644
--- a/build2/config/operation.cxx
+++ b/build2/config/operation.cxx
@@ -562,6 +562,7 @@ namespace build2
"configuring",
"configured",
"is configured",
+ true, // bootstrap_outer
&configure_pre, // meta-operation pre
&configure_operation_pre,
&configure_load, // normal load unless configuring forward
@@ -810,6 +811,7 @@ namespace build2
"disfiguring",
"disfigured",
"is disfigured",
+ false, // bootstrap_outer
disfigure_pre, // meta-operation pre
&disfigure_operation_pre,
&disfigure_load,
diff --git a/build2/dist/operation.cxx b/build2/dist/operation.cxx
index 659b7b8..8921b7b 100644
--- a/build2/dist/operation.cxx
+++ b/build2/dist/operation.cxx
@@ -630,6 +630,7 @@ namespace build2
"distributing",
"distributed",
"has nothing to distribute", // We cannot "be distributed".
+ true, // bootstrap_outer
nullptr, // meta-operation pre
&dist_operation_pre,
&load, // normal load
diff --git a/build2/file.cxx b/build2/file.cxx
index 7cc6b5e..cadcc29 100644
--- a/build2/file.cxx
+++ b/build2/file.cxx
@@ -96,6 +96,23 @@ namespace build2
return make_pair (dir_path (), false);
}
+ dir_path old_src_root;
+ dir_path new_src_root;
+
+ // Remap the src_root variable value if it is inside old_src_root.
+ //
+ static inline void
+ remap_src_root (value& v)
+ {
+ if (!old_src_root.empty ())
+ {
+ dir_path& d (cast<dir_path> (v));
+
+ if (d.sub (old_src_root))
+ d = new_src_root / d.leaf (old_src_root);
+ }
+ }
+
static void
source (scope& root, scope& base, const path& bf, bool boot)
{
@@ -444,32 +461,50 @@ namespace build2
{
tracer trace ("find_project_name");
+ // First check if the root scope for this project has already been setup
+ // in which case we will have src_root and maybe even the name.
+ //
+ const dir_path* src_root (nullptr);
+ const scope& s (scopes.find (out_root));
+
+ if (s.root_scope () == &s && s.out_path () == out_root)
+ {
+ if (lookup l = s.vars[var_project])
+ return cast<string> (l);
+
+ src_root = s.src_path_;
+ }
+
// Load the project name. If this subdirectory is the subproject's
- // src_root, then we can get directly to that. Otherwise, we first
- // have to discover its src_root.
+ // src_root, then we can get directly to that. Otherwise, we first have to
+ // discover its src_root.
//
- const dir_path* src_root;
value src_root_v; // Need it to live until the end.
- if (src_hint != nullptr ? *src_hint : is_src_root (out_root))
- src_root = &out_root;
- else
+ if (src_root == nullptr)
{
- path f (out_root / src_root_file);
-
- if (!fallback_src_root.empty () && !exists (f))
- src_root = &fallback_src_root;
+ if (src_hint != nullptr ? *src_hint : is_src_root (out_root))
+ src_root = &out_root;
else
{
- auto p (extract_variable (f, *var_src_root));
+ path f (out_root / src_root_file);
+
+ if (!fallback_src_root.empty () && !exists (f))
+ src_root = &fallback_src_root;
+ else
+ {
+ auto p (extract_variable (f, *var_src_root));
+
+ if (!p.second)
+ fail << "variable src_root expected as first line in " << f;
- if (!p.second)
- fail << "variable src_root expected as first line in " << f;
+ src_root_v = move (p.first);
+ remap_src_root (src_root_v); // Remap if inside old_src_root.
+ src_root = &cast<dir_path> (src_root_v);
- src_root_v = move (p.first);
- src_root = &cast<dir_path> (src_root_v);
- l5 ([&]{trace << "extracted src_root " << *src_root << " for "
- << out_root;});
+ l5 ([&]{trace << "extracted src_root " << *src_root
+ << " for " << out_root;});
+ }
}
}
@@ -871,6 +906,8 @@ namespace build2
v = move (src_root);
}
}
+ else
+ remap_src_root (v); // Remap if inside old_src_root.
setup_root (rs, forwarded (root, out_root, v.as<dir_path> ()));
bootstrap_pre (rs);
@@ -917,9 +954,13 @@ namespace build2
value& v (rs.assign (var_src_root));
if (!v)
+ {
v = is_src_root (out_root)
? out_root
: (root.src_path () / p.second);
+ }
+ else
+ remap_src_root (v); // Remap if inside old_src_root.
setup_root (rs, forwarded (root, out_root, v.as<dir_path> ()));
bootstrap_pre (rs);
@@ -1234,10 +1275,14 @@ namespace build2
auto l (root->vars[*var_src_root]);
if (l)
{
+ // Note that unlike main() here we fail hard. The idea is that if
+ // the project we are importing is misconfigured, then it should be
+ // fixed first.
+ //
const dir_path& p (cast<dir_path> (l));
if (!src_root.empty () && p != src_root)
- fail (loc) << "bootstrapped src_root " << p << " does not match "
+ fail (loc) << "configured src_root " << p << " does not match "
<< "discovered " << src_root;
}
else
diff --git a/build2/file.hxx b/build2/file.hxx
index 23362c8..08d089d 100644
--- a/build2/file.hxx
+++ b/build2/file.hxx
@@ -57,6 +57,11 @@ namespace build2
pair<dir_path, bool>
find_out_root (const dir_path&);
+ // The old/new src_root paths. See main() (where they are set) for details.
+ //
+ extern dir_path old_src_root;
+ extern dir_path new_src_root;
+
// If buildfile is '-', then read from STDIN.
//
void
diff --git a/build2/operation.cxx b/build2/operation.cxx
index 10ae6e7..56f2979 100644
--- a/build2/operation.cxx
+++ b/build2/operation.cxx
@@ -52,6 +52,7 @@ namespace build2
"", // to do anything.
"",
"",
+ true, // bootstrap_outer
nullptr, // meta-operation pre
nullptr, // operation pre
&load,
@@ -416,6 +417,7 @@ namespace build2
"",
"",
"",
+ true, // bootstrap_outer
nullptr, // meta-operation pre
nullptr, // operation pre
&load,
@@ -507,6 +509,7 @@ namespace build2
"",
"",
"",
+ false, // bootstrap_outer
nullptr, // meta-operation pre
&info_operation_pre,
&info_load,
diff --git a/build2/operation.hxx b/build2/operation.hxx
index fd8ca0c..d70db28 100644
--- a/build2/operation.hxx
+++ b/build2/operation.hxx
@@ -253,6 +253,12 @@ namespace build2
const string name_did; // E.g., 'configured'.
const string name_done; // E.g., 'is configured'.
+ // Whether to bootstrap outer projects. If load() below calls load_root(),
+ // then this must be true. Note that this happens before
+ // meta_operation_pre() is called.
+ //
+ const bool bootstrap_outer;
+
// The first argument in all the callback is the meta-operation
// parameters.
//