aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2019-08-15 08:57:50 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2019-08-15 08:57:50 +0200
commitf303ec225c294c695711bead8310d3a7b23baade (patch)
tree5cfd74f6d119cc0fd65ea5ad355ca72b6bc971e9
parent043eb79a1085cf9df14f35c51428a975c84c9233 (diff)
Implement libs_paths symlinking support on Windows
Also, temporarily enable libs_paths::link on Windows for testing.
-rw-r--r--build2/cc/link-rule.cxx34
-rw-r--r--libbuild2/algorithm.cxx12
-rw-r--r--libbuild2/install/rule.cxx44
3 files changed, 70 insertions, 20 deletions
diff --git a/build2/cc/link-rule.cxx b/build2/cc/link-rule.cxx
index c9e4ee3..f2ee33f 100644
--- a/build2/cc/link-rule.cxx
+++ b/build2/cc/link-rule.cxx
@@ -413,6 +413,10 @@ namespace build2
append_ext (ip);
li.derive_path (move (ip), tsys == "mingw32" ? "a" : "lib");
}
+
+ //@@ TMP
+ lk = b;
+ append_ext (lk);
}
else if (!v.empty ())
{
@@ -2823,7 +2827,8 @@ namespace build2
if (lt.shared_library ())
{
- // For shared libraries we may need to create a bunch of symlinks.
+ // For shared libraries we may need to create a bunch of symlinks (or
+ // fallback to hardlinks/copies on Windows).
//
auto ln = [] (const path& f, const path& l)
{
@@ -2835,16 +2840,29 @@ namespace build2
try
{
- // The -f part.
- //
- if (file_exists (l, false /* follow_symlinks */))
- try_rmfile (l);
+ try
+ {
+ // The -f part.
+ //
+ if (file_exists (l, false /* follow_symlinks */))
+ try_rmfile (l);
- mksymlink (f, l);
+ mkanylink (f, l, true /* copy */);
+ }
+ catch (system_error& e)
+ {
+ throw pair<entry_type, system_error> (entry_type::symlink,
+ move (e));
+ }
}
- catch (const system_error& e)
+ catch (const pair<entry_type, system_error>& e)
{
- fail << "unable to create symlink " << l << ": " << e;
+ const char* w (e.first == entry_type::regular ? "copy" :
+ e.first == entry_type::symlink ? "symlink" :
+ e.first == entry_type::other ? "hardlink" :
+ nullptr);
+
+ fail << "unable to make " << w << ' ' << l << ": " << e.second;
}
};
diff --git a/libbuild2/algorithm.cxx b/libbuild2/algorithm.cxx
index 75b0f5a..50db5d3 100644
--- a/libbuild2/algorithm.cxx
+++ b/libbuild2/algorithm.cxx
@@ -1270,15 +1270,9 @@ namespace build2
}
catch (const pair<entry_type, system_error>& e)
{
- const char* w (nullptr);
- switch (e.first)
- {
- case entry_type::regular: w = "copy"; break;
- case entry_type::symlink: w = "symlink"; break;
- case entry_type::other: w = "hardlink"; break;
- default: assert (false);
- }
-
+ const char* w (e.first == entry_type::regular ? "copy" :
+ e.first == entry_type::symlink ? "symlink" :
+ e.first == entry_type::other ? "hardlink" : nullptr);
print ();
fail << "unable to make " << w << ' ' << l << ": " << e.second;
}
diff --git a/libbuild2/install/rule.cxx b/libbuild2/install/rule.cxx
index 0b34832..90ee7cb 100644
--- a/libbuild2/install/rule.cxx
+++ b/libbuild2/install/rule.cxx
@@ -834,8 +834,10 @@ namespace build2
// We can create a symlink directly without calling ln. This, however,
// won't work if we have sudo. Also, we would have to deal with existing
// destinations (ln's -f takes care of that). So we are just going to
- // always use ln.
+ // always (sudo or not) use ln unless we are on Windows, where we will
+ // use mkanylink().
//
+#ifndef _WIN32
const char* args_a[] = {
base.sudo != nullptr ? base.sudo->c_str () : nullptr,
"ln",
@@ -855,6 +857,40 @@ namespace build2
if (!dry_run)
run (pp, args);
+#else
+ if (verb >= 2)
+ text << "ln -sf " << target.string () << ' ' << rell.string ();
+ else if (verb && verbose)
+ text << "install " << rell << " -> " << target;
+
+ if (!dry_run)
+ try
+ {
+ try
+ {
+ // The -f part.
+ //
+ if (file_exists (target, false /* follow_symlinks */))
+ try_rmfile (target);
+
+ mkanylink (target, rell, true /* copy */);
+ }
+ catch (system_error& e)
+ {
+ throw pair<entry_type, system_error> (entry_type::symlink,
+ move (e));
+ }
+ }
+ catch (const pair<entry_type, system_error>& e)
+ {
+ const char* w (e.first == entry_type::regular ? "copy" :
+ e.first == entry_type::symlink ? "symlink" :
+ e.first == entry_type::other ? "hardlink" :
+ nullptr);
+
+ fail << "unable to make " << w << ' ' << target << ": " << e.second;
+ }
+#endif
}
target_state file_rule::
@@ -1001,7 +1037,8 @@ namespace build2
// have sudo. So we are going to do it both ways.
//
// While there is no sudo on Windows, deleting things that are being
- // used can get complicated. So we will always use rm/rmdir there.
+ // used can get complicated. So we will always use rm/rmdir from
+ // MSYS2/Cygwin which go above and beyond to accomplish the mission.
//
#ifndef _WIN32
if (base.sudo == nullptr)
@@ -1090,7 +1127,8 @@ namespace build2
text << "uninstall " << relf;
}
- // The same story as with uninstall -d.
+ // The same story as with uninstall -d (on Windows rm is also from
+ // MSYS2/Cygwin).
//
#ifndef _WIN32
if (base.sudo == nullptr)