diff options
Diffstat (limited to 'libbuild2')
-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 |