Page MenuHome GnuPG

build failure with slibtool - error: undefined symbol: QGpgME::RevokeKeyJob::staticMetaObject
Closed, ResolvedPublic

Description

When building gpgme with slibtool the build fails when building t-revokekey in the lang/qt/tests/ directory with undefined references for QGpgME::RevokeKeyJob::result and QGpgME::RevokeKeyJob::staticMetaObject.

I think this is because they are defined in lang/qt/src/revokekeyjob.moc and t-revokekey never includes this moc header. I tried this, but unfortunately I don't know what I am doing with qt so while the undefined references were resolved, the actual test failed with a segfault.

I am unsure how GNU libtool silently ignores the undefined references in this case. Additionally, this issue only occurs under special circumstances which I also don't quite understand. So far it seems to only occur when updating gpgme and building a working version with GNU libtool will hide the issue even if gpgme is removed from the system and rebuilt.

Any help would be greatly appreciated!

--- a/lang/qt/tests/t-revokekey.cpp
+++ b/lang/qt/tests/t-revokekey.cpp
@@ -336,3 +336,13 @@ private:
 QTEST_MAIN(RevokeKeyJobTest)
 
 #include "t-revokekey.moc"
+
+#define make_job_subclass_ext(x,y)                \
+    QGpgME::x::x( QObject * parent ) : y( parent ) {} \
+    QGpgME::x::~x() {}
+
+#define make_job_subclass(x) make_job_subclass_ext(x,Job)
+
+make_job_subclass(RevokeKeyJob)
+
+#include "revokekeyjob.moc"
rdlibtool --tag=CXX --mode=link clang++ -g -O2 -no-install -o t-revokekey t-revokekey.o t-support.o ../../cpp/src/libgpgmepp.la ../src/libqgpgme.la ../../../src/libgpgme.la -lQt5Core -lgpg-error -lQt5Test -lQt5Core -lstdc++

rdlibtool: lconf: {.name="libtool"}.
rdlibtool: fdcwd: {.fdcwd=AT_FDCWD, .realpath="/tmp/gpgme-1.18.0/lang/qt/tests"}.
rdlibtool: lconf: fstatat(AT_FDCWD,".",...) = 0 {.st_dev = 45, .st_ino = 346600}.
rdlibtool: lconf: openat(AT_FDCWD,"libtool",O_RDONLY,0) = -1 [ENOENT].
rdlibtool: lconf: openat(AT_FDCWD,"../",O_DIRECTORY,0) = 3.
rdlibtool: lconf: fstat(3,...) = 0 {.st_dev = 45, .st_ino = 346598}.
rdlibtool: lconf: openat(3,"libtool",O_RDONLY,0) = -1 [ENOENT].
rdlibtool: lconf: openat(3,"../",O_DIRECTORY,0) = 4.
rdlibtool: lconf: fstat(4,...) = 0 {.st_dev = 45, .st_ino = 346436}.
rdlibtool: lconf: openat(4,"libtool",O_RDONLY,0) = -1 [ENOENT].
rdlibtool: lconf: openat(4,"../",O_DIRECTORY,0) = 3.
rdlibtool: lconf: fstat(3,...) = 0 {.st_dev = 45, .st_ino = 346258}.
rdlibtool: lconf: openat(3,"libtool",O_RDONLY,0) = 4.
rdlibtool: lconf: found "/tmp/gpgme-1.18.0/libtool".
rdlibtool: link: clang++ t-revokekey.o t-support.o -g -O2 -L../../cpp/src/.libs -lgpgmepp -L../../cpp/src/../../../src/.libs -lgpgme -L/usr/lib64 -lassuan -lgpg-error -lassuan -L../src/.libs -lqgpgme -L../src/../../cpp/src/.libs -lgpgmepp -L../src/../../cpp/src/../../../src/.libs -lgpgme -lassuan -lgpg-error -L../src/../../../src/.libs -lQt5Core -L../../../src/.libs -lgpgme -lassuan -lgpg-error -lQt5Test -lQt5Core -lstdc++ -o .libs/t-revokekey
ld.lld: error: undefined symbol: QGpgME::RevokeKeyJob::result(GpgME::Error const&, QString const&, GpgME::Error const&)
>>> referenced by char_traits.h:0 (/usr/lib/gcc/x86_64-pc-linux-gnu/11.3.0/include/g++-v11/bits/char_traits.h:0)
>>>               t-revokekey.o:(RevokeKeyJobTest::testAsync())

ld.lld: error: undefined symbol: QGpgME::RevokeKeyJob::staticMetaObject
>>> referenced by qobject.h:343 (/usr/include/qt5/QtCore/qobject.h:343)
>>>               t-revokekey.o:(RevokeKeyJobTest::testAsync())
clang-14: error: linker command failed with exit code 1 (use -v to see invocation)
rdlibtool: exec error upon slbt_exec_link_create_executable(), line 1745: (see child process error messages).
rdlibtool: < returned to > slbt_exec_link(), line 2155.
make[4]: *** [Makefile:774: t-revokekey] Error 2
make[4]: Leaving directory '/tmp/gpgme-1.18.0/lang/qt/tests'
make[3]: *** [Makefile:673: all] Error 2
make[3]: Leaving directory '/tmp/gpgme-1.18.0/lang/qt/tests'
make[2]: *** [Makefile:466: all-recursive] Error 1
make[2]: Leaving directory '/tmp/gpgme-1.18.0/lang/qt'
make[1]: *** [Makefile:463: all-recursive] Error 1
make[1]: Leaving directory '/tmp/gpgme-1.18.0/lang'
make: *** [Makefile:540: all-recursive] Error 1

Details

External Link
https://bugs.gentoo.org/844226
Version
1.18.0

Event Timeline

revokekeyjob.moc is included by job.cpp (as many other *job.moc files). The missing symbols should be available in the built libqgpgme.so. The command line

rdlibtool: link: clang++ t-revokekey.o t-support.o -g -O2 -L../../cpp/src/.libs -lgpgmepp -L../../cpp/src/../../../src/.libs -lgpgme -L/usr/lib64 -lassuan -lgpg-error -lassuan -L../src/.libs -lqgpgme -L../src/../../cpp/src/.libs -lgpgmepp -L../src/../../cpp/src/../../../src/.libs -lgpgme -lassuan -lgpg-error -L../src/../../../src/.libs -lQt5Core -L../../../src/.libs -lgpgme -lassuan -lgpg-error -lQt5Test -lQt5Core -lstdc++ -o .libs/t-revokekey

includes -L../src/.libs -lqgpgme. So it should link against the newly built library and not against an installed library.

And the symbols are there (if compiled with GNU libtool):

$ cd .../build/gpgme/lang/qt/src/.libs
$ nm -C libqgpgme.so.15 | grep QGpgME::RevokeKeyJob::staticMetaObject
00000000000ea900 D QGpgME::RevokeKeyJob::staticMetaObject
$ nm -C libqgpgme.so.15 | grep QGpgME::RevokeKeyJob::result
00000000000405c0 T QGpgME::RevokeKeyJob::result(GpgME::Error const&, QString const&, GpgME::Error const&)

Is t-revokekey the only executable for which the build fails?

ikloecker added a project: gpgme.

Hmm. There is a -L/usr/lib64 before -L../src/.libs. I guess this causes problems if there is a /usr/lib64/libqgpgme.la because this will be found before the newly built libqgpgme.la in the build directory.

For comparison: libtool does

/bin/sh ../../../libtool  --tag=CXX   --mode=link g++  -g -O2 -Wall -Wextra -Wno-shadow -no-install  -o t-revokekey t-revokekey.o t-support.o ../../cpp/src/libgpgmepp.la ../src/libqgpgme.la ../../../src/libgpgme.la -lQt5Core  -L/opt/gnupg/master/lib64 -lgpg-error -lQt5Test -lQt5Core  -Wl,--disable-new-dtags -lstdc++ 
libtool: link: g++ -g -O2 -Wall -Wextra -Wno-shadow -o t-revokekey t-revokekey.o t-support.o -Wl,--disable-new-dtags  ../../cpp/src/.libs/libgpgmepp.so ../src/.libs/libqgpgme.so ../../../src/.libs/libgpgme.so -L/opt/gnupg/master/lib64 /opt/gnupg/master/lib64/libgpg-error.so -lQt5Test -lQt5Core -lstdc++ -Wl,-rpath -Wl,/[...]/gpgme/lang/cpp/src/.libs -Wl,-rpath -Wl,/[...]/gpgme/lang/qt/src/.libs -Wl,-rpath -Wl,/[...]/gpgme/src/.libs -Wl,-rpath -Wl,/opt/gnupg/master/lib64 -Wl,-rpath -Wl,/opt/gnupg/master/lib64

i.e. it links against the newly built libgpgmepp.so, libqgpgme.so, and libgpgme.so and the -L occurs after those libraries.

revokekeyjob.moc is included by job.cpp (as many other *job.moc files). The missing symbols should be available in the built libqgpgme.so

Earlier when I was researching what was going wrong I found these references that suggest that moc really wants these to be defined by Q_OBJECT subclasses in the .h file rather than the .cpp file.

https://forum.qt.io/topic/126096/undefined-reference-to-staticmetaobject
https://stackoverflow.com/questions/54621016/undefined-reference-to-mastercontrollerstaticmetaobject/54622770#54622770

When attempting that the undefined references were resolved. This makes me think it has the symbols, but it doesn't have the definitions which are providing in the moc include.

Hmm. There is a -L/usr/lib64 before -L../src/.libs. I guess this causes problems if there is a /usr/lib64/libqgpgme.la because this will be found before the newly built libqgpgme.la in the build directory.

By default slibtool does not install any .la files to the system and the only one I have installed in /usr/lib64 is libltdl.la. Is it possibly picking up the actual .so library?

Another interesting detail is that this is reproduced when trying to update to 1.18.0 from 1.17.1 which is installed on the system, but if 1.17.1 is built without qt5 support and 1.18.0 is then this issue is not reproducible.

rdlibtool --tag=CXX --mode=link clang++ -g -O2 -no-install -o t-revokekey t-revokekey.o t-support.o ../../cpp/src/libgpgmepp.la ../src/libqgpgme.la ../../../src/libgpgme.la -lQt5Core -lgpg-error -lQt5Test -lQt5Core -lstdc++

rdlibtool: lconf: {.name="libtool"}.
rdlibtool: fdcwd: {.fdcwd=AT_FDCWD, .realpath="/tmp/gpgme-1.18.0/lang/qt/tests"}.
rdlibtool: lconf: fstatat(AT_FDCWD,".",...) = 0 {.st_dev = 45, .st_ino = 346600}.
rdlibtool: lconf: openat(AT_FDCWD,"libtool",O_RDONLY,0) = -1 [ENOENT].
rdlibtool: lconf: openat(AT_FDCWD,"../",O_DIRECTORY,0) = 3.
rdlibtool: lconf: fstat(3,...) = 0 {.st_dev = 45, .st_ino = 346598}.
rdlibtool: lconf: openat(3,"libtool",O_RDONLY,0) = -1 [ENOENT].
rdlibtool: lconf: openat(3,"../",O_DIRECTORY,0) = 4.
rdlibtool: lconf: fstat(4,...) = 0 {.st_dev = 45, .st_ino = 346436}.
rdlibtool: lconf: openat(4,"libtool",O_RDONLY,0) = -1 [ENOENT].
rdlibtool: lconf: openat(4,"../",O_DIRECTORY,0) = 3.
rdlibtool: lconf: fstat(3,...) = 0 {.st_dev = 45, .st_ino = 346258}.
rdlibtool: lconf: openat(3,"libtool",O_RDONLY,0) = 4.
rdlibtool: lconf: found "/tmp/gpgme-1.18.0/libtool".
rdlibtool: link: clang++ t-revokekey.o t-support.o -g -O2 -L../../cpp/src/.libs -lgpgmepp -L../../cpp/src/../../../src/.libs -lgpgme -L/usr/lib64 -lassuan -lgpg-error -lassuan -L../src/.libs -lqgpgme -L../src/../../cpp/src/.libs -lgpgmepp -L../src/../../cpp/src/../../../src/.libs -lgpgme -lassuan -lgpg-error -L../src/../../../src/.libs -lQt5Core -L../../../src/.libs -lgpgme -lassuan -lgpg-error -lQt5Test -lQt5Core -lstdc++ -o .libs/t-revokekey
rdlibtool: link: ln -s ../t-revokekey .libs/t-revokekey.exe.wrapper

After some experimenting I found how GNU libtool avoids this.

GNU libtool

clang++ -g -O2 -o t-revokekey t-revokekey.o t-support.o  ../../cpp/src/.libs/libgpgmepp.so -L/usr/lib64 ../src/.libs/libqgpgme.so /tmp/gpgme-1.18.0/lang/cpp/src/.libs/libgpgmepp.so /tmp/gpgme-1.18.0/src/.libs/libgpgme.so ../../../src/.libs/libgpgme.so -lassuan -lgpg-error -lQt5Test -lQt5Core -lstdc++ -Wl,-rpath -Wl,/tmp/gpgme-1.18.0/lang/cpp/src/.libs -Wl,-rpath -Wl,/tmp/gpgme-1.18.0/lang/qt/src/.libs -Wl,-rpath -Wl,/tmp/gpgme-1.18.0/src/.libs

slibtool

clang++ t-revokekey.o t-support.o -g -O2 -L../../cpp/src/.libs -lgpgmepp -L../../cpp/src/../../../src/.libs -lgpgme -L/usr/lib64 -lassuan -lgpg-error -lassuan -L../src/.libs -lqgpgme -L../src/../../cpp/src/.libs -lgpgmepp -L../src/../../cpp/src/../../../src/.libs -lgpgme -lassuan -lgpg-error -L../src/../../../src/.libs -lQt5Core -L../../../src/.libs -lgpgme -lassuan -lgpg-error -lQt5Test -lQt5Core -lstdc++ -o .libs/t-revokekey

GNU libtool is using ../src/.libs/libqgpgme.so while slibtool is using -L../src/.libs -lqgpgme. If I manually run the following command that uses the .so library directly it will work.

clang++ t-revokekey.o t-support.o -g -O2 -L../../cpp/src/.libs -lgpgmepp -L../../cpp/src/../../../src/.libs -lgpgme -L/usr/lib64 -lassuan -lgpg-error -lassuan ../src/.libs/libqgpgme.so -L../src/../../cpp/src/.libs -lgpgmepp -L../src/../../cpp/src/../../../src/.libs -lgpgme -lassuan -lgpg-error -L../src/../../../src/.libs -lQt5Core -L../../../src/.libs -lgpgme -lassuan -lgpg-error -lQt5Test -lQt5Core -lstdc++ -o .libs/t-revokekey

I'm not exactly sure why this difference is so significant here?

Additionally, moving the -L../src/.libs -lqgpgme earlier in the command line works.

clang++ t-revokekey.o t-support.o -g -O2 -L../../cpp/src/.libs -lgpgmepp -L../../cpp/src/../../../src/.libs -lgpgme -L../src/.libs -lqgpgme -L/usr/lib64 -lassuan -lgpg-error -lassuan -L../src/../../cpp/src/.libs -lgpgmepp -L../src/../../cpp/src/../../../src/.libs -lgpgme -lassuan -lgpg-error -L../src/../../../src/.libs -lQt5Core -L../../../src/.libs -lgpgme -lassuan -lgpg-error -lQt5Test -lQt5Core -lstdc++ -o .libs/t-revokekey

In retrospect this might be better handled in slibtool itself. I'll try to contact the main dev behind the slibtool project, but they have been very busy lately so it might take some time.

Your observations seem to confirm that the linking picks up the old 1.17.1 version of libqgpgme instead of the newly built one. You could use strace to dispel last doubts. In any case this very much looks like a problem in slibtool.

We could change the order of the .la files in lang/qt/tests/Makefile.am:

LDADD = ../../cpp/src/libgpgmepp.la ../src/libqgpgme.la \
	        ../../../src/libgpgme.la @GPGME_QT_LIBS@ @GPG_ERROR_LIBS@ \
	        @GPGME_QTTEST_LIBS@ @LDADD_FOR_TESTS_KLUDGE@ -lstdc++

but then the linker would probably miss new symbols in libgpgmepp. Therefore, I don't think it's of much use to make this change.

I attached the strace log of the failing clang command, but I am not seeing anywhere where it finds libqgpgme on the system, Maybe I'm doing something wrong?

You probably have to call strace with -f, so that processes started by clang are also straced.

Yes, you are correct.

[pid  1252] rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
[pid  1252] access("../../cpp/src/.libs/libqgpgme.so", F_OK) = -1 ENOENT (No such file or directory)
[pid  1252] access("../../cpp/src/.libs/libqgpgme.a", F_OK) = -1 ENOENT (No such file or directory)
[pid  1252] access("../../cpp/src/../../../src/.libs/libqgpgme.so", F_OK) = -1 ENOENT (No such file or directory)
[pid  1252] access("../../cpp/src/../../../src/.libs/libqgpgme.a", F_OK) = -1 ENOENT (No such file or directory)
[pid  1252] access("/usr/lib64/libqgpgme.so", F_OK) = 0
[pid  1252] openat(AT_FDCWD, "/usr/lib64/libqgpgme.so", O_RDONLY|O_CLOEXEC) = 3
[pid  1252] newfstatat(3, "", {st_mode=S_IFREG|0755, st_size=1253896, ...}, AT_EMPTY_PATH) = 0
[pid  1252] mmap(NULL, 1253896, PROT_READ, MAP_PRIVATE|MAP_NORESERVE, 3, 0) = 0x7fe6f6ffa000
[pid  1252] rt_sigprocmask(SIG_SETMASK, ~[RTMIN RT_1], [], 8) = 0
[pid  1252] close(3)                    = 0

As it shows it checks the linker path in the order they are passed to the compiler and then finds the old system library before the newly built library. GNU libtool also sets the /usr/lib64 path before the using libqgpgme library, but avoids this by using the .so file directly. Presumably this is only on compatible platforms and maybe even a problem on less compatible platforms? I'm not sure the ramifications of slibtool trying to reorder the library paths itself. Hopefully the slibtool dev has some time to also share their thought soon.

One idea would be that gpgme installs its libraries in a directory like /usr/lib64/gpgme/, but that might be too disruptive?

I have checked where -L/usr/lib64 comes from. Ultimately, it seems to come from gpg-error-config --libs which outputs -L/usr/lib64 -lgpg-error. I have no idea why gpg-error-config --libs adds the -L/usr/lib64, but this seems very dangerous to me and was bound to cause trouble because a -L applies to everything that follows and not just to the following -l.

Maybe @gniibe can shed some light on this.

Another problem seems to be that libtool/automake does not differentiate between library dependencies needed for building the library itself and library dependencies that should be exported to users of the library. There's just mylib_la_LIBADD for specifying the internal/private library dependencies and those also end up as dependencies in the .la file. Or maybe the dependencies in the .la file are used by the original libtool only for building static libraries and it's slibtool's fault to also copy the dependencies verbatim when building a shared library.

In libassuan.pc gpg-error is only mentioned as Requires.private, i.e. this dependency is only meant to be used for static libraries.

Maybe the solution would be to stop using gpg-error-config and start using pkgconfig instead?

$ pkgconf --libs gpg-error
-lgpg-error

gpg-error-config (which is old shell script to offer functionality of pkg-config) gives -L/usr/lib64 when it is configured at the build time.
gpg-error-config hasn't got improved, but kept its behavior (for backward compatibility and lesser surprise), while we are moving to the support of gpg-error.pc (by pkg-config and/or gpgrt-config).

Basically, old gpg-error-config doesn't support multiarch/multilib well, like /usr/lib64. gpg-error.pc works well.

I'm going to push a patch for T5683. When it will be common, the problem will be gone.

Please note that with newer libgpg-error releases, you can safely not install or can safely remove installed gpg-error-config. For GnuPG and its friends (including gpgme), gpgrt-config with gpg-error.pc are used instead (when no gpg-error-config).

gpgrt-config works as a minimum version of pkg-config for GnuPG and its friends.

Note that gpgrt-config supports the PKG_CONFIG_PATH and PKG_CONFIG_LIBDIR environment variables.

Please use those variables to control the behavior.

It seems that the case $libdir = '${exec_prefix}/lib64' is not handled correctly, i.e. I get

prefix=/usr
exec_prefix=${prefix}
includedir=${prefix}/include
libdir=${exec_prefix}/lib64
[...]
Libs: -L${libdir} -lgpg-error

in gpg-error.pc.

The following patch for libgpg-error fixes this:

diff --git a/configure.ac b/configure.ac
index af57678..8de8cf8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -548,7 +548,7 @@ case "$includedir" in
 esac
 case "$libdir" in
   /usr/lib|/usr/lib64|/lib|/lib64) ;;
-  '${exec_prefix}/lib')
+  '${exec_prefix}/lib'|'${exec_prefix}/lib64')
     if test "$exec_prefix" = "NONE"; then
       if test "$prefix" != / -a "$prefix" != /usr; then
         GPG_ERROR_CONFIG_LIBS="-L\${libdir} $GPG_ERROR_CONFIG_LIBS"

With this patch I get

prefix=/usr
exec_prefix=${prefix}
includedir=${prefix}/include
libdir=${exec_prefix}/lib64
[...]
Libs: -lgpg-error

which I think is intended.

@gniibe: Okay to commit this?

@ikloecker Thank you. You're right. Please go ahead.

It seems the issue is also in libassuan-config.

$ libassuan-config --libs
-L/usr/lib64 -lassuan -lgpg-error

The shell logic here does not seem quite right to me.

https://dev.gnupg.org/source/libassuan/browse/master/src/libassuan-config.in;6da6a3df3c98552c710616d40e245467c3fe675c$132

gpg-error-config and its relatives (libassuan-config, included) were written before pkg-config. The support of cross build, multiarch, and multilib by those are quite limited (and sometimes wrong). Basically, those scripts are deprecated, but it has been kept for backward compatibility.

Please don't use those scripts for your new build, but use *.pc by pkg-config.

GnuPG and its friends uses gpgrt-config for *.pc, so that it helps porting GnuPG in an earlier stage.

Even without libassuan-config installed in libassuan-2.5.5.

$ gpgrt-config --libdir=/usr/lib64 libassuan --libs
-L/usr/lib64 -lassuan

gpg-error is not affected at least.

 gpgrt-config --libdir=/usr/lib64 gpg-error --libs
-lgpg-error

In lang/qt/tests/Makefile:

LIBASSUAN_CONFIG = /usr/bin/gpgrt-config --libdir=/usr/lib64 libassuan
LIBASSUAN_LIBS = -L/usr/lib64 -lassuan

I suggest simply removing any -L linker path from the output if it matches the $libdir in gpgrt-config.

This might be the correct way to do it?

--- gpgrt-config.orig	2022-08-21 23:14:40.017298485 -0700
+++ gpgrt-config	2022-08-21 23:16:40.220634136 -0700
@@ -209,17 +209,19 @@
     # Scan the list and eliminate duplicates for non-"-lxxx"
     # the resulted list is in reverse order
     for __arg; do
-	case "$__arg" in
-	    -l*)
-		# As-is
-		__rev_list="$__arg${__rev_list:+ }$__rev_list"
-		;;
-	    *)
-		if not_listed_yet $__arg $__rev_list; then
-		    __rev_list="$__arg${__rev_list:+ }$__rev_list"
-		fi
-		;;
-	esac
+	if [ "$__arg" != "-L$libdir" ]; then
+		case "$__arg" in
+		    -l*)
+			# As-is
+			__rev_list="$__arg${__rev_list:+ }$__rev_list"
+			;;
+		    *)
+			if not_listed_yet $__arg $__rev_list; then
+			    __rev_list="$__arg${__rev_list:+ }$__rev_list"
+			fi
+			;;
+		esac
+	fi
     done
 
     # Scan again

It at least seems to work correctly on my system with libgpg-error and libassuan.

$ /tmp/gpgrt-config --libdir=/usr/lib64 libassuan --libs
-lassuan

$ /tmp/gpgrt-config --libdir=/usr/lib64 gpg-error --libs
-lgpg-error

Or maybe it would be better to only check the standard libdir paths as in the libgpg-error configure.ac?

--- gpgrt-config.orig	2022-08-21 23:14:40.017298485 -0700
+++ gpgrt-config	2022-08-22 08:28:16.339977281 -0700
@@ -210,6 +210,7 @@
     # the resulted list is in reverse order
     for __arg; do
 	case "$__arg" in
+	    -L/usr/lib|-L/usr/lib64|-L/lib|-L/lib64) ;;
 	    -l*)
 		# As-is
 		__rev_list="$__arg${__rev_list:+ }$__rev_list"

Why should gpgrt-config change the information read from the *.pc files?

Isn't the actual problem that -L/usr/lib64 is stored in the *.pc files? Indeed, libassuan.pc.in contains a hard-coded

Libs: -L${libdir} @LIBASSUAN_CONFIG_LIBS@

This needs to be changed similar to the implementation for libgpg-error.

The -L${libdir} is standard in nearly all applicable .pc files on my system. In the case of pkgconf the -L linker path is removed from the output if its the standard linker path. Of course however you think its best to fix this would be fine though.

Hmm. Good point. Always adding -L${libdir} makes the .pc files easier to relocate.

In T6136#161915, @orbea wrote:

Or maybe it would be better to only check the standard libdir paths as in the libgpg-error configure.ac?

--- gpgrt-config.orig	2022-08-21 23:14:40.017298485 -0700
+++ gpgrt-config	2022-08-22 08:28:16.339977281 -0700
@@ -210,6 +210,7 @@
     # the resulted list is in reverse order
     for __arg; do
 	case "$__arg" in
+	    -L/usr/lib|-L/usr/lib64|-L/lib|-L/lib64) ;;
 	    -l*)
 		# As-is
 		__rev_list="$__arg${__rev_list:+ }$__rev_list"

This looks like a good approach, but I think stripping the standard paths needs to be deferred until later, because, if PKG_CONFIG_SYSROOT_DIR is set, then the library search paths are prefixed with $PKG_CONFIG_SYSROOT_DIR, and then the prefixed standard paths probably shouldn't be stripped.

Original pkg-config supports PKG_CONFIG_SYSTEM_LIBRARY_PATH (default is determined by build time, and overridden by environment var), PKG_CONFIG_SYSTEM_INCLUDE_PATH as well.

I'll consider about introducing those support to gpgrt-config.

This looks like a good approach, but I think stripping the standard paths needs to be deferred until later, because, if PKG_CONFIG_SYSROOT_DIR is set, then the library search paths are prefixed with $PKG_CONFIG_SYSROOT_DIR, and then the prefixed standard paths probably shouldn't be stripped.

I'm not sure how the check could be later, list_only_once_for_libs() is only executed near the end of the gpgrt-config script which is expanded as a list of arguments for sysroot(). However I now see how my approach is problematic, perhaps this would be better?

--- gpgrt-config.orig	2022-08-21 23:14:40.017298485 -0700
+++ gpgrt-config	2022-08-23 09:30:39.653366443 -0700
@@ -205,11 +205,13 @@
     __result=""
     __rev_list=""
     __arg=""
+    __root="-L${PKG_CONFIG_SYSROOT_DIR:-/}"
 
     # Scan the list and eliminate duplicates for non-"-lxxx"
     # the resulted list is in reverse order
     for __arg; do
 	case "$__arg" in
+	    ${__root}usr/lib|${__root}usr/lib64|${__root}lib|${__root}lib64) ;;
 	    -l*)
 		# As-is
 		__rev_list="$__arg${__rev_list:+ }$__rev_list"

This seems to work for me.

$ /tmp/gpgrt-config --libdir=/usr/lib64 libassuan --libs
-lassuan

$ PKG_CONFIG_SYSROOT_DIR=/tmp/delme /tmp/gpgrt-config --libdir=/usr/lib64 libassuan --libs
-L/tmp/delme/usr/lib64 -lassuan

@orbea Thank you for your suggestions.

I think that the prefixed standard paths should be stripped when PKG_CONFIG_SYSROOT_DIR is specified. So, your original suggestion is relevant, I suppose.
(you can compare the behavior by pkg-config/pkgconf).

I pushed the changes. It also cares about the case for --cflags.

Thanks, I really appreciate having this fixed in gpgrt-config! I backported the commit to gentoo and can confirm that fixes the build issue with slibtool.

https://github.com/gentoo/gentoo/pull/27083
https://github.com/gentoo/gentoo/commit/2decb35d9c92550ed0688745039751b38dd5b916

werner changed the task status from Open to Testing.Sep 22 2022, 10:50 AM
werner removed a project: Restricted Project.
werner claimed this task.