Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Overview of C++ language support in Apple Clang (developer.apple.com)
69 points by ingve on June 12, 2023 | hide | past | favorite | 48 comments


This just lists what they do support, not what they leave out compared to the free alternatives. Here's a better chart -- look at all that red in the Apple clang column: https://en.cppreference.com/w/cpp/compiler_support

I don't understand why they deviate so much from mainstream clang. I think they'd be better off being closer to the trunk. TBH I don't really understand why they have their own tree at all.


FWIW, I don't know how much they actually "deviate" (and in fact I do think they have a bunch of likely-needless changes) but they definitely lag a bit what they ship, so the core issue is just that they are behind a version or two, so the differences are almost entirely just "the stuff introduced in clang/libc++ 15/16+" with maybe one or two backports. If it makes you feel any better, the Android NDK copy of clang isn't far off of upstream clang and yet they also often are shipping a slightly older version... it just doesn't warrant its own column as they expose the underlying clang version number, while Apple does this really really annoying thing where the version number of clang is hacked to report a version number based on the Xcode release cycle (so the moral equivalent would be if Android NDK r25c modified clang 16 to report version 25... they don't do that, so they don't really need to be treated as their own compiler ever.)


I think Apple’s clang is the one they build the OS with, and they don’t want to run the risk of introducing a compiler bug late into a project.

So, they pick what’s current early in a project and stick with it.

They may add a few backports of bug fixes to that, but that’s it.

IMO, that’s a good strategy.


Contrasting opinion, it's a terrible strategy. Limiting the entire ecoystem of devs on your platform to features that have not only shipped but stabilized over 5 years prior on other platforms is nonsensical. Compare to MSFT, which is frankly ahead of the curve when it comes to compiler feature support, and even has the entire STL open sourced.


> even has the entire STL open sourced.

You do realize that everything from llvm/clang, gcc, libc++ to libstdc++ is open source? MSVC is late in that regard (and the compiler itself is as closed as can be).


Yes I hack on llvm and clang. Where can I submit a PR to Apple Clang?


You can absolutely use a different compiler as an apple dev. Just might be a touch tougher to set up a non-standard build


Sorry, this might be a dumb question, but I'm not sure what you mean by "as an Apple dev".

I assume you mean "as a developer [anybody] developing software on an Apple platform".

I would be surprised if Apple employees were free to choose their compiler.


Compiler version used to compile the OS mandating same compiler version to compile all apps for the OS is a very head-scratching strategy.


It’s commonly known as dogfooding, and it’s a very common (and I’d argue, the correct) strategy. It’s more head scratching IMO for there to be two standards on compiler stability.


There are no two standards on compiler stability - there is one and it is called ABI. What Apple chose is rather an outstanding case and not really common when you consider all the operating systems and their flavors.


If we were to presuppose that Apple already has a new compiler version that works with new C++ features, but doesn’t think it’s ready yet, than IMO it stands to reason that they’re also not confident that the ABI emitted by said compiler will be something they’re ready to support forever. It’s a bad idea to say “go ahead and compile with an unsupported compiler, and we’ll just support the ABI it emits in perpetuity even though we have already admitted it’s not stabilized yet.”


How else do you imagine different compiler vendors with loath of varying compiler versions work on other Unices?


They define a de facto ABI for their compiler, and once they’re confident enough that the code emitted by their compiler actually works and adheres to it, they take it out of beta and say it’s ready to use. No sooner than that. Not sure what you’re asking here.

Remember that supporting C++ features isn’t just about emitting code, it’s about the implementation of libstdc++/libc++ that you have to make sure you don’t paint yourself into a corner with. It’s easy to accidentally write code that needs to be linked to one way, then later on in the development cycle, subtly change it in a way that changes a symbol, or a type layout, etc. This is all fiddly work that they have to spend time getting right.

You mention other compiler vendors: I remember very distinctly times when GCC would change the ABI to libstdc++. I was running Debian sid at the time and there was basically a month where the OS was not usable at all, as packages had to be recompiled against the new libstdc++.

These kinds of issues happen where, if you let people use a complier (and its corresponding stdlib implementation) before it’s ready, you may find that you have to break ABI in order to fix issues with your new language support, and you leave people stranded who may have already compiled their code against the old stdlib.


Itanium ABI is the de facto ABI standard. It's not developed by a single "compiler" but a collaboration of multiple compiler vendors. It works across basically all Unix/Linux platforms, even Windows. GCC broke the ABI and not "changed it to libstdc++" and that was more than 10 years ago with introduction of C++11 - it's a very rare occassion and exactly the reason why we can have nice and open things in Unices without worrying that software will suddenly break. Mistakes do slip from time to time such as the recent one with LLVM (15) starting to emulate SSE2 when one is not available on the HW but the code makes explicit use of it. Again, such things are rather an exception and my understanding is that Apple chooses quite the opposite strategy - they break their ABI much more often. I see that only as an annoyance which generates unnecessary extra work to keep your code running. I also think that it makes it somewhat impossible to use vanilla clang and mix it with apple-clang binaries. It's a PITA from developer PoV.


I meant “changed libstdc++’s ABI”, not changed to libstdc++.

ABI doesn’t just mean calling conventions defined in things like Itanium’s spec. It also means name mangling, size of structs, and many other things. Think “if I make a shared lib and compile it, and a bunch of programs link to it dynamically at runtime, what changes to the lib can break those programs after the fact, if they don’t recompile?” The answer ends up being a lot. Again, remember that supporting new C++ features means adding things to libc++, which is linked at runtime, so you don’t want to mess it up.

Again, I don’t just mean “change the ABI of arbitrary code emitted by the compiler”, I mean the particular exported symbols in the particular implementation of libc++, which is dynamically linked. If they decide to add one extra field to a struct exported by that lib, then oops, they broke ABI. You don’t want to mess this up and you want it to be stable before letting people use it.


I think I have a good understanding what ABI is. The point I am trying to make is that the theory you have doesn't add up to the facts - you mention Apple as more cautious around the changes they make but the reality is that they break the ABI much more often than other vendors.


Unless it changed, tracking down what Android NDK ships is even worse, tracking down git hash codes to guess which clang was imported into NDK rXX.


Update to myself, not only it hasn't had a release since July 2022, we are suppose to track down which LLVM 14 release, the hash clang-r450784d actually maps to, like always.

https://developer.android.com/ndk/downloads


They have definitely in the past added features that they later released as part of product launches and then upstreamed, e.g. ARM64 backend or more recently -fbounds-checks (which I think will be in the new Xcode?) Other things I don't think they ever tried to upstream e.g. I think watchOS bitcode might have been special. In the end it's basically the same reason anyone maintains a fork or a set of patches; better integration and prioritization of the things you need for your products and more control over risk, etc.

It would always be nice to slim the differences and get new releases faster though, of course.


They only need enough for Swift, Objective-C(++) and Metal Shading Language implementations, alongside IO and Driver Kit, the key places where Apple's ecosystem makes use of C++.

Then they used to have the integration of blocks (C extension for lambdas) into the respective frameworks, and their own bitcode format was more stable than LLVM bitcode (deprecated now, most likely fed up with the bitcode fork).


This wiki seems somewhat out of date. For example OP lists support for P2362R3, but the wiki has that as red.


cppreference is indeed a wiki so you can update it if you’d like. Usually the compiler maintainers do.


Does anyone know why the clang that comes with macOS does not support OpenMP, even though upstream clang does? I use OpenMP to teach basic parallel programming, and it is really annoying that the macOS users have to install another compiler to get it working.

(The problem is exacerbated by the ridiculous fact that macOS includes a 'gcc' alias that is not in fact GCC, and which risks shadowing a proper GCC that the students install themselves.)


When Apple initially moved to clang instead of GCC, clang did not support OpenMP. Apple chose vendor lock-in with Grand Central Dispatch (in the same way they would chose vendor lock-in with Metal years later) rather than invest the time in the existing work on a competitive clang OpenMP implementation.

I think the track record of Apple on supporting anything standardized speaks for itself (see OpenGL, OpenCL, OpenMP, C & C++ features, etc) - Apple gives as few fucks about cross-platform development as possible. Apple sees its platform being so valuable that developers will jump through whatever hoops Apple puts in their way, and largely their developers put up with this.


OpenMP vs GCD? That’s apples and oranges. They’re not even in the same ballpark. I can’t fathom how GCD fills the same needs OpenMP targets, nor can I see how GCD is Apple’s “no” response to OpenMP.

And GCD is open source (not sure when the source was first made available, though). It even supports Linux (thanks to Swift) though that’s recent.


OpenMP and GCD are very different in some ways, yet very similar in others. Both provide threadpool-based parallelism, and both provided "managed" parallelism well before C and C++ gained standardized parallelism via std::async/std::future/std::thread. If you want vendor-supported threadpool parallelism on MacOS, GCD was the singular answer for years. They aren't exactly compatible, but neither are Cilk or TBB to OpenMP, yet all of these approaches can be used to perform a similar subset of parallelized operations.

libdispatch is open source, and available on Linux, but I can't see any reason to use it versus the alternatives of TBB and OpenMP, unless you were trying to port an application/library originally written for MacOS/iOS.


> Apple chose vendor lock-in with Grand Central Dispatch

I will note here that this vendor lock-in is one of the (if not the) main reasons Apple et al. moved away from the GPLed GCC.

The ability to lock in users is the central difference between open source and Free Software.

As such, this is WAI from the Open Source perspective.


This isn't necessarily a free software versus open source issue. Apple could have just as easily continued to ship a GCC version with OpenMP disabled. Sure you could build your own with-OpenMP GCC from source, just like you can build MacOS-compatible upstream Clang from source now. But third-party dev tools will always be a pain and an additional barrier to use.

There are a couple of notable examples of major software shipping OpenMP-using code on MacOS, namely R and Matlab, but the structure of these projects means that few of their users have to encounter the complexity of getting an OpenMP-supporting toolchain working. Not so easy for a library author where nearly all of your users will need to use a special toolchain.


> Apple could have just as easily continued to ship a GCC version with OpenMP disabled.

Sure, and one of their users could have distributed a version that put it back in.


OpenCL was created by Apple...


I don't know the answer to your original question, but based on this StackOverflow answer (https://stackoverflow.com/a/60564952/2682729), it seems like a small compiler wrapper should do the trick to get the same experience across platforms without having to install another compiler.

Depending on the platforms you need to support, a more heavyweight but more reproducible solution would be to use a fixed LLVM toolchain, say using Bazel.


The parallel versioning scheme of apple clang is truly annoying, as it often interferes with feature detection macros


No std::format? Or am I just not searching for the right thing?


No clue what it will appear as once it is there, but I'm not seeing it listed as Apple supported in the cppreference table either. It is listed as "Text Formatting" there.

https://en.cppreference.com/w/cpp/compiler_support


Finally, it's great that Apple added library support for ranges and PMR (memory resource) support. Currently, with a stable Xcode, you are living with clang 14. Link [1] is helpful for matching clang versions and placing preprocessor guards. Many new features (like pmr) were available in 'experimental' headers but not implemented in libc++ or any experimental library that lies nearby 'libc++'. Usually, I expect an experimental library like libstdc++fs that contains the implementation of experimental features. Starting with Xcode 15, I have seen a 'libc++experimental.a' library in a package. Could someone confirm the existence of this library in a beta installation?

[1] https://en.wikipedia.org/wiki/Xcode#Xcode_11.0_-_14.x_(since...


> and PMR (memory resource) support.

note that this sadly will require your users to use a macOS version that isn't even released yet (or rebuild your own libc++) as Apple ties libc++ to the OS releases. when I see the amount of people around me still on 10.x...


Thank you, good point.

It is a small note "Minimum deployment target" at the original article. Seems like features tied to target OS are: PMR, filesystem, to_chars/from_chars and newest atomic-based synchronisation primitives.


std::variant and std::optional also don't work below 10.14


TIL about P2327R1 (De-deprecating volatile compound operations) [0] and the earlier (P1152) deprecation of volatile compound expressions due to those giving the incorrect appearance of atomicity. I'm shaking my head. The `volatile` keyword has a very specific and useful meaning, and P1152 should never have happened.

[0] https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p23...


Neat! I kept pestering them about how to figure this stuff out and hopefully they got enough people doing it that they finally made a page for it.


When did they start calling it Apple Clang? It was Apple LLVM Compiler for the longest time.


As far back as 2007 it was called clang. I'm not sure if it was called clang internally before that. See the seventh slide in the linked presentation.

https://web.archive.org/web/20190403123249/http://llvm.org/d...


Apple has publicly referred to the compiler that they ship with Xcode as the "Apple LLVM Compiler", even though the command line tool was still "clang". E.g., `clang --version` might have reported "Apple LLVM version 7.0.0 (clang-700.1.76)" instead of what it says now, "Apple clang version 14.0.3" on my system.

MacPorts suggests that the --version string changed in Xcode 11 with macOS 10.14 Mojave, but I don't know if the Clang name was reflected in the Xcode GUI at that point. https://trac.macports.org/wiki/XcodeVersionInfo


They're not the same thing.

Clang is a compiler for C and C++ and Objective-C and Objective-C++.

LLVM is the underlying technology which is used by clang, but it's also used by other compilers (e.g. Swift uses LLVM, and some major JavaScript compilers as well).

Neither is owned by Apple - they're open source projects with contributors from Microsoft, Google, ARM, Intel, AMD and many others.


Apple has publicly referred to the C/C++/Objective-C compiler that ships with Xcode as the "Apple LLVM Compiler", apparently a marketing name for their variant of Clang. I was commenting on the fact that the linked article refers to "Apple Clang" which is a deviation from a long-standing practice. I understand the difference between Clang and LLVM; I've committed to both.


> De-deprecating volatile compound operations.

Thank goodness. Those deprecatios are a pain in the butt.


I kind of understand that for embedded. Where do you need to use it when targeting MacOS?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: