From b6fb7330299ab6a9aaac9a7a8852168f0df52dba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20L=C3=B8nner=C3=B8d=20Madsen?= Date: Wed, 16 Sep 2026 10:37:39 +0200 Subject: [PATCH] fix(juce): keep the module header includable under `using namespace juce` The SDK is header-only, so including moonbase_licensing.h drags the platform's system headers into the consumer's TU. On Apple those reach MacTypes.h and its global `Point`; on Windows, wingdi.h and its global `Rectangle()`. In a TU with a file-scope `using namespace juce;`, which is how HISE is written, each becomes ambiguous with the matching juce name, and MacTypes.h then stops parsing outright. Measured with clang against JUCE 6.1.3 and 8.0.4: 4 errors either way, in both include orders. Rename those system names out of the way around the system includes, with push_macro/pop_macro so a consumer's own Point/Component macros survive, and MOONBASE_DISABLE_SYSTEM_NAME_SHIM to opt out. This is the same trick JUCE uses in juce_audio_devices.cpp. Add tests/juce/global_using_namespace_juce.cpp to the existing JUCE test target: no other TU in this repo has a global `using namespace juce;`, so CI could not see this class of bug at all. --- docs/juce-module.md | 7 ++++ .../moonbase/detail/crypto/apple_backend.hpp | 18 ++++++++ .../detail/crypto/windows_backend.hpp | 13 ++++++ include/moonbase/legacy_fingerprint.hpp | 12 ++++++ .../moonbase/moonbase_device_id_resolver.hpp | 29 +++++++++++++ modules/moonbase_licensing/README.md | 5 +++ .../moonbase/detail/crypto/apple_backend.hpp | 18 ++++++++ .../detail/crypto/windows_backend.hpp | 13 ++++++ .../moonbase/legacy_fingerprint.hpp | 12 ++++++ .../moonbase/moonbase_device_id_resolver.hpp | 29 +++++++++++++ tests/juce/CMakeLists.txt | 5 ++- tests/juce/global_using_namespace_juce.cpp | 41 +++++++++++++++++++ 12 files changed, 201 insertions(+), 1 deletion(-) create mode 100644 tests/juce/global_using_namespace_juce.cpp diff --git a/docs/juce-module.md b/docs/juce-module.md index eb5e675..9c83f29 100644 --- a/docs/juce-module.md +++ b/docs/juce-module.md @@ -56,6 +56,13 @@ module needs from it only exists from JUCE 8.0.4. The module detects it: link it and the transitions run on `juce::Animator`, leave it out and they run on the module's own equivalent. Nothing to configure either way. +The header is safe to include from a translation unit with a file-scope +`using namespace juce;`, in either include order. Getting there costs one thing +worth knowing about: it renames the two system-header names that would otherwise +be ambiguous with JUCE's, Carbon's `Point` and GDI's `Rectangle()`, so neither is +reachable under its own name once you include the module header. Define +`MOONBASE_DISABLE_SYSTEM_NAME_SHIM` if you need them. + ## Configure + show it ```cpp diff --git a/include/moonbase/detail/crypto/apple_backend.hpp b/include/moonbase/detail/crypto/apple_backend.hpp index 53809fc..c7ed046 100644 --- a/include/moonbase/detail/crypto/apple_backend.hpp +++ b/include/moonbase/detail/crypto/apple_backend.hpp @@ -11,9 +11,27 @@ #include #include +// MacTypes.h's global `Point` is ambiguous with juce::Point in a TU with a +// file-scope `using namespace juce;`, and MacTypes.h itself then stops parsing. +#ifndef MOONBASE_DISABLE_SYSTEM_NAME_SHIM +#pragma push_macro("Point") +#pragma push_macro("Component") +#undef Point +#undef Component +#define Point MoonbaseCarbonDummyPointName +#define Component MoonbaseCarbonDummyCompName +#endif + #include #include +#ifndef MOONBASE_DISABLE_SYSTEM_NAME_SHIM +#undef Point +#undef Component +#pragma pop_macro("Component") +#pragma pop_macro("Point") +#endif + #include "moonbase/detail/crypto/der.hpp" #include "moonbase/errors.hpp" diff --git a/include/moonbase/detail/crypto/windows_backend.hpp b/include/moonbase/detail/crypto/windows_backend.hpp index af4b57e..e7238a2 100644 --- a/include/moonbase/detail/crypto/windows_backend.hpp +++ b/include/moonbase/detail/crypto/windows_backend.hpp @@ -18,10 +18,23 @@ #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif +// wingdi.h's global `Rectangle()` is ambiguous with juce::Rectangle in a TU with +// a file-scope `using namespace juce;`. +#ifndef MOONBASE_DISABLE_SYSTEM_NAME_SHIM +#pragma push_macro("Rectangle") +#undef Rectangle +#define Rectangle MoonbaseGdiDummyRectangleName +#endif + #include #include +#ifndef MOONBASE_DISABLE_SYSTEM_NAME_SHIM +#undef Rectangle +#pragma pop_macro("Rectangle") +#endif + #include "moonbase/detail/crypto/der.hpp" #include "moonbase/errors.hpp" diff --git a/include/moonbase/legacy_fingerprint.hpp b/include/moonbase/legacy_fingerprint.hpp index e00ca0a..ad920a7 100644 --- a/include/moonbase/legacy_fingerprint.hpp +++ b/include/moonbase/legacy_fingerprint.hpp @@ -21,7 +21,19 @@ #ifndef NOMINMAX #define NOMINMAX #endif +// wingdi.h's global `Rectangle()`, see detail/crypto/windows_backend.hpp. +#ifndef MOONBASE_DISABLE_SYSTEM_NAME_SHIM +#pragma push_macro("Rectangle") +#undef Rectangle +#define Rectangle MoonbaseGdiDummyRectangleName +#endif + #include + +#ifndef MOONBASE_DISABLE_SYSTEM_NAME_SHIM +#undef Rectangle +#pragma pop_macro("Rectangle") +#endif #else #include #endif diff --git a/include/moonbase/moonbase_device_id_resolver.hpp b/include/moonbase/moonbase_device_id_resolver.hpp index 3e97495..a9af1db 100644 --- a/include/moonbase/moonbase_device_id_resolver.hpp +++ b/include/moonbase/moonbase_device_id_resolver.hpp @@ -34,7 +34,19 @@ #ifndef NOMINMAX #define NOMINMAX #endif +// wingdi.h's global `Rectangle()`, see detail/crypto/windows_backend.hpp. +#ifndef MOONBASE_DISABLE_SYSTEM_NAME_SHIM +#pragma push_macro("Rectangle") +#undef Rectangle +#define Rectangle MoonbaseGdiDummyRectangleName +#endif + #include + +#ifndef MOONBASE_DISABLE_SYSTEM_NAME_SHIM +#undef Rectangle +#pragma pop_macro("Rectangle") +#endif #else #include #endif @@ -68,9 +80,26 @@ || (defined(TARGET_OS_MACCATALYST) && TARGET_OS_MACCATALYST)) \ && !defined(MOONBASE_FINGERPRINT_NO_IOKIT) #define MOONBASE_FINGERPRINT_USE_IOKIT 1 +// MacTypes.h's global `Point`, see detail/crypto/apple_backend.hpp. +#ifndef MOONBASE_DISABLE_SYSTEM_NAME_SHIM +#pragma push_macro("Point") +#pragma push_macro("Component") +#undef Point +#undef Component +#define Point MoonbaseCarbonDummyPointName +#define Component MoonbaseCarbonDummyCompName +#endif + #include #include #include + +#ifndef MOONBASE_DISABLE_SYSTEM_NAME_SHIM +#undef Point +#undef Component +#pragma pop_macro("Component") +#pragma pop_macro("Point") +#endif #endif #endif diff --git a/modules/moonbase_licensing/README.md b/modules/moonbase_licensing/README.md index bbcaf83..45a070a 100644 --- a/modules/moonbase_licensing/README.md +++ b/modules/moonbase_licensing/README.md @@ -88,6 +88,11 @@ needs from it only exists from JUCE 8.0.4. The module detects it: link it and th transitions run on `juce::Animator`, leave it out and they run on the module's own equivalent, with the same curves. +The header is safe to include from a translation unit with a file-scope +`using namespace juce;`, in either include order. See +[the JUCE module guide](../../docs/juce-module.md) for the one caveat that comes with +that. + ## Configure and use Only three fields are required; in a plugin the product and manufacturer names default diff --git a/modules/moonbase_licensing/moonbase/detail/crypto/apple_backend.hpp b/modules/moonbase_licensing/moonbase/detail/crypto/apple_backend.hpp index 53809fc..c7ed046 100644 --- a/modules/moonbase_licensing/moonbase/detail/crypto/apple_backend.hpp +++ b/modules/moonbase_licensing/moonbase/detail/crypto/apple_backend.hpp @@ -11,9 +11,27 @@ #include #include +// MacTypes.h's global `Point` is ambiguous with juce::Point in a TU with a +// file-scope `using namespace juce;`, and MacTypes.h itself then stops parsing. +#ifndef MOONBASE_DISABLE_SYSTEM_NAME_SHIM +#pragma push_macro("Point") +#pragma push_macro("Component") +#undef Point +#undef Component +#define Point MoonbaseCarbonDummyPointName +#define Component MoonbaseCarbonDummyCompName +#endif + #include #include +#ifndef MOONBASE_DISABLE_SYSTEM_NAME_SHIM +#undef Point +#undef Component +#pragma pop_macro("Component") +#pragma pop_macro("Point") +#endif + #include "moonbase/detail/crypto/der.hpp" #include "moonbase/errors.hpp" diff --git a/modules/moonbase_licensing/moonbase/detail/crypto/windows_backend.hpp b/modules/moonbase_licensing/moonbase/detail/crypto/windows_backend.hpp index af4b57e..e7238a2 100644 --- a/modules/moonbase_licensing/moonbase/detail/crypto/windows_backend.hpp +++ b/modules/moonbase_licensing/moonbase/detail/crypto/windows_backend.hpp @@ -18,10 +18,23 @@ #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif +// wingdi.h's global `Rectangle()` is ambiguous with juce::Rectangle in a TU with +// a file-scope `using namespace juce;`. +#ifndef MOONBASE_DISABLE_SYSTEM_NAME_SHIM +#pragma push_macro("Rectangle") +#undef Rectangle +#define Rectangle MoonbaseGdiDummyRectangleName +#endif + #include #include +#ifndef MOONBASE_DISABLE_SYSTEM_NAME_SHIM +#undef Rectangle +#pragma pop_macro("Rectangle") +#endif + #include "moonbase/detail/crypto/der.hpp" #include "moonbase/errors.hpp" diff --git a/modules/moonbase_licensing/moonbase/legacy_fingerprint.hpp b/modules/moonbase_licensing/moonbase/legacy_fingerprint.hpp index e00ca0a..ad920a7 100644 --- a/modules/moonbase_licensing/moonbase/legacy_fingerprint.hpp +++ b/modules/moonbase_licensing/moonbase/legacy_fingerprint.hpp @@ -21,7 +21,19 @@ #ifndef NOMINMAX #define NOMINMAX #endif +// wingdi.h's global `Rectangle()`, see detail/crypto/windows_backend.hpp. +#ifndef MOONBASE_DISABLE_SYSTEM_NAME_SHIM +#pragma push_macro("Rectangle") +#undef Rectangle +#define Rectangle MoonbaseGdiDummyRectangleName +#endif + #include + +#ifndef MOONBASE_DISABLE_SYSTEM_NAME_SHIM +#undef Rectangle +#pragma pop_macro("Rectangle") +#endif #else #include #endif diff --git a/modules/moonbase_licensing/moonbase/moonbase_device_id_resolver.hpp b/modules/moonbase_licensing/moonbase/moonbase_device_id_resolver.hpp index 3e97495..a9af1db 100644 --- a/modules/moonbase_licensing/moonbase/moonbase_device_id_resolver.hpp +++ b/modules/moonbase_licensing/moonbase/moonbase_device_id_resolver.hpp @@ -34,7 +34,19 @@ #ifndef NOMINMAX #define NOMINMAX #endif +// wingdi.h's global `Rectangle()`, see detail/crypto/windows_backend.hpp. +#ifndef MOONBASE_DISABLE_SYSTEM_NAME_SHIM +#pragma push_macro("Rectangle") +#undef Rectangle +#define Rectangle MoonbaseGdiDummyRectangleName +#endif + #include + +#ifndef MOONBASE_DISABLE_SYSTEM_NAME_SHIM +#undef Rectangle +#pragma pop_macro("Rectangle") +#endif #else #include #endif @@ -68,9 +80,26 @@ || (defined(TARGET_OS_MACCATALYST) && TARGET_OS_MACCATALYST)) \ && !defined(MOONBASE_FINGERPRINT_NO_IOKIT) #define MOONBASE_FINGERPRINT_USE_IOKIT 1 +// MacTypes.h's global `Point`, see detail/crypto/apple_backend.hpp. +#ifndef MOONBASE_DISABLE_SYSTEM_NAME_SHIM +#pragma push_macro("Point") +#pragma push_macro("Component") +#undef Point +#undef Component +#define Point MoonbaseCarbonDummyPointName +#define Component MoonbaseCarbonDummyCompName +#endif + #include #include #include + +#ifndef MOONBASE_DISABLE_SYSTEM_NAME_SHIM +#undef Point +#undef Component +#pragma pop_macro("Component") +#pragma pop_macro("Point") +#endif #endif #endif diff --git a/tests/juce/CMakeLists.txt b/tests/juce/CMakeLists.txt index 58991a8..2c97813 100644 --- a/tests/juce/CMakeLists.txt +++ b/tests/juce/CMakeLists.txt @@ -22,7 +22,10 @@ endif() juce_add_console_app(MoonbaseJuceTests PRODUCT_NAME "Moonbase JUCE Tests") -target_sources(MoonbaseJuceTests PRIVATE controller_tests.cpp) +target_sources(MoonbaseJuceTests PRIVATE + controller_tests.cpp + # Compile-only guard, see the file header. + global_using_namespace_juce.cpp) target_compile_features(MoonbaseJuceTests PRIVATE cxx_std_17) diff --git a/tests/juce/global_using_namespace_juce.cpp b/tests/juce/global_using_namespace_juce.cpp new file mode 100644 index 0000000..1b6628b --- /dev/null +++ b/tests/juce/global_using_namespace_juce.cpp @@ -0,0 +1,41 @@ +// The module header must be includable from a TU with a file-scope +// `using namespace juce;`, the way HISE is written. No other TU in this repo has +// one, so without this the system-header name collisions (MacTypes.h's `Point`, +// wingdi.h's `Rectangle()`) are invisible to CI. The compile is the assertion. + +#include + +using namespace juce; + +#include + +#include + +namespace +{ +// Unqualified on purpose: anything the system headers leak shows up here. +Point makePoint() { return { 3.0f, 4.0f }; } +Rectangle makeRectangle() { return { 0, 0, 640, 480 }; } + +[[maybe_unused]] Component* component = nullptr; +[[maybe_unused]] Timer* timer = nullptr; +} // namespace + +TEST_CASE("the module header survives a global using namespace juce") +{ + CHECK(makePoint().getDistanceFromOrigin() == doctest::Approx(5.0f)); + CHECK(makeRectangle().getWidth() == 640); + + String text { "moonbase" }; + MemoryBlock block { text.toRawUTF8(), text.getNumBytesAsUTF8() }; + CHECK(block.getSize() == 8); + + Range range { 2, 7 }; + CHECK(range.getLength() == 5); + + Colour colour = Colours::white; + CHECK(colour.isOpaque()); + + moonbase::juce_integration::ActivationConfig config; + CHECK(config.resolvedDeviceIdResolver() != nullptr); +}