aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-08-02 11:18:38 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-08-02 11:33:51 +0200
commite65c406301c3a7b30174f8706ba39584e80ddf25 (patch)
tree39ab598476f4965616979f498e016e3f7913008c
parente8ef2fbd339afd8113bd92d371bc49d7d570c32f (diff)
Save module map to pkg-config files
-rw-r--r--build2/cc/compile.cxx6
-rw-r--r--build2/cc/pkgconfig.cxx50
-rw-r--r--build2/install/rule.cxx25
-rw-r--r--build2/install/utility.hxx6
-rw-r--r--build2/target.hxx9
5 files changed, 91 insertions, 5 deletions
diff --git a/build2/cc/compile.cxx b/build2/cc/compile.cxx
index 6c3cc4c..9f36e8b 100644
--- a/build2/cc/compile.cxx
+++ b/build2/cc/compile.cxx
@@ -2766,8 +2766,8 @@ namespace build2
// name for each mxx{} explicitly. This will be a major pain, however.
// Another would be to require encoding of the module name in the
// interface unit file name. For example, hello.core -> hello-core.mxx.
- // This is better but will still too restrictive: some will want to call
- // it hello_core.mxx or HelloCore.mxx (because that's their file naming
+ // This is better but still too restrictive: some will want to call it
+ // hello_core.mxx or HelloCore.mxx (because that's their file naming
// convention) or place it in a subdirectory, say, hello/core.mxx.
//
// In the above examples one common theme about all the file names is
@@ -3010,6 +3010,8 @@ namespace build2
// available.
//
// @@ MOD: BMI compatibility check.
+ // @@ UTL: we need to (recursively) see through libux{} (and
+ // also in pkgconfig_save()).
//
if (bt != nullptr &&
(bt->is_a<bmis> () ||
diff --git a/build2/cc/pkgconfig.cxx b/build2/cc/pkgconfig.cxx
index 8d0ea25..d320060 100644
--- a/build2/cc/pkgconfig.cxx
+++ b/build2/cc/pkgconfig.cxx
@@ -733,6 +733,56 @@ namespace build2
os << endl;
+ // If we have modules, list them in the modules variable. This code
+ // is pretty similar to compiler::search_modules().
+ //
+ if (modules)
+ {
+ os << endl
+ << "modules =";
+
+ for (const target* pt: l.prerequisite_targets)
+ {
+ // @@ UTL: we need to (recursively) see through libux{} (and
+ // also in search_modules()).
+ //
+ if (pt != nullptr &&
+ (pt->is_a<bmis> () ||
+ pt->is_a<bmia> () ||
+ pt->is_a<bmie> ()))
+ {
+ // What we have is a binary module interface. What we need is
+ // a module interface source it was built from. We assume it's
+ // the first mxx{} target that we see.
+ //
+ const target* mt (nullptr);
+ for (const target* t: pt->prerequisite_targets)
+ {
+ if ((mt = t->is_a (*x_mod)))
+ break;
+ }
+
+ // Can/should there be a bmi{} without mxx{}? Can't think of a
+ // reason.
+ //
+ assert (mt != nullptr);
+
+ path p (install::resolve_file (mt->as<file> ()));
+
+ if (p.empty ()) // Not installed.
+ continue;
+
+ const string& n (cast<string> (pt->vars[c_module_name]));
+
+ // Module name shouldn't require escaping.
+ //
+ os << ' ' << n << '=' << escape (p.string ());
+ }
+ }
+
+ os << endl;
+ }
+
os.close ();
arm.cancel ();
}
diff --git a/build2/install/rule.cxx b/build2/install/rule.cxx
index c76800a..1f14fce 100644
--- a/build2/install/rule.cxx
+++ b/build2/install/rule.cxx
@@ -399,6 +399,29 @@ namespace build2
return move (resolve (t, move (d)).back ().dir);
}
+ path
+ resolve_file (const file& f)
+ {
+ // Note: similar logic to perform_install().
+ //
+ const path* p (lookup_install<path> (f, "install"));
+
+ if (p == nullptr) // Not installable.
+ return path ();
+
+ bool n (!p->to_directory ());
+ dir_path d (n ? p->directory () : path_cast<dir_path> (*p));
+
+ install_dirs ids (resolve (f, d));
+ if (auto l = f["install.subdirs"])
+ {
+ if (cast<bool> (l))
+ resolve_subdir (ids, f, f.base_scope (), l);
+ }
+
+ return ids.back ().dir / (n ? p->leaf () : f.path ().leaf ());
+ }
+
// On Windows we use MSYS2 install.exe and MSYS2 by default ignores
// filesystem permissions (noacl mount option). And this means, for
// example, that .exe that we install won't be runnable by Windows (MSYS2
@@ -631,6 +654,8 @@ namespace build2
auto install_target = [this] (const file& t, const path& p, bool verbose)
{
+ // Note: similar logic to resolve_file().
+ //
bool n (!p.to_directory ());
dir_path d (n ? p.directory () : path_cast<dir_path> (p));
diff --git a/build2/install/utility.hxx b/build2/install/utility.hxx
index 21c0c44..173b25c 100644
--- a/build2/install/utility.hxx
+++ b/build2/install/utility.hxx
@@ -9,6 +9,7 @@
#include <build2/utility.hxx>
#include <build2/scope.hxx>
+#include <build2/target.hxx>
namespace build2
{
@@ -57,6 +58,11 @@ namespace build2
//
dir_path
resolve_dir (const target&, dir_path); // rule.cxx
+
+ // Resolve file installation path returning empty path if not installable.
+ //
+ path
+ resolve_file (const file&); // rule.cxx
}
}
diff --git a/build2/target.hxx b/build2/target.hxx
index 3af533f..94fb800 100644
--- a/build2/target.hxx
+++ b/build2/target.hxx
@@ -640,8 +640,9 @@ namespace build2
// Target type info and casting.
//
public:
- bool
- is_a (const target_type& tt) const {return type ().is_a (tt);}
+ const target*
+ is_a (const target_type& tt) const {
+ return type ().is_a (tt) ? this : nullptr;}
template <typename T>
T*
@@ -871,7 +872,9 @@ namespace build2
bool
is_a (const target_type_type& tt) const
{
- return target != nullptr ? target->is_a (tt) : prerequisite.is_a (tt);
+ return target != nullptr
+ ? target->is_a (tt) != nullptr
+ : prerequisite.is_a (tt);
}
prerequisite_key