aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2024-01-10 12:02:13 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2024-01-10 12:02:13 +0200
commit7197d069cb82286f9789a8ce987fe5f0f5b6f05d (patch)
tree590c7af8bd552f0b377c8550eab54302299a6753
parent293aed4d3b9bafd0ffb30de095ab955615434e67 (diff)
Add ability to specify alternative sysroot for pkg-config files (GC issue #59)
Specifically, the new config.cc.pkgconfig.sysroot variable provides roughly equivalent functionality to PKG_CONFIG_SYSROOT_DIR in pkg-config. For details and limitations, see "Rewriting Installed Libraries System Root (sysroot)" in the manual for details.
-rw-r--r--doc/manual.cli49
-rw-r--r--libbuild2/cc/init.cxx18
-rw-r--r--libbuild2/cc/pkgconfig.cxx51
3 files changed, 114 insertions, 4 deletions
diff --git a/doc/manual.cli b/doc/manual.cli
index f24b429..66d0ffb 100644
--- a/doc/manual.cli
+++ b/doc/manual.cli
@@ -7585,6 +7585,11 @@ config.cc.libs
config.cc.internal.scope
cc.internal.scope
+
+config.cc.reprocess
+ cc.reprocess
+
+config.cc.pkgconfig.sysroot
\
Note that the compiler mode options are \"cross-hinted\" between \c{config.c}
@@ -7946,6 +7951,50 @@ prerequisite library, resolved using the above algorithm, and linked. In other
words, in this case we end up with a binless library \c{lib{znonsense\}} that
depends on \c{lib{z\}} instead of a single \c{lib{z\}} library.
+\h2#cc-import-installed-sysroot|Rewriting Installed Libraries System Root (sysroot)|
+
+Sometimes the installed libraries are moved to a different location after the
+installation. This is especially common in embedded development where the code
+is normally cross-compiled and the libraries for the target platform are
+placed into a host directory, called system root or \i{sysroot}, that doesn't
+match where these libraries were originally installed to. For example, the
+libraries might have been installed into \c{/usr/} but on the host machine
+they may reside in \c{/opt/target/usr/}. In this example, \c{/opt/target/} is
+the sysroot.
+
+While such relocations usually do not affect the library headers or binaries,
+they do break the \c{pkg-config}'s \c{.pc} files which often contain \c{-I}
+and \c{-L} options with absolute paths. Continue with the above example, a
+\c{.pc} file as originally installed may contain \c{-I/usr/include} and
+\c{-L/usr/lib} while now, that the libraries have been relocated to
+\c{/opt/target/}, they somehow need to be adjusted to
+\c{-I/opt/target/usr/include} and \c{-L/opt/target/usr/lib}.
+
+While it is possible (and perhaps correct) to accomplish this by fixing the
+\c{.pc} files to match the new location, it is not always possible or easy.
+As a result, \c{build2} provides a mechanism for automatically adjusting the
+system root in the \c{-I} and \c{-L} options extracted from \c{.pc} files.
+
+\N|This functionality is roughly equivalent to that provided with the
+\c{PKG_CONFIG_SYSROOT_DIR} environment variable by the \c{pkg-config}
+utility.|
+
+Specifically, the \c{config.cc.pkgconfig.sysroot} variable can be used to
+specify an alternative system root. When specified, all absolute paths in the
+\c{-I} and \c{-L} options that are not already in this directory will be
+rewritten to start with this sysroot.
+
+\N|Note that this mechanism is a workaround rather than a proper solution since
+it is limited to the \c{-I} and \c{-L} options. In particular, it does not
+handle any other options that may contain absolute paths nor \c{pkg-config}
+variables that may be queried.
+
+As a result, it should only be used for dealing with issues in third-party
+\c{.pc} files that do not handle relocation (for example, using the
+\c{${pcfiledir\}} built-in \c{pkg-config} variable). In particular, for
+\c{build2}-generated \c{.pc} files a \l{#install-reloc relocatable
+installation} should be used instead.|
+
\h#cc-gcc|GCC Compiler Toolchain|
diff --git a/libbuild2/cc/init.cxx b/libbuild2/cc/init.cxx
index d766b30..1bddbb2 100644
--- a/libbuild2/cc/init.cxx
+++ b/libbuild2/cc/init.cxx
@@ -100,13 +100,19 @@ namespace build2
vp.insert<strings> ("config.cc.loptions");
vp.insert<strings> ("config.cc.aoptions");
vp.insert<strings> ("config.cc.libs");
- vp.insert<string> ("config.cc.internal.scope");
+
+ vp.insert<string> ("config.cc.internal.scope");
+
+ vp.insert<bool> ("config.cc.reprocess"); // See cc.preprocess below.
+
+ vp.insert<abs_dir_path> ("config.cc.pkgconfig.sysroot");
vp.insert<strings> ("cc.poptions");
vp.insert<strings> ("cc.coptions");
vp.insert<strings> ("cc.loptions");
vp.insert<strings> ("cc.aoptions");
vp.insert<strings> ("cc.libs");
+
vp.insert<string> ("cc.internal.scope");
vp.insert<strings> ("cc.internal.libs");
@@ -177,7 +183,6 @@ namespace build2
// Ability to disable using preprocessed output for compilation.
//
- vp.insert<bool> ("config.cc.reprocess");
vp.insert<bool> ("cc.reprocess");
// Register scope operation callback.
@@ -337,6 +342,15 @@ namespace build2
if (lookup l = lookup_config (rs, "config.cc.reprocess"))
rs.assign ("cc.reprocess") = *l;
+ // config.cc.pkgconfig.sysroot
+ //
+ // Let's look it up instead of just marking for saving to make sure the
+ // path is valid.
+ //
+ // Note: save omitted.
+ //
+ lookup_config (rs, "config.cc.pkgconfig.sysroot");
+
// Load the bin.config module.
//
if (!cast_false<bool> (rs["bin.config.loaded"]))
diff --git a/libbuild2/cc/pkgconfig.cxx b/libbuild2/cc/pkgconfig.cxx
index b0b9675..ff84dc4 100644
--- a/libbuild2/cc/pkgconfig.cxx
+++ b/libbuild2/cc/pkgconfig.cxx
@@ -316,9 +316,15 @@ namespace build2
assert (!ap.empty () || !sp.empty ());
- // Append -I<dir> or -L<dir> option suppressing duplicates.
+ const scope& rs (*s.root_scope ());
+
+ const dir_path* sysroot (
+ cast_null<abs_dir_path> (rs["config.cc.pkgconfig.sysroot"]));
+
+ // Append -I<dir> or -L<dir> option suppressing duplicates. Also handle
+ // the sysroot rewrite.
//
- auto append_dir = [] (strings& ops, string&& o)
+ auto append_dir = [sysroot] (strings& ops, string&& o)
{
char c (o[1]);
@@ -337,6 +343,47 @@ namespace build2
// Note that we do normalize -L paths in the usrd logic later
// (but not when setting as *.export.loptions).
+ if (sysroot != nullptr)
+ {
+ // Notes:
+ //
+ // - The path might not be absolute (we only rewrite absolute ones).
+ //
+ // - Do this before duplicate suppression since options in ops
+ // already have the sysroot rewritten.
+ //
+ // - Check if the path already starts with sysroot since some .pc
+ // files might already be in a good shape (e.g., because they use
+ // ${pcfiledir} to support relocation properly).
+ //
+ const char* op (o.c_str () + 2);
+ size_t on (o.size () - 2);
+
+ if (path_traits::absolute (op, on))
+ {
+ const string& s (sysroot->string ());
+
+ const char* sp (s.c_str ());
+ size_t sn (s.size ());
+
+ if (!path_traits::sub (op, on, sp, sn)) // Already in sysroot.
+ {
+ // Find the first directory seperator that seperates the root
+ // component from the rest of the path (think /usr/include,
+ // c:\install\include). We need to replace the root component
+ // with sysroot. If there is no separator (say, -Ic:) or the
+ // path after the separator is empty (say, -I/), then we replace
+ // the entire path.
+ //
+ size_t p (path_traits::find_separator (o, 2));
+ if (p == string::npos || p + 1 == o.size ())
+ p = o.size ();
+
+ o.replace (2, p - 2, s);
+ }
+ }
+ }
+
for (const string& x: ops)
{
if (x.size () > 2 && x[0] == '-' && x[1] == c)