aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/file.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2/file.cxx')
-rw-r--r--libbuild2/file.cxx159
1 files changed, 94 insertions, 65 deletions
diff --git a/libbuild2/file.cxx b/libbuild2/file.cxx
index f834d8c..14b60bd 100644
--- a/libbuild2/file.cxx
+++ b/libbuild2/file.cxx
@@ -2004,9 +2004,8 @@ namespace build2
if (!opt)
{
- diag_record dr;
- dr << error (loc) << "invalid metadata signature in " << args[0]
- << " output" <<
+ diag_record dr (error (loc));
+ dr << "invalid metadata signature in " << args[0] << " output" <<
info << "expected '" << s << "'";
if (verb >= 1 && verb <= 2)
@@ -2042,8 +2041,8 @@ namespace build2
//
if (!opt)
{
- diag_record dr;
- dr << error (loc) << "unable to extract metadata from " << args[0] <<
+ diag_record dr (error (loc));
+ dr << "unable to extract metadata from " << args[0] <<
info << "process " << args[0] << " " << *pr.exit;
if (verb >= 1 && verb <= 2)
@@ -2111,14 +2110,17 @@ namespace build2
dr << info << "use config.import." << pv << " configuration variable to "
<< "specify its " << (qual != nullptr ? qual : "") << "project out_root";
- // Suggest ad hoc import but only if it's a path-based target (doing it
- // for lib{} is very confusing).
+ // Suggest ad hoc import. Note that now we do it even for non-path-based
+ // targets since we have ad hoc import phase 2 logic for lib{}.
//
- if (tt != nullptr && tt->is_a<path_target> ())
+ if (tt != nullptr)
{
- string v (tt->is_a<exe> () && (pv == tn || pn == tn)
+ string nv (sanitize_identifier (tn));
+
+ string v (tt->is_a<exe> () && pv == nv
? "config." + pv
- : "config.import." + pv + '.' + tn + '.' + tt->name);
+ : ("config.import." + pv + '.' + nv + '.' +
+ sanitize_identifier (tt->name)));
dr << info << "or use " << v << " configuration variable to specify "
<< "its " << (qual != nullptr ? qual : "") << "path";
@@ -2266,12 +2268,14 @@ namespace build2
// recognize the special config.<proj> (tool importation; we could
// also handle the case where <proj> is not the same as <name> via
// the config.<proj>.<name> variable). For backwards-compatibility
- // reasons, it takes precedence over config.import.
+ // reasons, it takes precedence over config.import. Note that both
+ // <name> and <type> must be sanitized to a valid identifier (think
+ // libs{build2-foo} and cli.cxx{}).
//
- // Note: see import phase 2 diagnostics if changing anything here.
+ // Note also that phase 2 import may handle these imports in an ad hoc
+ // manner (see cc::search_library() for an example).
//
- // @@ How will this work for snake-case targets, say libs{build2-foo}?
- // As well as for dot-separated target types, say, cli.cxx{}?
+ // Note: see import phase 2 diagnostics if changing anything here.
//
// @@ This duality has a nasty side-effect: if we have config.<proj>
// configured, then specifying config.<proj>.import has no effect
@@ -2330,6 +2334,8 @@ namespace build2
//
const path* p (nullptr);
+ string valv (sanitize_identifier (tgt.value));
+
if (tgt.typed ())
{
bool e (tgt.type == "exe");
@@ -2338,15 +2344,18 @@ namespace build2
// overridable variable of type path. The config.<proj> we have to
// type manually.
//
- if (e && (projv == tgt.value || proj == tgt.value))
+ if (e && projv == valv)
p = lookup (vp.insert<path> ("config." + projv), e);
if (p == nullptr)
- p = lookup (vp.insert (n + '.' + tgt.value + '.' + tgt.type), e);
+ {
+ string ttv (sanitize_identifier (tgt.type));
+ p = lookup (vp.insert (n + '.' + valv + '.' + ttv), e);
+ }
}
if (p == nullptr)
- p = lookup (vp.insert (n + '.' + tgt.value), false);
+ p = lookup (vp.insert (n + '.' + valv), false);
if (p != nullptr)
{
@@ -2356,18 +2365,29 @@ namespace build2
{
string on (move (tgt.value)); // Original name as imported.
- tgt.dir = p->directory ();
- tgt.value = p->leaf ().string ();
+ // Keep the original name if the path is (syntactically) to
+ // directory.
+ //
+ if (p->to_directory ())
+ {
+ tgt.dir = path_cast<dir_path> (*p);
+ tgt.value = on;
+ }
+ else
+ {
+ tgt.dir = p->directory ();
+ tgt.value = p->leaf ().string ();
+ }
// If the path is relative, then keep it project-qualified
// assuming import phase 2 knows what to do with it. Think:
//
// config.import.build2.b=b-boot
//
- // @@ Maybe we should still complete it if it's not simple? After
- // all, this is a path, do we want interpretations other than
- // relative to CWD? Maybe we do, who knows. Doesn't seem to
- // harm anything at the moment.
+ // Maybe we should still complete it if it's not simple? After
+ // all, this is a path, do we want interpretations other than
+ // relative to CWD? Maybe we do, who knows. Doesn't seem to harm
+ // anything at the moment. Yes, we do, see cc::search_library().
//
// Why not call import phase 2 directly here? Well, one good
// reason would be to allow for rule-specific import resolution.
@@ -2376,48 +2396,59 @@ namespace build2
tgt.proj = move (proj);
else
{
- // Enter the target and assign its path (this will most commonly
- // be some out of project file).
- //
- // @@ Should we check that the file actually exists (and cache
- // the extracted timestamp)? Or just let things take their
- // natural course?
- //
name n (tgt);
const target_type* tt (ibase.find_target_type (n, loc).first);
if (tt == nullptr)
fail (loc) << "unknown target type " << n.type << " in " << n;
- // Note: not using the extension extracted by find_target_type()
- // to be consistent with import phase 2.
- //
- target& t (insert_target (trace, ctx, *tt, *p).first);
-
- // Load the metadata, similar to import phase 2.
+ // If this is not a path-based target, then delegate to import
+ // phase 2 as above (see cc::search_library() for an example).
//
- if (meta)
+ if (!tt->is_a<path_target> ())
+ {
+ tgt.proj = move (proj);
+ }
+ else
{
- if (exe* e = t.is_a<exe> ())
+ // Enter the target and assign its path (this will most
+ // commonly be some out of project file).
+ //
+ // @@ Should we check that the file actually exists (and cache
+ // the extracted timestamp)? Or just let things take their
+ // natural course?
+ //
+
+ // Note: not using the extension extracted by
+ // find_target_type() to be consistent with import phase 2.
+ //
+ target& t (insert_target (trace, ctx, *tt, *p).first);
+
+ // Load the metadata, similar to import phase 2.
+ //
+ if (meta)
{
- if (!e->vars[ctx.var_export_metadata].defined ())
+ if (exe* e = t.is_a<exe> ())
{
- optional<string> md;
+ if (!e->vars[ctx.var_export_metadata].defined ())
{
- auto df = make_diag_frame (
- [&proj, tt, &on] (const diag_record& dr)
- {
- import_suggest (
- dr, proj, tt, on, false, "alternative ");
- });
-
- md = extract_metadata (e->process_path (),
- *meta,
- false /* optional */,
- loc);
+ optional<string> md;
+ {
+ auto df = make_diag_frame (
+ [&proj, tt, &on] (const diag_record& dr)
+ {
+ import_suggest (
+ dr, proj, tt, on, false, "alternative ");
+ });
+
+ md = extract_metadata (e->process_path (),
+ *meta,
+ false /* optional */,
+ loc);
+ }
+
+ parse_metadata (*e, move (*md), loc);
}
-
- parse_metadata (*e, move (*md), loc);
}
}
}
@@ -2664,12 +2695,10 @@ namespace build2
}
else
{
- diag_record dr;
- dr << fail (loc) << "unable to determine src_root for imported ";
- if (proj)
- dr << *proj;
- else
- dr << out_root;
+ diag_record dr (fail (loc));
+ dr << "unable to determine src_root for imported ";
+ if (proj) dr << *proj;
+ else dr << out_root;
dr << info << "consider configuring " << out_root;
}
@@ -3247,8 +3276,8 @@ namespace build2
if (opt || exist)
return nullptr;
- diag_record dr;
- dr << fail (loc) << "unable to import target " << pk;
+ diag_record dr (fail (loc));
+ dr << "unable to import target " << pk;
if (proj.empty ())
dr << info << "consider adding its installation location" <<
@@ -3295,8 +3324,8 @@ namespace build2
if (opt || exist)
return nullptr;
- diag_record dr;
- dr << fail (loc) << "unable to import target " << ns;
+ diag_record dr (fail (loc));
+ dr << "unable to import target " << ns;
import_suggest (dr, *n.proj, nullptr, string (), meta.has_value ());
}
}
@@ -3374,8 +3403,8 @@ namespace build2
if (opt)
return names {};
- diag_record dr;
- dr << fail (loc) << "unable to import target " << n;
+ diag_record dr (fail (loc));
+ dr << "unable to import target " << n;
import_suggest (dr, *n.proj, nullptr /* tt */, n.value, false);