From 68479ed8e502f201da35e16a69c7b1f1cd27f305 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Mon, 31 Aug 2026 22:06:46 +0200 Subject: [PATCH 1/2] fix: Hide React renderer headers from the Swift-facing `NitroModules` module Since 0.37.0, `ReactProp.hpp`, `ViewComponentDescriptor.hpp` and `ViewPropsHolderState.hpp` are in `public_header_files`, so CocoaPods puts them into the generated `NitroModules` modulemap. Their includes reach , and on React Native <= 0.83 glog's modulemap cannot be compiled as a clang module (its `logging.h` includes `glog/log_severity.h` from inside `namespace google`). Every Swift `import NitroModules` then fails in static-library builds: error: import of module 'glog.glog.log_severity' appears within namespace 'google' error: could not build module 'glog' error: could not build Objective-C module 'NitroModules' Swift never uses these C++ view types - only nitrogen-generated C++ includes them. Guard their contents with clang's `__building_module()` so they stay public and textually includable, but become empty inside the module build. Verified in a bare React Native 0.80.3 app (static libraries): unfixed 0.37.1 fails as above, with this change it builds; reverting the change makes it fail again. RN 0.84+ was never affected (its glog ships a textual-headers modulemap). --- .../cpp/utils/NitroDefines.hpp | 7 +++++++ .../react-native-nitro-modules/cpp/views/ReactProp.hpp | 9 +++++++++ .../cpp/views/ViewComponentDescriptor.hpp | 9 +++++++++ .../cpp/views/ViewPropsHolderState.hpp | 9 +++++++++ 4 files changed, 34 insertions(+) diff --git a/packages/react-native-nitro-modules/cpp/utils/NitroDefines.hpp b/packages/react-native-nitro-modules/cpp/utils/NitroDefines.hpp index f26400ac9..e4d09da87 100644 --- a/packages/react-native-nitro-modules/cpp/utils/NitroDefines.hpp +++ b/packages/react-native-nitro-modules/cpp/utils/NitroDefines.hpp @@ -31,6 +31,13 @@ #define _CXX_INTEROP_HAS_ATTRIBUTE(x) 0 #endif +// Helper to find out if this code is currently being compiled as part of a given clang module +#ifdef __building_module +#define NITRO_BUILDING_MODULE(module) __building_module(module) +#else +#define NITRO_BUILDING_MODULE(module) 0 +#endif + // Closed/Final Enums #if _CXX_INTEROP_HAS_ATTRIBUTE(enum_extensibility) // Enum is marked as closed/not extensible diff --git a/packages/react-native-nitro-modules/cpp/views/ReactProp.hpp b/packages/react-native-nitro-modules/cpp/views/ReactProp.hpp index ad9e4c0c0..e5ff10c9f 100644 --- a/packages/react-native-nitro-modules/cpp/views/ReactProp.hpp +++ b/packages/react-native-nitro-modules/cpp/views/ReactProp.hpp @@ -4,6 +4,13 @@ #pragma once +#include "NitroDefines.hpp" + +// This header includes headers, which cannot be compiled as part of a +// clang module - so it is hidden from the Swift-facing `NitroModules` module and can only +// be included textually, from C++. +#if !NITRO_BUILDING_MODULE(NitroModules) + #include "BorrowingReference.hpp" #include "IsFunctionProp.hpp" #include "JSIConverter.hpp" @@ -121,3 +128,5 @@ class ReactProp final { }; } // namespace margelo::nitro + +#endif diff --git a/packages/react-native-nitro-modules/cpp/views/ViewComponentDescriptor.hpp b/packages/react-native-nitro-modules/cpp/views/ViewComponentDescriptor.hpp index a2d9f29a8..7f34a266e 100644 --- a/packages/react-native-nitro-modules/cpp/views/ViewComponentDescriptor.hpp +++ b/packages/react-native-nitro-modules/cpp/views/ViewComponentDescriptor.hpp @@ -4,6 +4,13 @@ #pragma once +#include "NitroDefines.hpp" + +// This header includes headers, which cannot be compiled as part of a +// clang module - so it is hidden from the Swift-facing `NitroModules` module and can only +// be included textually, from C++. +#if !NITRO_BUILDING_MODULE(NitroModules) + #include "RawPropsCompat.hpp" #include @@ -75,3 +82,5 @@ class ViewComponentDescriptor final : public react::ConcreteComponentDescriptor< }; } // namespace margelo::nitro + +#endif diff --git a/packages/react-native-nitro-modules/cpp/views/ViewPropsHolderState.hpp b/packages/react-native-nitro-modules/cpp/views/ViewPropsHolderState.hpp index cedaf0023..4486094b9 100644 --- a/packages/react-native-nitro-modules/cpp/views/ViewPropsHolderState.hpp +++ b/packages/react-native-nitro-modules/cpp/views/ViewPropsHolderState.hpp @@ -4,6 +4,13 @@ #pragma once +#include "NitroDefines.hpp" + +// This header includes headers, which cannot be compiled as part of a +// clang module - so it is hidden from the Swift-facing `NitroModules` module and can only +// be included textually, from C++. +#if !NITRO_BUILDING_MODULE(NitroModules) + #include #include #include @@ -48,3 +55,5 @@ struct ViewPropsHolderState final { }; } // namespace margelo::nitro + +#endif From a9dbfb4053c1bac9edbcafac8aaf9b6480682115 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20Fazekas?= Date: Mon, 31 Aug 2026 22:04:29 +0200 Subject: [PATCH 2/2] ci: Build `NitroModules` pod in a bare React Native 0.80 app (static libraries) Since 0.37.0, plain CocoaPods iOS builds (static libraries, no `use_frameworks!`) fail on React Native <= 0.83 with: glog/logging.h:512:1: error: import of module 'glog.glog.log_severity' appears within namespace 'google' react/debug/react_native_assert.h: error: could not build module 'glog' :0: error: could not build Objective-C module 'NitroModules' 0.37.0 added `ReactProp.hpp`, `ViewComponentDescriptor.hpp` and `ViewPropsHolderState.hpp` to `public_header_files`, so they became part of the CocoaPods-generated NitroModules modulemap. Their includes reach , and glog's modulemap on RN <= 0.83 cannot be compiled as a clang module - so every Swift `import NitroModules` fails. RN 0.84+ ships a textual-headers glog modulemap, which is why the example app (and existing CI) cannot see this. This workflow pins the regression: it is red on main and should turn green once the renderer-including headers are hidden from the Swift-facing module. --- .github/workflows/build-ios-rn080.yml | 73 +++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 .github/workflows/build-ios-rn080.yml diff --git a/.github/workflows/build-ios-rn080.yml b/.github/workflows/build-ios-rn080.yml new file mode 100644 index 000000000..2e2437acd --- /dev/null +++ b/.github/workflows/build-ios-rn080.yml @@ -0,0 +1,73 @@ +name: Build iOS (React Native 0.80) + +# Builds the NitroModules pod inside a bare React Native 0.80 app with static +# libraries (the CocoaPods default). React Native <= 0.83 builds glog from +# source with a modulemap that cannot be compiled as a clang module, so any +# NitroModules public header that (transitively) includes +# breaks every `import NitroModules` from Swift. The example app cannot cover +# this: its React Native ships glog with a textual-headers modulemap (RN 0.84+). + +on: + push: + branches: + - main + paths: + - '.github/workflows/build-ios-rn080.yml' + - 'packages/react-native-nitro-modules/cpp/**' + - 'packages/react-native-nitro-modules/ios/**' + - 'packages/react-native-nitro-modules/*.podspec' + - 'packages/react-native-nitro-modules/nitro_pod_utils.rb' + pull_request: + paths: + - '.github/workflows/build-ios-rn080.yml' + - 'packages/react-native-nitro-modules/cpp/**' + - 'packages/react-native-nitro-modules/ios/**' + - 'packages/react-native-nitro-modules/*.podspec' + - 'packages/react-native-nitro-modules/nitro_pod_utils.rb' + +env: + XCODE_VERSION: '26.5' + RN_VERSION: '0.80.3' + +jobs: + build: + name: Build NitroModules pod (RN 0.80, static libraries) + runs-on: macOS-26 + steps: + - uses: actions/checkout@v7 + + - name: Select Xcode ${{ env.XCODE_VERSION }} + run: sudo xcode-select -s "/Applications/Xcode_${{ env.XCODE_VERSION }}.app/Contents/Developer" + + - name: Create a bare React Native ${{ env.RN_VERSION }} app + working-directory: ${{ runner.temp }} + run: npx -y @react-native-community/cli@latest init TestApp --version ${{ env.RN_VERSION }} --skip-git-init --install-pods false + + - name: Add NitroModules to the Podfile + working-directory: ${{ runner.temp }}/TestApp/ios + env: + NITRO_PATH: ${{ github.workspace }}/packages/react-native-nitro-modules + run: | + ruby - <<'RUBY' + podfile = File.read('Podfile') + pod_line = " pod 'NitroModules', :path => '#{ENV['NITRO_PATH']}'\n" + raise 'use_native_modules! not found in template Podfile' unless podfile.sub!(/^(\s*config = use_native_modules!\n)/) { "#{$1}#{pod_line}" } + File.write('Podfile', podfile) + RUBY + + - name: Install Pods + working-directory: ${{ runner.temp }}/TestApp/ios + run: pod install + + - name: Build NitroModules pod + working-directory: ${{ runner.temp }}/TestApp/ios + run: | + set -o pipefail + xcodebuild \ + -project Pods/Pods.xcodeproj \ + -target NitroModules \ + -sdk iphonesimulator \ + -configuration Debug \ + ARCHS=arm64 \ + ONLY_ACTIVE_ARCH=YES \ + build | xcbeautify --renderer github-actions