aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2024-11-18 11:38:44 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2024-11-18 11:38:44 +0200
commitbbf670d03ee587b0794f77a39db801bad6459ca5 (patch)
treef7e144fc5a1ca83c4ee6d7a1f21039c657ef3718
parent462afa615e9f2fdff12a0ee7a36eb431ee07e141 (diff)
Only install runtime part of static library prerequisites of share libraries (GH issue #448)HEADmaster
-rw-r--r--libbuild2/bin/init.cxx8
-rw-r--r--libbuild2/bin/rule.cxx13
-rw-r--r--libbuild2/bin/rule.hxx21
-rw-r--r--libbuild2/cc/install-rule.cxx22
-rw-r--r--libbuild2/install/rule.hxx2
5 files changed, 58 insertions, 8 deletions
diff --git a/libbuild2/bin/init.cxx b/libbuild2/bin/init.cxx
index 610082e..f01adfb 100644
--- a/libbuild2/bin/init.cxx
+++ b/libbuild2/bin/init.cxx
@@ -12,7 +12,6 @@
#include <libbuild2/test/module.hxx>
-#include <libbuild2/install/rule.hxx>
#include <libbuild2/install/utility.hxx>
#include <libbuild2/bin/rule.hxx>
@@ -31,6 +30,7 @@ namespace build2
static const obj_rule obj_;
static const libul_rule libul_;
static const lib_rule lib_;
+ static const install_lib_rule install_lib_;
static const def_rule def_;
// Default config.bin.*.lib values.
@@ -631,10 +631,8 @@ namespace build2
//
if (install_loaded)
{
- auto& gr (install::group_rule::instance);
-
- r.insert<lib> (perform_install_id, "bin.lib", gr);
- r.insert<lib> (perform_uninstall_id, "bin.lib", gr);
+ r.insert<lib> (perform_install_id, "bin.lib", install_lib_);
+ r.insert<lib> (perform_uninstall_id, "bin.lib", install_lib_);
}
if (const test::module* m = rs.find_module<test::module> ("test"))
diff --git a/libbuild2/bin/rule.cxx b/libbuild2/bin/rule.cxx
index c7147bf..1fea558 100644
--- a/libbuild2/bin/rule.cxx
+++ b/libbuild2/bin/rule.cxx
@@ -218,5 +218,18 @@ namespace build2
const target* m[] = {t.a, t.s};
return execute_members (a, t, m);
}
+
+ // install_lib_rule
+ //
+ pair<const target*, uint64_t> install_lib_rule::
+ filter (const scope* is,
+ action a, const target& t, const prerequisite& p,
+ match_extra& me) const
+ {
+ if (p.is_a<lib> ())
+ return pair<const target*, uint64_t> (nullptr, 0);
+
+ return install::group_rule::filter (is, a, t, p, me);
+ }
}
}
diff --git a/libbuild2/bin/rule.hxx b/libbuild2/bin/rule.hxx
index 9dd1d14..74f4301 100644
--- a/libbuild2/bin/rule.hxx
+++ b/libbuild2/bin/rule.hxx
@@ -10,6 +10,7 @@
#include <libbuild2/rule.hxx>
#include <libbuild2/dist/rule.hxx>
+#include <libbuild2/install/rule.hxx>
#include <libbuild2/bin/export.hxx>
@@ -78,6 +79,26 @@ namespace build2
static target_state
perform (action, const target&);
};
+
+ // Install rule for lib{} group.
+ //
+ // The only difference compared to the standard install::group_rule is
+ // that it ignores the lib{} prerequisites, instead expecting the correct
+ // things to be installed via the liba{}/libs{} members. This is important
+ // due to the presence of match options (see lib{} target for details).
+ //
+ class LIBBUILD2_BIN_SYMEXPORT install_lib_rule: public install::group_rule
+ {
+ public:
+ install_lib_rule () {}
+
+ virtual pair<const target*, uint64_t>
+ filter (const scope*,
+ action, const target&, const prerequisite&,
+ match_extra&) const override;
+
+ using install::group_rule::filter; // "Unhide" to make Clang happy.
+ };
}
}
diff --git a/libbuild2/cc/install-rule.cxx b/libbuild2/cc/install-rule.cxx
index 3fede89..46764a6 100644
--- a/libbuild2/cc/install-rule.cxx
+++ b/libbuild2/cc/install-rule.cxx
@@ -109,7 +109,21 @@ namespace build2
// This is a library prerequisite of a library target and
// runtime-only begets runtime-only.
//
- if (me.cur_options == lib::option_install_runtime)
+ // @@ But it goes further: while an interface prerequisite should
+ // match the target's options, it feels an implementation can be
+ // runtime-only, at least for shared library targets (for static
+ // the consumer would still need to link the prerequisite
+ // explicitly, which means it is more like buildtime). We could
+ // probably distinguish between interface/implementation by
+ // examining the *.export.libs variable and looking for the
+ // prerequisite (or its group). Feels hairy, though. So for now we
+ // only do this for target-shared/prerequisite-static case where
+ // we can assume the prerequisite is always implementation. See GH
+ // issue #448. See also apply_posthoc() as well as
+ // libux_install_rule below.
+ //
+ if (me.cur_options == lib::option_install_runtime ||
+ (t.is_a<libs> () && pt->is_a<liba> ()))
options = lib::option_install_runtime;
}
}
@@ -315,6 +329,9 @@ namespace build2
p.match_options = lib::option_install_runtime;
else
{
+ // @@ Hm, maybe runtime should be unconditional here since a
+ // plugin is always an implementation dependency?
+ //
if (me.cur_options == lib::option_install_runtime)
p.match_options = lib::option_install_runtime;
}
@@ -493,7 +510,8 @@ namespace build2
options = lib::option_install_runtime;
else
{
- if (me.cur_options == lib::option_install_runtime)
+ if (me.cur_options == lib::option_install_runtime ||
+ (t.is_a<libus> () && pt->is_a<liba> ()))
options = lib::option_install_runtime;
}
}
diff --git a/libbuild2/install/rule.hxx b/libbuild2/install/rule.hxx
index b023af5..3dbb68d 100644
--- a/libbuild2/install/rule.hxx
+++ b/libbuild2/install/rule.hxx
@@ -119,7 +119,7 @@ namespace build2
virtual recipe
apply (action, target&, match_extra&) const override;
- group_rule (bool sto): see_through_only (sto) {}
+ group_rule (bool sto = false): see_through_only (sto) {}
static const group_rule instance;
bool see_through_only;