diff options
Diffstat (limited to 'libbuild2/file.cxx')
-rw-r--r-- | libbuild2/file.cxx | 159 |
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); |