Re: Question on DSO and visibility
On 14 September 2016 at 15:26, Paul Smith wrote: > On Wed, 2016-09-14 at 10:13 +0100, Jonathan Wakely wrote: >> The real problem is that your library will depend on a newer libstdc++ >> but that's orthogonal to the ABI changes. Statically linking it is one >> solution, deploying the newer libstdc++.so with your library is >> another. > > Yes, again good point. So, as long as I don't pass objects of the > problematic types across the ABI all is fine assuming a sufficient > libstd++ library is available. Right. If making the new libstdc++.so available is a problem then your static linking + -fvisibility=hidden approach should work. I think :-) > There's one question: what about exceptions? std::exception::what() > returns a const char*; I don't know if that's stored internally as a > std::string which might have problematic types. If I throw an exception > from my code (new GCC/ABI) and it's caught by the caller's code (old > GCC/ABI) is there a problem? I'm assuming this is not an issue. The exception classes are the same in the old and new ABIs (except for std::ios_base::failure, which gains a new base class and data members in C++11, so had to change anyway). The character data returned by what() is always stored in a copy-on-write string, even when std::string is the non-copy-on-write std::__cxx11::string.
Re: Question on DSO and visibility
On Wed, 2016-09-14 at 10:13 +0100, Jonathan Wakely wrote: > On 11 September 2016 at 22:38, Paul Smith wrote: > > I wonder if someone can comment on this situation: I'll do some testing > > but I likely can't test everything. > > > > I'm creating DSO's for GNU/Linux with GCC 4.9.2 right now. I want to > > upgrade to GCC 6.2.0. My code is written in C++. I'm aware of the C++ > > STL ABI break in GCC 5.x. > > Based on the solution you outlined, I'm not sure you've fully > understood the ABI change in GCC 5. There's little doubt you're correct about that :) > See https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html Thanks. That is relatively clear. > >3. Use a linker map to make all symbols in my DSO hidden except the > > specific ones I want to be public. I use a linker map and not just > > -fvisibility=hidden, so that all the symbols I've statically linked > > from libstdc++.a will also be marked hidden (since libstdc++.a was > > not compiled with -fvisibility=hidden). > > The different ABIs coexist automatically. Affected symbols mangle > differently so they don't collide. Aha. Yes, this is the critical point I was glossing over. > > In other words, I can use std::basic_string and std::list in my library > > and get the C++11 ABI from GCC 6.2 that I've statically linked, and > > users can use std::basic_string and std::list in their code and get > > their version of the libstdc++.so (presumably that is provided by their > > GNU/Linux distribution) and all will work properly. > > You don't necessarily need two version of libstdc++ in the process. > The newer libstdc++.so is compatible with the users' code. > > If all you're worried about is the ABI change then just build your > library with _GLIBCXX_USE_CXX11_ABI defined to 0 (or build your gcc > with --with-default-libstdcxx-abi=gcc4-compatible) I could do that. The problem is: I actually create two different binaries from my code: one is the shared library which users can link and the other is a standalone application. They contain almost all the same code (the idea is that users may want to embed the application or run it stand-alone). I really don't want to have to compile the entire project twice. And all things being equal, I'd like to use the newer ABI (since 99% of my users actually use the stand-alone binary). But maybe the complexity of both having my cake and eating it is not worth it. > The real problem is that your library will depend on a newer libstdc++ > but that's orthogonal to the ABI changes. Statically linking it is one > solution, deploying the newer libstdc++.so with your library is > another. Yes, again good point. So, as long as I don't pass objects of the problematic types across the ABI all is fine assuming a sufficient libstd++ library is available. There's one question: what about exceptions? std::exception::what() returns a const char*; I don't know if that's stored internally as a std::string which might have problematic types. If I throw an exception from my code (new GCC/ABI) and it's caught by the caller's code (old GCC/ABI) is there a problem? I'm assuming this is not an issue. One reason all this came up was that a user was linking with my shared library and got a crash in their own code, and saw my version of std::string in the stacktrace (because I linked libstdc++ statically) even though my code was not involved. Even though it all was working fine, seeing this stack trace concerned them. I was thinking that if I ensured that my static libstdc++ was marked hidden, they would get their own dynamically linked libstdc++ and use that from their code and I could avoid this "appearance of impropriety". Thanks for the response Jonathan!
Re: Question on DSO and visibility
On 11 September 2016 at 22:38, Paul Smith wrote: > I wonder if someone can comment on this situation: I'll do some testing > but I likely can't test everything. > > I'm creating DSO's for GNU/Linux with GCC 4.9.2 right now. I want to > upgrade to GCC 6.2.0. My code is written in C++. I'm aware of the C++ > STL ABI break in GCC 5.x. Based on the solution you outlined, I'm not sure you've fully understood the ABI change in GCC 5. See https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html > I have users who will be using my library who are also writing C++ code > and they will be using older versions of GCC (I build my own GCC and I > use a specific sysroot for an older version of libc etc. so I know my > code will run properly on their system: they'll use their distribution's > version of GCC). > > What I was thinking of doing was this: >1. Link my DSO with -static-libstdc++ and -static-libgcc >2. Ensure that no STL typed objects are passed across the ABI between my > library and its callers; also that no memory I allocate is freed by > the user and no memory the user allocates is freed by me (my library > also runs on Windows as a DLL so I already have this restriction). On GNU/Linux there's no reason for the restriction on allocation, there's only a single malloc. You might need to do that for Windows, but not GNU/Linux. >3. Use a linker map to make all symbols in my DSO hidden except the > specific ones I want to be public. I use a linker map and not just > -fvisibility=hidden, so that all the symbols I've statically linked > from libstdc++.a will also be marked hidden (since libstdc++.a was > not compiled with -fvisibility=hidden). > > Is this plan sufficient to allow people to link with my library and not > have their version of GCC's libstdc++.so interfere with my library's > version, so the different ABI's can coexist in the same program without > interfering with each other? The different ABIs coexist automatically. Affected symbols mangle differently so they don't collide. > In other words, I can use std::basic_string and std::list in my library > and get the C++11 ABI from GCC 6.2 that I've statically linked, and > users can use std::basic_string and std::list in their code and get > their version of the libstdc++.so (presumably that is provided by their > GNU/Linux distribution) and all will work properly. You don't necessarily need two version of libstdc++ in the process. The newer libstdc++.so is compatible with the users' code. If all you're worried about is the ABI change then just build your library with _GLIBCXX_USE_CXX11_ABI defined to 0 (or build your gcc with --with-default-libstdcxx-abi=gcc4-compatible) The real problem is that your library will depend on a newer libstdc++ but that's orthogonal to the ABI changes. Statically linking it is one solution, deploying the newer libstdc++.so with your library is another.
Question on DSO and visibility
I wonder if someone can comment on this situation: I'll do some testing but I likely can't test everything. I'm creating DSO's for GNU/Linux with GCC 4.9.2 right now. I want to upgrade to GCC 6.2.0. My code is written in C++. I'm aware of the C++ STL ABI break in GCC 5.x. I have users who will be using my library who are also writing C++ code and they will be using older versions of GCC (I build my own GCC and I use a specific sysroot for an older version of libc etc. so I know my code will run properly on their system: they'll use their distribution's version of GCC). What I was thinking of doing was this: 1. Link my DSO with -static-libstdc++ and -static-libgcc 2. Ensure that no STL typed objects are passed across the ABI between my library and its callers; also that no memory I allocate is freed by the user and no memory the user allocates is freed by me (my library also runs on Windows as a DLL so I already have this restriction). 3. Use a linker map to make all symbols in my DSO hidden except the specific ones I want to be public. I use a linker map and not just -fvisibility=hidden, so that all the symbols I've statically linked from libstdc++.a will also be marked hidden (since libstdc++.a was not compiled with -fvisibility=hidden). Is this plan sufficient to allow people to link with my library and not have their version of GCC's libstdc++.so interfere with my library's version, so the different ABI's can coexist in the same program without interfering with each other? In other words, I can use std::basic_string and std::list in my library and get the C++11 ABI from GCC 6.2 that I've statically linked, and users can use std::basic_string and std::list in their code and get their version of the libstdc++.so (presumably that is provided by their GNU/Linux distribution) and all will work properly.