diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2022-09-06 17:09:06 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2022-09-06 17:09:06 +0200 |
commit | 7595381c1a6aa75eedae3c982d923ba4154c8e32 (patch) | |
tree | b94b4e290dc974308706282e1702fffe55160f89 /libbuild2/dist | |
parent | 52296a1e3e57bdfa80003f37b63f4f263734e2c0 (diff) |
Add ability to remap paths in distribution
Specifically, the dist target-specific variable now can specify a path
besides true or false. This path is the "imaginary" source location which
is used to derive the corresponding distribution local. This location can
be either a directory path (to remap with the same file name) or a file
path (to remap with a different name). If the path is relative, then it's
treated relative to the target directory. Note that to make things less
error prone, simple paths without any directory separators are not allowed
(use ./<name> instead).
Note that if multiple targets end up with the same source location, the
behavior is undefined and no diagnostics is issued.
Note also that such remapping has no effect in the bootstrap distribution
mode.
Diffstat (limited to 'libbuild2/dist')
-rw-r--r-- | libbuild2/dist/init.cxx | 21 | ||||
-rw-r--r-- | libbuild2/dist/operation.cxx | 110 |
2 files changed, 102 insertions, 29 deletions
diff --git a/libbuild2/dist/init.cxx b/libbuild2/dist/init.cxx index 2b2aaa4..dd8e25b 100644 --- a/libbuild2/dist/init.cxx +++ b/libbuild2/dist/init.cxx @@ -71,7 +71,26 @@ namespace build2 vp.insert<paths> ("dist.archives"); vp.insert<paths> ("dist.checksums"); - vp.insert<bool> ("dist", variable_visibility::target); // Flag. + // The dist flag or path. Normally it is a flag (true or false) but can + // also be used to remap the distribution location. + // + // In the latter case it specifies the "imaginary" source location which + // is used to derive the corresponding distribution local. This location + // can be specified as either a directory path (to remap with the same + // file name) or a file path (to remap with a different name). And the + // way we distinguish between the two is via the presence/absence of the + // trailing directory separator. If the path is relative, then it's + // treated relative to the target directory. Note that to make things + // less error prone, simple paths without any directory separators are + // not allowed (use ./<name> instead). + // + // Note that if multiple targets end up with the same source location, + // the behavior is undefined and no diagnostics is issued. + // + // Note also that such remapping has no effect in the bootstrap + // distribution mode. + // + vp.insert<path> ("dist", variable_visibility::target); // Project's package name. Note: if set, must be in bootstrap.build. // diff --git a/libbuild2/dist/operation.cxx b/libbuild2/dist/operation.cxx index 87710d6..468f7bd 100644 --- a/libbuild2/dist/operation.cxx +++ b/libbuild2/dist/operation.cxx @@ -27,14 +27,14 @@ namespace build2 // install -d <dir> // static void - install (const process_path& cmd, const dir_path&); + install (const process_path&, const dir_path&); - // install <file> <dir> + // install <file> <dir>[/<name>] // // Return the destination file path. // static path - install (const process_path& cmd, const file&, const dir_path&); + install (const process_path&, const file&, const dir_path&, const path&); // tar|zip ... <dir>/<pkg>.<ext> <pkg> // @@ -254,10 +254,13 @@ namespace build2 // action_targets files; + const variable* dist_var (nullptr); if (tgt != nullptr) { l5 ([&]{trace << "load dist " << rs;}); + dist_var = ctx.var_pool.find ("dist"); + // Match a rule for every operation supported by this project. Skip // default_id. // @@ -392,8 +395,6 @@ namespace build2 // Note that we are not showing progress here (e.g., "N targets to // distribute") since it will be useless (too fast). // - const variable& dist_var (ctx.var_pool["dist"]); - for (const auto& pt: ctx.targets) { file* ft (pt->is_a<file> ()); @@ -405,29 +406,29 @@ namespace build2 { // Include unless explicitly excluded. // - auto l ((*ft)[dist_var]); - - if (l && !cast<bool> (l)) - l5 ([&]{trace << "excluding " << *ft;}); - else - files.push_back (ft); + if (const path* v = cast_null<path> ((*ft)[dist_var])) + { + if (v->string () == "false") + { + l5 ([&]{trace << "excluding " << *ft;}); + continue; + } + } - continue; + files.push_back (ft); } - - if (ft->dir.sub (out_root)) + else if (ft->dir.sub (out_root)) { // Exclude unless explicitly included. // - auto l ((*ft)[dist_var]); - - if (l && cast<bool> (l)) + if (const path* v = cast_null<path> ((*ft)[dist_var])) { - l5 ([&]{trace << "including " << *ft;}); - files.push_back (ft); + if (v->string () != "false") + { + l5 ([&]{trace << "including " << *ft;}); + files.push_back (ft); + } } - - continue; } } @@ -518,14 +519,61 @@ namespace build2 // Figure out where this file is inside the target directory. // - bool src (t.dir.sub (src_root)); - dir_path dl (src ? t.dir.leaf (src_root) : t.dir.leaf (out_root)); + // First see if the path has been remapped (unless bootstrap). + // + const path* rp (nullptr); + if (tgt != nullptr) + { + if ((rp = cast_null<path> (t[dist_var])) != nullptr) + { + if (rp->string () == "true") // Wouldn't be here if false. + rp = nullptr; + } + } + + bool src; + path rn; + dir_path dl; + if (rp == nullptr) + { + src = t.dir.sub (src_root); + dl = src ? t.dir.leaf (src_root) : t.dir.leaf (out_root); + } + else + { + // Sort the remapped path into name (if any) and directory, + // completing the latter if relative. + // + bool n (!rp->to_directory ()); + + if (n) + { + if (rp->simple ()) + { + fail << "expected true, false, of path in the dist variable " + << "value of target " << t << + info << "specify ./" << *rp << " to remap the name"; + } + + rn = rp->leaf (); + } + + dir_path rd (n ? rp->directory () : path_cast<dir_path> (*rp)); + + if (rd.relative ()) + rd = t.dir / rd; + + rd.normalize (); + + src = rd.sub (src_root); + dl = src ? rd.leaf (src_root) : rd.leaf (out_root); + } dir_path d (td / dl); if (!exists (d)) install (dist_cmd, d); - path r (install (dist_cmd, t, d)); + path r (install (dist_cmd, t, d, rn)); // See if this file is in a subproject. // @@ -696,14 +744,20 @@ namespace build2 run (cmd, args); } - // install <file> <dir> + // install <file> <dir>[/<name>] // static path - install (const process_path& cmd, const file& t, const dir_path& d) + install (const process_path& cmd, + const file& t, + const dir_path& d, + const path& n) { - dir_path reld (relative (d)); + path reld (relative (d)); path relf (relative (t.path ())); + if (!n.empty ()) + reld /= n.string (); + cstrings args {cmd.recall_string ()}; // Preserve timestamps. This could becomes important if, for @@ -732,7 +786,7 @@ namespace build2 run (cmd, args); - return d / relf.leaf (); + return d / (n.empty () ? relf.leaf () : n); } static path |