aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2022-09-06 17:09:06 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2022-09-06 17:09:06 +0200
commit7595381c1a6aa75eedae3c982d923ba4154c8e32 (patch)
treeb94b4e290dc974308706282e1702fffe55160f89
parent52296a1e3e57bdfa80003f37b63f4f263734e2c0 (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.
-rw-r--r--libbuild2/dist/init.cxx21
-rw-r--r--libbuild2/dist/operation.cxx110
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