Linux GPIO subsystem development
 help / color / mirror / Atom feed
From: Jack Winch <sunt.un.morcov@gmail.com>
To: Bartosz Golaszewski <brgl@bgdev.pl>
Cc: "open list:GPIO SUBSYSTEM" <linux-gpio@vger.kernel.org>,
	Bartosz Golaszewski <bartekgola@gmail.com>,
	Kent Gibson <warthog618@gmail.com>
Subject: Re: [libgpiod] C++ Bindings ABI Compatibility
Date: Tue, 3 Nov 2020 21:01:18 +0000	[thread overview]
Message-ID: <c0f159a1-32d7-d5b5-7f08-c0cb482e4501@gmail.com> (raw)
In-Reply-To: <CAMRc=MenVv0p2A7+E5z=5E8t50uh3vhhCWpg22oAfO0bEK1QJA@mail.gmail.com>

Sorry for the delayed response.

    I've had some experience in enterprise C++ a couple years ago (high
    availability systems for a big corporation) and I've worked with some
    brilliant C++ developers and I believe it. It's due to the fact that
    such systems are usually packaged together and rebuilt from scratch.
    Add to it a strong "not-invented-here" syndrome and you can basically
    disregard any ABI issues.


That's exactly it.

    > 2.  Provide a C++ ABI, but  implement the PImpl pattern such that it is
    > possible to  maintain ABI compatibility for the major version releases
    > of the library  (implementation details may be changed to implement bug
    > fixes, etc, which  is not possible without using the PImpl pattern).
    > Even with this  approach, there are limitations as to what should be
    > passed over the  shared library - application boundary.
    >
    Could you elaborate on the last sentence? Since my gut is telling me
    PImpl would be the right choice, I'd like to know what these
    limitations are.


Sure.  The expansion of that comment is thus:

In order to reduce ABI compatibility problems in this scenario, do not 
pass anything over the boundary unless you can be certain that the ABI 
of those items are stable and compatible.  This should be taken to mean 
objects where ABI stability is guaranteed by the provider or you have 
control of the ABI stability yourself.  On some platforms and with some 
C++ standard library implementations, the exposure of standard library 
types in the public interface is out of the question, as ABI 
compatibility is not retained between major releases of the standard 
library implementation.  These are the 'pain points' for the Qt 
libraries on certain platforms and with certain compiler collections.

You also have to consider the binary compatibility of how certain 
language features are implemented by the dependency and reverse 
dependency.  For example, the manner in which exceptions are handled may 
differ between the dependency and reverse dependency.  This issue in 
particular is why Qt makes exclusive use of return codes (and not 
exceptions) for error handling.  Of course, the implementation of such 
features is determined by the compiler collection being used to build 
each binary module (as well as any settings applied during the build).

Fortunately, both libc++ and libstdc++ are relatively stable and 
somewhat compatible from an ABI point of view.  Both gcc and clang 
attempt to implement ABI stability and compatibility, with both 
implementing portions of the Itanium C++ ABI.  There are still some 
issues though, but with time these issues are being resolved in later 
releases of the compiler collections.

The detailed status of compatibility between other compiler collections 
for GNU / Linux is beyond me at current, though it would be safe to 
assume that ABI compatibility is not completely guaranteed.

    Thanks for taking the time to write this down, very helpful!


You're very welcome. Obviously this is a very high-level and general 
overview.

    As I mentioned above - I'm leaning towards PImpl. The reasons I see
    for that are: we don't expose any templates to the user and we don't
    need any polymorphism. We also seem to have a rather well defined
    scope for the library - I can't imagine huge changes happening after
    the v2.0 release. 


I agree that the scope of the library is well-defined and relatively 
limited.  As you also point out, templates and polymorphism are not 
utilised in the current form of the library and its public interface.  
Of course, it is possible that future features might come along within 
the gpio subsystem / libgpiod, where making use of these language 
features within the C++ binding might be desired. That being said, it's 
not like we're developing a library of highly generic components.  If 
required, we can make use of Qt as a reference for implementing 
polymorphic inheritance hierarchies and limited [dynamic] strong data 
type variation with the PImpl pattern. So PImpl is a very viable option 
for the C++ binding, should you want to retain it being a shared library.

    Header-only approach means every user includes everything and we still
    need to recompile every user to update the library even with minor
    changes. How do distros handle this anyway? Let's say boost gets a
    bugfix - do all reverse dependencies get a bugfix release?


That's how it usually works.  And that fact means that the reverse 
dependency can be confident as to whether a library bug fix is available 
at runtime, because it is compiled into the reverse dependency.  This 
differs from the shared library approach, as whether or not the bug fix 
is available will depend on which version of the shared library is 
available and which gets loaded and linked at runtime.

With a lot of C++ developers, there is a cultural element around 
steering away from these types of issues if possible (and not for bad 
reason either).  So that is, in my opinion, one of the contributing 
reasons as to why this approach is seen as acceptable / preferred by a 
lot of this community.  If you make a bug fix to the library, you have 
to build the library and deploy it to the target anyway. Personally, I'd 
rather build the reverse dependency with the bug fix 'baked in' and 
deploy that.

Don't forget that if you make an ABI breaking change to the public 
interface of a shared library, you have to do a re-build and 
re-deployment of the library and reverse dependencies anyway.  At least 
if you go down the header-only library route, you remove the pain of 
having to worry about ABI compatibility and stability entirely (while 
being able to make full use of the features offered by the language).

    I've been looking at what C++ shared libraries I have installed on my
    regular Debian 10 system and then also browsed their code a bit. It
    turns out that many of them also put the entire implementation in the
    header (libjsoncpp, libmpeg2encpp and several others) and they're
    still at relatively low ABI major versions of the shared object - so
    I'm wondering if that's really such an issue? Or do so few people
    realize this is a problem?


ABI compatibility for C++ libraries is certainly less of an issue on GNU 
/ Linux (as compared to other platforms), but it is still an issue.  
I've not had experience with either of the packages you've mentioned, so 
it's possible they have not made ABI breaking changes or they just don't 
care (maybe through ignorance).

I guess, like everything, it all comes down to what you're trying to 
achieve and what you really care about.  I've met individuals who didn't 
give a hoot about this particular issue, as the carnage it caused 
downstream "wasn't their problem" and they "still get paid at the end of 
the month".

If you need me to expand on anything above, then let me know.  
Personally, I'm still for a header-only approach, but if you still want 
the C++ binding to be available as a shared library, the PImpl pattern 
would also be well suited in this case.  In either case, implementing 
the required changes should not be too taxing.

On a somewhat related note, I did a build of the libgpiod master branch 
yesterday.  Could you just confirm what the version should be for the 
resultant libgpiodcxx.so?  The built library has a version of 1.1.1.

Jack

  reply	other threads:[~2020-11-03 21:31 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-10-23 20:04 [libgpiod] C++ Bindings ABI Compatibility Jack Winch
2020-10-24 13:19 ` Bartosz Golaszewski
2020-11-03 21:01   ` Jack Winch [this message]
2020-11-03 21:06     ` Jack Winch
2020-11-27 10:14       ` Bartosz Golaszewski

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c0f159a1-32d7-d5b5-7f08-c0cb482e4501@gmail.com \
    --to=sunt.un.morcov@gmail.com \
    --cc=bartekgola@gmail.com \
    --cc=brgl@bgdev.pl \
    --cc=linux-gpio@vger.kernel.org \
    --cc=warthog618@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox