Skip to content

Commit

Permalink
feat: Specify RN version as compiler flag (#490)
Browse files Browse the repository at this point in the history
* feat: Specify RN version in iOS

* Set RN version

* docs

* fix: Adjust scripts and add bootstrap

* fix: Fix react-native path again

* feat: Add `REACT_NATIVE_VERSION` flag to gradle

* fix: Use `tasks.register` to avoid reconfiguration

* fix: Use `project.layout.buildDirectory` instead of `project.buildDir`

* fix: arguments with comma

* fix: Use `buildDir` again

* fix: Pass `YES`

* feat: Add CMake C++ flags now

* fix: Indicate default overridden `HybridObject` constructor

* perf: Make `equals()` a bit faster
  • Loading branch information
mrousavy authored Jan 13, 2025
1 parent 646a346 commit bbbeeaf
Show file tree
Hide file tree
Showing 9 changed files with 216 additions and 140 deletions.
256 changes: 128 additions & 128 deletions example/ios/Podfile.lock

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@
],
"scripts": {
"build": "bun run --cwd packages/react-native-nitro-modules build && bun run --cwd packages/nitrogen build && bun run --cwd packages/react-native-nitro-image build",
"bootstrap": "bun i && bun run build && cd example && bundle install && bun pods",
"typecheck": "bun --filter=\"**\" typecheck",
"lint": "bun nitro lint && bun nitrogen lint && bun image lint && bun example lint",
"lint-cpp": "./scripts/clang-format.sh",
"clean": "rm -rf packages/**/tsconfig.tsbuildinfo packages/**/node_modules packages/**/lib",
"clean": "git clean -dfx",
"release": "./scripts/release.sh",
"docs": "bun --cwd docs",
"nitro": "bun --cwd packages/react-native-nitro-modules",
Expand Down
23 changes: 18 additions & 5 deletions packages/react-native-nitro-modules/NitroModules.podspec
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require "json"
require_relative './nitro_pod_utils'

package = JSON.parse(File.read(File.join(__dir__, "package.json")))

Expand Down Expand Up @@ -53,18 +54,30 @@ Pod::Spec.new do |s|
"ios/utils/SwiftClosure.hpp",
]

compiler_flags = "$(inherited) FOLLY_NO_CONFIG FOLLY_CFG_NO_COROUTINES"
if has_react_native()
react_native_version = get_react_native_version()
compiler_flags += " HAS_REACT_NATIVE REACT_NATIVE_VERSION=#{react_native_version}"
end

s.pod_target_xcconfig = {
# Use C++ 20
"CLANG_CXX_LANGUAGE_STANDARD" => "c++20",
# Enables C++ <-> Swift interop (by default it's only C)
"SWIFT_OBJC_INTEROP_MODE" => "objcxx",
# Enables stricter modular headers
"DEFINES_MODULE" => "YES",
# C++ compiler flags, mainly for folly.
"GCC_PREPROCESSOR_DEFINITIONS" => "$(inherited) FOLLY_NO_CONFIG FOLLY_CFG_NO_COROUTINES"
# C++ compiler flags, mainly for RN version and folly.
"GCC_PREPROCESSOR_DEFINITIONS" => compiler_flags
}

s.dependency 'React-jsi'
s.dependency 'React-callinvoker'
install_modules_dependencies(s)
if has_react_native()
# Using Nitro in react-native
s.dependency 'React-jsi'
s.dependency 'React-callinvoker'
install_modules_dependencies(s)
else
# Using Nitro somewhere else (NativeScript? Bare iOS?)
raise "Couldn't find react-native - are you trying to use Nitro outside of React Native?"
end
end
6 changes: 6 additions & 0 deletions packages/react-native-nitro-modules/android/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ add_library(NitroModules SHARED
${android_files}
)

# Add C++ flags
if (HAS_REACT_NATIVE)
message(STATUS "Building with React Native v${REACT_NATIVE_VERSION}...")
add_compile_definitions(HAS_REACT_NATIVE REACT_NATIVE_VERSION=${REACT_NATIVE_VERSION})
endif ()

# Specifies a path to native header files.
include_directories(
# Shared C++ includes
Expand Down
33 changes: 31 additions & 2 deletions packages/react-native-nitro-modules/android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import groovy.json.JsonSlurper

buildscript {
repositories {
google()
Expand All @@ -9,6 +11,28 @@ buildscript {
}
}

def getReactNativePackagePath() {
return file(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim())
}

def hasReactNative() {
def path = getReactNativePackagePath()
return path.exists()
}

def getReactNativeVersion() {
logger.info("[NitroModules] Finding react-native package...")
def reactNativePackage = getReactNativePackagePath()
if (!reactNativePackage.exists()) {
throw new GradleException("[NitroModules] Couldn't find react-native path!")
}
def json = new JsonSlurper().parse(reactNativePackage)
def version = json.version
def minorVersion = version.tokenize('.')[1].toInteger()
logger.info("[NitroModules] Found react-native ${json.version} (${minorVersion}) at ${reactNativePackage}!")
return minorVersion
}

def reactNativeArchitectures() {
def value = rootProject.getProperties().get("reactNativeArchitectures")
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
Expand Down Expand Up @@ -49,7 +73,12 @@ android {
externalNativeBuild {
cmake {
cppFlags "-frtti -fexceptions -Wall -Wextra -fstack-protector-all"
arguments "-DANDROID_STL=c++_shared"
if (hasReactNative()) {
def reactNativeVersion = getReactNativeVersion()
arguments "-DANDROID_STL=c++_shared", "-DHAS_REACT_NATIVE=YES", "-DREACT_NATIVE_VERSION=${reactNativeVersion}"
} else {
arguments "-DANDROID_STL=c++_shared"
}
abiFilters (*reactNativeArchitectures())

buildTypes {
Expand Down Expand Up @@ -154,7 +183,7 @@ if (isNewArchitectureEnabled()) {
}
}

task prepareHeaders(type: Copy) {
tasks.register('prepareHeaders', Copy) {
from fileTree('./src/main/cpp').filter { it.isFile() }
from fileTree('../cpp/').filter { it.isFile() }
include "*.hpp"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
namespace margelo::nitro {

HybridObject::HybridObject(const char* name) : HybridObjectPrototype(), _name(name) {}
HybridObject::~HybridObject() {}

std::string HybridObject::toString() {
return "[HybridObject " + std::string(_name) + "]";
Expand All @@ -19,7 +18,7 @@ std::string HybridObject::getName() {
return _name;
}

bool HybridObject::equals(std::shared_ptr<HybridObject> other) {
bool HybridObject::equals(const std::shared_ptr<HybridObject>& other) {
return this == other.get();
}

Expand Down
4 changes: 2 additions & 2 deletions packages/react-native-nitro-modules/cpp/core/HybridObject.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class HybridObject : public virtual jsi::NativeState, public HybridObjectPrototy
* Called when no more references to the given `HybridObject` exist in both C++ and JS.
* JS might keep references for longer, as it is a garbage collected language.
*/
virtual ~HybridObject();
~HybridObject() override = default;
/**
* HybridObjects cannot be copied.
*/
Expand Down Expand Up @@ -80,7 +80,7 @@ class HybridObject : public virtual jsi::NativeState, public HybridObjectPrototy
* While two `jsi::Object`s of the same `HybridObject` might not be equal when compared with `==`,
* they might still be the same `HybridObject` - in this case `equals(other)` will return true.
*/
bool equals(std::shared_ptr<HybridObject> other);
bool equals(const std::shared_ptr<HybridObject>& other);
/**
* Get a string representation of this `HybridObject` - useful for logging or debugging.
*/
Expand Down
27 changes: 27 additions & 0 deletions packages/react-native-nitro-modules/nitro_pod_utils.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
require "json"

# Gets the path of the react-native/package.json file.
def get_react_native_package_path()
pod_root = Pod::Config.instance.installation_root.to_s
return `cd "#{pod_root}" && node --print "require.resolve('react-native/package.json')"`.strip!
end

# Finds out whether react-native is available, or not.
# This works by checking if the react-native node package can be resolved.
def has_react_native()
react_native_package_path = get_react_native_package_path()
return File.exist?(react_native_package_path)
end

# Gets the minor react-native version (e.g 76 for 0.76.4)
def get_react_native_version()
react_native_package_path = get_react_native_package_path()
if !File.exist?(react_native_package_path)
raise "[NitroModules] Couldn't find react-native path! File '#{react_native_package_path}' doesn't exist!"
end
react_native_package = JSON.parse(File.read(react_native_package_path))
react_native_version = react_native_package['version']
react_native_minor_version = react_native_version.split('.')[1].to_i
Pod::UI.puts "[NitroModules] Found react-native #{react_native_version} (#{react_native_minor_version}) in #{File.dirname(react_native_package_path)}!"
return react_native_minor_version
end
1 change: 1 addition & 0 deletions packages/react-native-nitro-modules/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"cpp/",
"app.plugin.js",
"*.podspec",
"nitro_pod_utils.rb",
"README.md"
],
"keywords": [
Expand Down

0 comments on commit bbbeeaf

Please sign in to comment.