On 13/02/23 12:49, Bartosz Golaszewski wrote:
> Hey!
>
> I'm the author and maintainer of libgpiod. I'm currently getting ready
> to do a new major release. After giving some exposure to the release
> candidate, I noticed that when using clang, I can't link against the
> C++ bindings, while it works just fine in GCC.
>
> The tree in question is here:
> https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/log/
>
> You can trigger the linking program by trying to build the C++ tests
> with clang like that:
>
> CC=clang CXX=clang++ ./autogen.sh --enable-bindings-cxx --enable-tests
> && make -j16
>
> You'll get the following error:
>
> /usr/bin/ld: tests-chip.o:(.data+0x0): undefined reference to
> `typeinfo for gpiod::chip_closed'
> /usr/bin/ld: tests-line-request.o:(.data+0x0): undefined reference to
> `typeinfo for gpiod::request_released'
> /usr/bin/ld: .libs/gpiod-cxx-test: hidden symbol
> `_ZTIN5gpiod11chip_closedE' isn't defined
> /usr/bin/ld: final link failed: bad value
>
> The typoinfo is missing for exception types that should be visible to
> users of the library.
>
> The culprit is here:
> https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/tree/bindings/cxx/gpiod.hpp#n26
>
> I added the GPIOD_CXX_BUILD macro in order to not re-export the
> visible symbols if any user of the library would include the gpiod.hpp
> header. When the library is being built, the symbols are visible, when
> someone includes the header, the symbols are hidden.
But the typeid of the symbol, for instance gpiod, will still be provided
by shared library if I understood correctly:
libgpiod-llvm$ objdump -t ./bindings/cxx/tests/tests-chip.o 2>/dev/null| grep
-w _ZTIN5gpiod11chip_closedE
0000000000000000 *UND* 0000000000000000 .hidden
_ZTIN5gpiod11chip_closedE
libgpiod-llvm$ objdump -t bindings/cxx/.libs/libgpiodcxx.so 2>/dev/null| grep
_ZTIN5gpiod11chip_closedE
0000000000024b50 g O .data.rel.ro 0000000000000018
_ZTIN5gpiod11chip_closedE
However, it seems that GCC is not applying the hidden attribute on the
typeid class:
libgpiod-gcc$ objdump -t ./bindings/cxx/tests/tests-chip.o 2>/dev/null| grep -w
_ZTIN5gpiod11chip_closedE
0000000000000000 w O .data.rel.local.DW.ref._ZTIN5gpiod11chip_closedE
0000000000000008 .hidden DW.ref._ZTIN5gpiod11chip_closedE
0000000000000000 *UND* 0000000000000000 _ZTIN5gpiod11chip_closedE
When it creates create the vague linking weak symbol
.data.rel.local.DW.ref._ZTIN5gpiod11chip_closedE.
I am not sure why GCC is being permissive here, in fact IMHO this is
gcc issue. If I add the visibility explicitly using pragmas:
diff --git a/bindings/cxx/gpiodcxx/exception.hpp
b/bindings/cxx/gpiodcxx/exception.hpp
index 98b7bc4..24ae698 100644
--- a/bindings/cxx/gpiodcxx/exception.hpp
+++ b/bindings/cxx/gpiodcxx/exception.hpp
@@ -17,6 +17,8 @@
namespace gpiod {
+#pragma GCC visibility push(hidden)
+
/**
* @ingroup gpiod_cxx
* @{
@@ -25,7 +27,7 @@ namespace gpiod {
/**
* @brief Exception thrown when an already closed chip is used.
*/
-class GPIOD_CXX_API chip_closed : public ::std::logic_error
+class /*GPIOD_CXX_API*/ chip_closed : public ::std::logic_error
{
public:
@@ -64,6 +66,8 @@ public:
virtual ~chip_closed();
};
+#pragma GCC visibility pop
+
/**
* @brief Exception thrown when an already released line request is used.
*/
I get an explicit linking error:
/usr/bin/ld:
tests-chip.o:(.data.rel.local.DW.ref._ZTIN5gpiod11chip_closedE[DW.ref._ZTIN5gpiod11chip_closedE]+0x0):
undefined reference to `typeinfo for gpiod::chip_closed'
Which is what I expect. So I suggest you to avoid adding the hidden
visibility on tests because since there are not linking static, they
should follow the default rules of ABI and hidden in this case does
not really make much sense.
>
> If I make the symbols unconditionally visible here, clang starts to
> work but I have no idea why and would like to avoid re-exporting the
> symbols if I can.
>
> I'm using the following version:
> Ubuntu clang version 15.0.6
> Target: x86_64-pc-linux-gnu
> Thread model: posix
> InstalledDir: /usr/bin
>
> Host is: x86_64 GNU/Linux
>
> It's not like gcc links fine but then fails to obtain typeid - I can
> catch exceptions coming out from libgpiod just fine in external apps
> linked using gcc and see their type.
>
> Any hints?
_______________________________________________
linaro-toolchain mailing list -- linaro-toolchain@lists.linaro.org
To unsubscribe send an email to linaro-toolchain-le...@lists.linaro.org