standard way to require c++11?

Jeremy Huddleston Sequoia jeremyhu at apple.com
Wed Apr 15 03:55:46 PDT 2015


> On 14.04.2015 10:02 AM, Jeremy Huddleston Sequoia wrote:
>> Yes, I actually have libc++ on all of my SL+ machines except a couple
>> VMs I keep around for testing the default configuration.  IMO, it
>> seems far easier to live on libc++ on SL than libstdc++ because so 
>> many ports these days require it.
> 
> What are they actually requiring? libc++ or C++11?

They are requiring C++11 which by extension means libc++ in our current situation.

> I don't know any port
> that fails to build with libstdc++ but is happy with libc++ offhand.

llvm-3.7 and webkit-gtk are two such ports that I can point to off the top of my head.

By "libstdc++" I am of course referring to the *system* libstdc++.  I apologize if that was not clear.

>>> If someone on <= 10.8 set libc++ globally... tough luck. He'll get 
>>> an error when trying to install the port.
>> 
>> Which is stupid. Users would set libc++ globally precisely for the 
>> reason you are trying to address: to avoid issues with the lack of 
>> C++11 support in libstdc++. And then you are ruling out exactly the 
>> users who care about C++11 most.
> 
> It's not stupid if you consider my point that libstdc++ is well able to
> compile C++11 code if using the FSF GCC in MacPorts.

Yes, but then you'd need to use the FSF GCC compilers from MacPorts to build all of your C++ ports in order for them to interoperate, and those ports would all have a new dependency on the libgcc port.

Furthermore, nobody has bothered to update the gcc ports to use the Apple gcc driver driver, so the use of multiple -arch options pretty much blocks +universal which is a big issue for ports like wine that have heavy dependencies and are i386.

> That will leave the
> problem if choking on Apple's headers that make use of their "Blocks"
> extension, though.

Do you have evidence of any such issues?  If so, that is a bug that should be filed.  If you notice, our headers are heavily annotated with '#ifdef __BLOCKS__' around such cases.

> (Which is practically all Cocoa/Carbon stuff, I
> guess?) For that reason (and "+universal"), clang + libc++ are indeed
> the superior choice. I agree. There are problems with that approach as
> well, though. More to that later in this message...
> 
> 
>>> But given that, in the case of hardcoding configure.cxx_stdlib to 
>>> another C++ runtime than the autodetected/default value, the 
>>> selected C++ runtime not matching the system C++ runtime and this 
>>> potentially leading to a variety of subtle to not so subtle bugs, 
>>> erroring out looked like the best thing to do.
> 
> On 14.04.2015 10:02 AM, Jeremy Huddleston Sequoia wrote:
>> What do you mean by "the system runtime"?  There is no "system 
>> runtime".  There are two runtimes available on the system, an ancient
>> libstdc++ kept around for binary compatibility, and a more modern
>> libc++.
> 
> With "system runtime", I mean the runtime that gets linked by Apple's
> libraries.

What the system libraries link against is irrelevant.  It is the interfaces provided by the system libraries that matters.

> For instance:
> 
> /usr/lib/libobjc.dylib:
>        /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current
> version 228.0.0)
>        /usr/lib/libauto.dylib (compatibility version 1.0.0, current
> version 1.0.0)
>        /usr/lib/libc++abi.dylib (compatibility version 1.0.0, current
> version 48.0.0)
>        /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current
> version 120.0.0)
>        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current
> version 1197.1.1)
> 
> Anything that links against -lobjc will also pull-in the "system
> runtime" libc++.

libobjc is a *client* of libc++.  It does not expose any C++ interfaces to its clients.  As I mentioned in my earlier response, it is perfectly valid to have any number of various C++ runtimes in the same process so long as they are isolated from eachother.

> This is a problem, because we cannot provide an libobjc
> alternative in MacPorts, so you may end up with two different versions
> of libc++ instead. Is that any better?

How would you end up with two different versions of libc++?

> On 14.04.2015 10:02 AM, Jeremy Huddleston Sequoia wrote:
>> To be fair, I did most of the work in MacPorts only after extensive 
>> testing of the configuration and transition by Apple in Mountain Lion
>> (or maybe it was Mavericks).  On newer OSX versions, we have an added
>> benefit of having libstdc++ on top of libc++abi.  We don't have that
>> benefit on SL, but other than that, installing the libcxx port on SL
>> gets you a pretty modern and well tested C++ runtime that is forwards
>> compatible with the system libc++ on Lion and later.
> 
> What does mean "forward compatible" here? Does it mean that programs
> linked against libc++ will continue to work if you upgrade libc++ (which
> is AFAIK also the case with libstdc++), or does it mean that you can mix
> multiple libc++ versions in the same process? If I read "port info
> libcxx" correctly, the latter case doesn't work even with libc++.

It means that if you use 'clang++-mp-3.4 --stdlib=libc++ ...' to compile code on Snow Leopard with the MacPorts-provided libcxx port, it will run on Yosemite.


> On 14.04.2015 10:02 AM, Jeremy Huddleston Sequoia wrote:
>> I think you misunderstand.  This is not entirely true.
> 
>> Why do people report problems then?
> 
>> Because the above is completely entirely true.  You can have multiple
>> versions of C++ runtimes in the same process (even libc++ and
>> libstdc++).  The issue arrises when you try to pass objects between
>> them.  For example, assume libA links libstdc++ and libB links
>> another copy of libstdc++ as well as libA.  If libA exports C++ API
>> that libB consumes, then it will be interacting with them through the
>> wrong runtime.
> 
> Re-iterating: is this not the case for multiple copies of libc++?

It is certainly be the case for multiple copies of the libc++ runtime.  But we're not dealing with multiple copies of libc++.  However, you are considering multiple copies of libstdc++.

>> But the idea is that you *can* compile that if you use libc++. My 
>> main point was that there should be no need to blacklist clang.
> 
> I believe you. But I didn't *want* to use libc++ on < 10.9, because
> that's not the "system runtime". Maybe that's a bad idea, see my
> comments and questions above.

Yes, it most certainly is a system runtime.  We've been shipping libc++ with OS X since Lion (10.7).  It was just made the default C++ runtime with Mavericks (10.9).

> On 14.04.2015 10:02 AM, Jeremy Huddleston Sequoia wrote:
>> 'sudo port -v -s install libcxx' is fairly automatic ;)
>> 
>> If you want to configure MacPorts to use the compiler by default, 
>> that isn't automatic but is fairly easy with steps laid out at: 
>> http://trac.macports.org/wiki/LibcxxOnOlderSystems
> 
> It is not.

Yes, I already said it was not automatic to use it within MacPorts.  I said it was automatic to install the toolchain.  Once you install the libcxx port, you are capable of using the toolchain for your own projects and distributing the built code.

> A user must edit macports.conf multiple time while
> bootstrapping the MacPorts system for libc++, (re-) build clang/llvm
> ports multiple times to make them use the correct stdlib, will not be
> able to use binary archives etc.

Yeah.  If you want to use a non-default configuration, you'll need to edit the config file.  If such configurations result in build time differences, you can't use the existing archive repositories.

This does not make them unable to use binary archives.  It makes them unable to use the binary archives that come out of the buildbot for the default configuration.  The same is true for anyone who enables non-default variants.

> About the same thing will need to be done on 10.7 and 10.8, too (well,
> setting configure.cxxstdlib and rebuilding everything. The bootstrapping
> part can be omitted there.)

Yeah.  Again, if the user wants to use a non-default configuration, they'll need to edit a configuration file.  I don't see the problem there.

> The needed compile time alone is inconvenient for users.

Yes, but it is just one time.  And hopefully they are aware of this choice at the beginning and set the configuration so that there is no need to re-compile.

> And users will
> need to actually *know* about having to change options and maybe even
> re-compile all ports/bootstrap somehow. My goal was to provide C++11
> support transparently, without needing to change the macports.conf or
> rebuilding the whole system.
> 
> Maybe that's just not possible.

The goals are competing.  As discussed earlier, the binary archiving and database would need a way to encode more than we currently encode, so base could determine how to deal with this better.

The easiest way for users on 10.6-10.9 systems to get C++11 support is by using libc++ as discussed in http://trac.macports.org/wiki/LibcxxOnOlderSystems

I'd also be in favor of having some libc++ buildbots for 10.8 and maybe 10.7 if the community demand is there.

>>> And even then -- won't you be mixing libc++ and libstdc++ when 
>>> linking anything system-related that happens to be written in C++ 
>>> and links libstdc++?
>> 
>> In your case one would be mixing libstdc++ shipped by apple and 
>> libstdc++ as shipped by gcc. From what I understand from fellow 
>> macports developers/maintainers mixing different libstdc++ is worse.
> 
> On 14.04.2015 10:02 AM, Jeremy Huddleston Sequoia wrote:
>> It's worse only in that it's less obvious.  If you screw up 
>> accidentally mixing libc++ and libstdc++ binaries, you'll get a 
>> linker error.  If you screw up mixing two different libstdc++ based 
>> binaries, you'll probably link ok since the symbol mangling will be 
>> the same, and you'll only notice odd errors at runtime.
> 
> Will linking to both libc++ and libstdc++ *always* lead to a linker error?

If a libstdc++-client library exposes a class that is being used by a libc++-client client, the libc++-client client of that library will fail to link because the mangling of the symbols will be differnet.

> What if, say, you have a binary that links -lc++ -lc++abi -lobjc on 10.8
> and below? Will this also result in a linker error?

No.  Why would it?

>>> My idea is: stay with libstdc++ on "legacy platforms" and avoid the
>>> problems created by mixing C++ runtimes, messing with user systems
>>> in a non-interactive way and creating a new buildslave 
>>> infrastructure. Why would you not use libstdc++, if it works *and* 
>>> can be used -- together with GCC -- to compile C++11 code? (Yes, 
>>> I'm avoiding your "PPC problem". I'm seriously sorry GCC is not 
>>> building there, but there's not much I can do about that.)
> 
> On 14.04.2015 10:02 AM, Jeremy Huddleston Sequoia wrote:
>> It can't.  You'd be using *differnet* libstdc++ runtimes.
> 
> It can for my ports. In hindsight, that's probably only working by
> chance, because the ports in question do not use anything Apple-specific
> and thus do not pull in the system libstdc++.

I think you are missing the point that this is about *interfaces* and not about what other libraries are doing internally.

> So it turns out it's not a general solution.

>> I wasn't talking about PPC here at all (and I believe that gcc 
>> actually compiled successfully in the meantime***). We are still 
>> talking about 10.6-10.8 with x86_64.
> 
> I just remembered GCC wasn't working for you on PPC at all. That would
> have been another "corner case" which my solution didn't address.
> 
> 
> Phew. That was quite a stretch, sorry.
> 
> I'll try to summarize the situation as far as I've understood. Please
> correct me if needed.
> 
> - There is no way to transparently provide C++11 support on OS X < 10.9.
> Users will need to switch their MacPorts installation to libc++ by
> rebuilding all ports.

Yep.

> - Even doing that may lead to situations where C++11 is used but also
> Apple's libraries or frameworks linked at the same time. If libstdc++ is
> being (implicitly) linked by that, linking fails. These ports will be
> uninstallable on a pre-10.9-libc++ system.

No.

> - Following my original idea of using libstdc++ on pre-10.9 systems will
> potentially link different versions of libstdc++ at the same time and
> not lead to linker errors, but most likely crashes or other undesired
> behavior at run time.

Assuming you are meaning the newer libstdc++ provided by the libgcc port, yes.  You would need to ensure that all C++ ports are built with the FSF compiler in order to avoid this problem.

> - OS X >= 10.9 is fine regarding C++11.

Yes.

> - C++14 support comes "free of charge" on 10.9 and 10.10 with XCode 6
> and if using MacPorts' libc++ and clang-3.4 or higher on 10.8 and below.

Yes.

> That doesn't sound too nice.

Seems reasonable to me.  For 10.7 and 10.8 users, just edit macports.conf and rebuild your ports.  10.6 users have to go through some additional steps to first build the toolchain, but that's rather expected for a 5 year old OS.  I've considered packaging up a modern toolchain for users to install instead of bootstrapping, but it's never seemed like a big enough hurdle to make that necessary.  If we ever get libc++ working on Leopard, then it might be worth the effort there since that bootstrapping process is even more of a headache.

> I have to add yet another thing, though. We'll be running into a similar
> issue on 10.9 and 10.10 (and (10.10)++ and ...) once C++1z (the next
> standard) is released and gains widespread usage. How can we provide
> C++1z support, if the system libc++ does not? Install our own version of
> libc++ and rebuild MacPorts against that?
> At some point, this will *also* lead to using different libc++ runtimes.

If the system libc++ runtime is not compatible with requirements of future versions of C++, then I suspect expert users will do what they already do now.  They can use the +replacemnt_libcxx variant of libcxxabi and libcxx to build roots that they can use darwinup to install, replacing the system runtimes.  It's certainly not ideal and will also potentially cause codesigning issues, but that's one option.  Another option would be as you suggest, moving to having MacPorts provide its C++ runtime, but that would also mean MacPorts always using its own toolchain instead of the one provided by Xcode.  I don't think we want to do that (other than in the fallback cases we do now).

> 
> 
> 
> Mihai
> 
> _______________________________________________
> macports-dev mailing list
> macports-dev at lists.macosforge.org
> https://lists.macosforge.org/mailman/listinfo/macports-dev

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 4109 bytes
Desc: not available
URL: <https://lists.macosforge.org/pipermail/macports-dev/attachments/20150415/1db603cb/attachment-0001.p7s>


More information about the macports-dev mailing list