Unable to build JUCE libraries with clang-18.1.8 and C++23

I’m trying to see if JUCE is appropriate for my project, where I’m using clang-18.1.8 to build on linux and macos to C++23.

I know JUCE is on C++17, but this is a heads up for changes you may need to make for C++23 and a plea to see how I could work around it. Any help appreciated.

The JUCE libraries fail to build on trivial project with clang-18.1.8 on Linux or Mac. I have uploaded it to a gitlab repo.

It fails on building juce::juce_core with the following output…

-- The CXX compiler identification is Clang 18.1.8
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/clang-18 - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/clang++-18 - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found Git: /usr/bin/git (found version "2.40.1") 
-- Found PkgConfig: /usr/bin/pkg-config (found version "1.8.1") 
-- Checking for module 'alsa'
--   Package 'alsa', required by 'virtual:world', not found
-- Checking for modules 'freetype2;fontconfig'
--   Found freetype2, version 26.0.20
--   Found fontconfig, version 2.14.2
-- Checking for module 'gl'
--   Found gl, version 1.2
-- Checking for module 'libcurl'
--   Found libcurl, version 8.2.1
-- Checking for modules 'webkit2gtk-4.0;gtk+-x11-3.0'
--   Found webkit2gtk-4.0, version 2.44.2
--   Found gtk+-x11-3.0, version 3.24.38
-- Configuring juceaide
-- Building juceaide
-- Exporting juceaide
-- Testing juceaide
-- Finished setting up juceaide
-- CPM: Adding package JUCE@8.0.0 (8.0.0 at /home/bruno/.cpmCache/juce/a38112fc097a2915e7330d9b61c844037ca264ae)
-- Configuring done (21.2s)
-- Generating done (0.0s)
-- Build files have been written to: /home/bruno/Work/BadJuceAidBuild/build
[0/2] Re-checking globbed directories...
[1/4] Building CXX object CMakeFiles/hello.dir/home/bruno/.cpmCache/juce/a38112fc097a2915e7330d9b61c844037ca264ae/modules/juce_core/juce_core_CompilationTime.cpp.o
[2/4] Building CXX object CMakeFiles/hello.dir/hello.cpp.o
[3/4] Building CXX object CMakeFiles/hello.dir/home/bruno/.cpmCache/juce/a38112fc097a2915e7330d9b61c844037ca264ae/modules/juce_core/juce_core.cpp.o
FAILED: CMakeFiles/hello.dir/home/bruno/.cpmCache/juce/a38112fc097a2915e7330d9b61c844037ca264ae/modules/juce_core/juce_core.cpp.o 
/usr/bin/clang++-18 -DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1 -DJUCE_MODULE_AVAILABLE_juce_core=1 -DLINUX=1 -DNDEBUG=1 -D_NDEBUG=1 -isystem /home/bruno/.cpmCache/juce/a38112fc097a2915e7330d9b61c844037ca264ae/modules -Wall -std=c++23 -stdlib=libc++ -Wno-deprecated-declarations -I/usr/include/gtk-3.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/pango-1.0 -I/usr/include/harfbuzz/  -I/usr/include/cairo -std=gnu++23 -MD -MT CMakeFiles/hello.dir/home/bruno/.cpmCache/juce/a38112fc097a2915e7330d9b61c844037ca264ae/modules/juce_core/juce_core.cpp.o -MF CMakeFiles/hello.dir/home/bruno/.cpmCache/juce/a38112fc097a2915e7330d9b61c844037ca264ae/modules/juce_core/juce_core.cpp.o.d -o CMakeFiles/hello.dir/home/bruno/.cpmCache/juce/a38112fc097a2915e7330d9b61c844037ca264ae/modules/juce_core/juce_core.cpp.o -c /home/bruno/.cpmCache/juce/a38112fc097a2915e7330d9b61c844037ca264ae/modules/juce_core/juce_core.cpp
In file included from /home/bruno/.cpmCache/juce/a38112fc097a2915e7330d9b61c844037ca264ae/modules/juce_core/juce_core.cpp:49:
In file included from /home/bruno/.cpmCache/juce/a38112fc097a2915e7330d9b61c844037ca264ae/modules/juce_core/juce_core.h:216:
In file included from /home/bruno/.cpmCache/juce/a38112fc097a2915e7330d9b61c844037ca264ae/modules/juce_core/system/juce_StandardHeader.h:62:
In file included from /usr/include/c++/v1/algorithm:1778:
In file included from /usr/include/c++/v1/__algorithm/inplace_merge.h:28:
/usr/include/c++/v1/__memory/unique_ptr.h:66:19: error: invalid application of 'sizeof' to an incomplete type 'juce::NamedPipe::Pimpl'
   66 |     static_assert(sizeof(_Tp) >= 0, "cannot delete an incomplete type");
      |                   ^~~~~~~~~~~
/usr/include/c++/v1/__memory/unique_ptr.h:300:7: note: in instantiation of member function 'std::default_delete<juce::NamedPipe::Pimpl>::operator()' requested here
  300 |       __ptr_.second()(__tmp);
      |       ^
/usr/include/c++/v1/__memory/unique_ptr.h:266:75: note: in instantiation of member function 'std::unique_ptr<juce::NamedPipe::Pimpl>::reset' requested here
  266 |   _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 ~unique_ptr() { reset(); }
      |                                                                           ^
/home/bruno/.cpmCache/juce/a38112fc097a2915e7330d9b61c844037ca264ae/modules/juce_core/network/juce_NamedPipe.cpp:40:12: note: in instantiation of member function 'std::unique_ptr<juce::NamedPipe::Pimpl>::~unique_ptr' requested here
   40 | NamedPipe::NamedPipe() {}
      |            ^
/home/bruno/.cpmCache/juce/a38112fc097a2915e7330d9b61c844037ca264ae/modules/juce_core/network/juce_NamedPipe.h:102:37: note: forward declaration of 'juce::NamedPipe::Pimpl'
  102 |     JUCE_PUBLIC_IN_DLL_BUILD (class Pimpl)
      |                                     ^
1 error generated.
ninja: build stopped: subcommand failed.

Thank you for reporting. We’re looking into this.

2 Likes

It compiles fine with -std=c++17

From my tinkering around this, the bulk of the problems seem to be due to the various Pimpl implementations.

From what I’ve discovered, where a class C uses a unique_ptr member of a forward referenced type T (used quite often for Pimpl classes); the C++23 compiler will fail on compilation of the constructor of class C.

For example, this code:

juce_NamedPipe.cpp

NamedPipe::NamedPipe() {}

In instantiation of member function 'std::unique_ptr<juce::NamedPipe::Pimpl>::~unique_ptr' requested here

/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.5.sdk/usr/include/c++/v1/__memory/unique_ptr.h:66:19 Invalid application of 'sizeof' to an incomplete type
'juce::NamedPipe::Pimpl'

However, NamedPipe::Pimple is actually defined in juce_Files_windows.cpp and juce_NamedPipe_posix.cpp (two different implementations).

So that is going to require quite a lot of work to resolve.

Pete

1 Like

My solution would probably be to declare a base class early, something simply like:

class PimplBase
{
PimpleBase() {}
virtual ~PimpleBase() {}
};

And elsewhere, declare the specific implementation

class PimplImplementation : public MyClass::PimplBase
{
PimplImplementation() {}
virtual ~PimplImplementation() {}

// And other stuff that is private to my implementation
};
1 Like

Thanks for the feedback. Indeed JUCE does not compile with C++23 in its current state, but we’ll soon release a fix for this.

1 Like

can you please clarify, will this fix be backported to 7.x or only 8.x? Thanks.

There is no need to forward declare the pimpl (defeating the pimpl idiom).

The issue is the destructor of the class holding the unique_ptr to the pimpl. That destructor needs to be explicit and have the pimpl class visible so instead of not having it declared (or having it inlined or defaulted in the header) it needs to be present in the cpp where the pimpl class is declared.

.h

struct Pimpy;

struct Z {
   Z();
   ~Z(); // this

   unique_ptr<Pimpy> y;
};

.cpp

struct Pimpy {};

Z::Z() = default;
Z::~Z() = default; // this, now the ~unique_ptr will know the Pimpy type layout structure and size
1 Like

For what it is worth, I’ve now got my code working with C++23, for Apple (macOS, iOS, tvOS, watchOS), Android and Windows.

Mostly, all it required was to change a handful of the Pimpl std::unique_ptr usages, to use std::shared_ptr.

I also changed a use of std::is_pod_v to std::is_standard_layout_v … and a few other small changes.

Best wishes, Pete

1 Like