On Mon, 13 Feb 2023 at 19:49, Adhemerval Zanella Netto <adhemerval.zane...@linaro.org> wrote: > > > > 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. >
I'm not sure I understand this. The tests are linked dynamically - just like any other program would. IIUC: I build libgpiodcxx making the exception symbols visible, then if anyone else (a program linking against libgpiodcxx) includes the header, the symbol is hidden. On top of that - if I build the examples with clang, they build because they don't reference the symbols openly. But if I then make one of those exceptions fly out of libgpiod unconditionally, their typeid is correctly seen: terminate called after throwing an instance of 'gpiod::request_released' what(): GPIO lines have been released Aborted If on the other hand I add catch (const gpiod::request_released& ex) somewhere, I get the same linking error. The same happens for any program that I'd build with -llgpiodcxx Bart > > > > 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