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 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