Can I make JUCE plugins with C++23?

I got the impression JUCE won’t be adopting C++23 features for a while, and I’m guessing that’s for backward compatibility. But do I need to worry about that? Can I compile a JUCE plugin with C++23? Can I write my code with C++23 features? Even if I can’t do it directly, can I use a C++23 library in a JUCE project?

I am learning JUCE, C++, CMake at the same time, so I’m not even sure how to check this for myself yet. The Projucer doesn’t have the option for C++23 yet. I’m thinking either JUCE plugins are not compatible with C++23 or it’s because Xcode doesn’t support C++23 yet (and Projucer has to support Xcode).

I installed the latest llvm/clang with homebrew and have no problem with C++23 in CLion, so I’m hoping when I get a better handle on CMake I can build my JUCE plugin with CMake and C++23.

Yes, you can compile JUCE with C++23, which should be expected as C++ is backwards compatible and deprecates code long before it is being removed.
JUCE also does a good job keeping up with maintenance of code being labeled as deprecated just in C++23 and updates to different implementations, so even though they are on C++17 (I think), the code base compiles without any warnings in C++23.

When you create a project with CMake, you should be able to set the C++23 dialect. When you use Projucer, you can select C++20 and later change that in Xcode or your IDE of choice manually. This change however will be overwritten, when you re-save the project in Projucer. Many use Projucer only to do the initial creation and then ditch it entirely.

Using all features in C++23 is not possible due to Apples Clang compiler being majorly behind on the
features. I don’t even believe they fully support C++20.

1 Like

Can someone please confirm if C++20 is supported or not for Apples Clang compiler?
I’m working on a plugin and I currently use C++20. I work on Windows but want to create Apple plugins too at a later stage.

Yes.

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

Looks like they’re pretty much there!

Don’t know what the missing entry for ‘floating point atomic’ means…

Click on it :stuck_out_tongue_winking_eye:

Okay thanks, I got it now. Stop panicking, everyone, Mac does support atomic floats after all.

There’s an official C++ language support page from Apple here

1 Like

Ok, thanks for the info!

Follow up question: Do I have to use Apple Clang in some scenarios? Maybe the MacOS code signing step requires using Apple Clang? If so, I expect that applies to apps on MacOS, iOS, and AU plugins in Apple DAWs. What if I only support VST3?

If you’re releasing on Mac then I’d say you have to support AU as well, otherwise you’ll cut out Logic and Garageband users…even though most other DAWs on Mac support VST3.

Yeah… I want to support AU eventually, so I’m trying to understand what the trade-offs are if I go ahead with C++23.

Reading between the lines, I suspect I must build with XCode and must use Apple Clang for code signing, which means I’m effectively limited to whatever Apple Clang supports. If I use the latest LLVM Clang compiler in my JUCE projects, then I am setting myself up to get stuck unable to support AU and MacOS/iOS until I get it all compiling with Apple Clang. Is this accurate?

So it seems that, although I can technically build JUCE plugins with C++23, unless I’m going the Windows-only route, I have to limit myself to (at best) whatever Apple Clang dialect c++2b currently supports. Sigh… As a web developer who has had to support Safari, this is completely unsurprising.

I don’t know why you would need Apple Clang for code signing/notarisation or AU. Try it out!

În general, newer C++ usage is less portable for some features. Concepts and Coroutines for example can easily have features that work on one toolchain and not implemented on another.

Also, usually with Apple, modern features that relevant to runtime could require newer macOS version.

1 Like

I’ve not been able to build JUCE with a C++23 compiler so far.

Using LLVM 17.0.6 with -std=gnu++23 set by:

set_target_properties(${TARGET}
  PROPERTIES
    CXX_STANDARD 23
    CXX_STANDARD_REQUIRED ON)

I see two ‘incomplete type’ errors:

In file included from /ext/juce/modules/juce_gui_basics/juce_gui_basics.h:60:
In file included from /ext/juce/modules/juce_graphics/juce_graphics.h:58:
In file included from /ext/juce/modules/juce_core/juce_core.h:204:
In file included from /ext/juce/modules/juce_core/system/juce_StandardHeader.h:50:
In file included from /opt/homebrew/opt/llvm/bin/../include/c++/v1/algorithm:1778:
In file included from /opt/homebrew/opt/llvm/bin/../include/c++/v1/__algorithm/inplace_merge.h:28:
/opt/homebrew/opt/llvm/bin/../include/c++/v1/__memory/unique_ptr.h:66:19: error: invalid application of 'sizeof' to an incomplete type 'juce::AccessibilityHandler'
   66 |     static_assert(sizeof(_Tp) >= 0, "cannot delete an incomplete type");
      |                   ^~~~~~~~~~~
/opt/homebrew/opt/llvm/bin/../include/c++/v1/__memory/unique_ptr.h:300:7: note: in instantiation of member function 'std::default_delete<juce::AccessibilityHandler>::operator()' requested here
  300 |       __ptr_.second()(__tmp);
      |       ^
/opt/homebrew/opt/llvm/bin/../include/c++/v1/__memory/unique_ptr.h:266:75: note: in instantiation of member function 'std::unique_ptr<juce::AccessibilityHandler>::reset' requested here
  266 |   _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 ~unique_ptr() { reset(); }
      |                                                                           ^
/ext/juce/modules/juce_gui_basics/layout/juce_Viewport.h:347:20: note: in instantiation of member function 'std::unique_ptr<juce::AccessibilityHandler>::~unique_ptr' requested here
  347 |             return createIgnoredAccessibilityHandler (*this);
      |                    ^
/ext/juce/modules/juce_gui_basics/juce_gui_basics.h:161:11: note: forward declaration of 'juce::AccessibilityHandler'
  161 |     class AccessibilityHandler;
In file included from /ext/juce/modules/juce_gui_basics/juce_gui_basics.h:60:
In file included from /ext/juce/modules/juce_graphics/juce_graphics.h:58:
In file included from /ext/juce/modules/juce_core/juce_core.h:204:
In file included from /ext/juce/modules/juce_core/system/juce_StandardHeader.h:50:
In file included from /opt/homebrew/opt/llvm/bin/../include/c++/v1/algorithm:1778:
In file included from /opt/homebrew/opt/llvm/bin/../include/c++/v1/__algorithm/inplace_merge.h:28:
/opt/homebrew/opt/llvm/bin/../include/c++/v1/__memory/unique_ptr.h:66:19: error: invalid application of 'sizeof' to an incomplete type 'juce::Drawable'
   66 |     static_assert(sizeof(_Tp) >= 0, "cannot delete an incomplete type");
      |                   ^~~~~~~~~~~
/opt/homebrew/opt/llvm/bin/../include/c++/v1/__memory/unique_ptr.h:300:7: note: in instantiation of member function 'std::default_delete<juce::Drawable>::operator()' requested here
  300 |       __ptr_.second()(__tmp);
      |       ^
/opt/homebrew/opt/llvm/bin/../include/c++/v1/__memory/unique_ptr.h:266:75: note: in instantiation of member function 'std::unique_ptr<juce::Drawable>::reset' requested here
  266 |   _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 ~unique_ptr() { reset(); }
      |                                                                           ^
/ext/juce/modules/juce_gui_basics/menus/juce_PopupMenu.h:302:62: note: in instantiation of member function 'std::unique_ptr<juce::Drawable>::~unique_ptr' requested here
  302 |                          std::unique_ptr<Drawable> iconToUse = {});
      |                                                              ^
/ext/juce/modules/juce_gui_basics/juce_gui_basics.h:153:11: note: forward declaration of 'juce::Drawable'
  153 |     class Drawable;
      |           ^

Oh, actually — I remember these errors. I think I had to shuffle a little bit in the include order. But maybe the JUCE team could fix that on develop?