Skip to content

Commit 982cb9d

Browse files
committed
Generate
Signed-off-by: Yuki Kishimoto <[email protected]>
1 parent 0cf73a0 commit 982cb9d

18 files changed

+102122
-37
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>AvailableLibraries</key>
6+
<array>
7+
<dict>
8+
<key>BinaryPath</key>
9+
<string>libnostr_sdk_ffi.a</string>
10+
<key>LibraryIdentifier</key>
11+
<string>ios-arm64</string>
12+
<key>LibraryPath</key>
13+
<string>libnostr_sdk_ffi.a</string>
14+
<key>SupportedArchitectures</key>
15+
<array>
16+
<string>arm64</string>
17+
</array>
18+
<key>SupportedPlatform</key>
19+
<string>ios</string>
20+
</dict>
21+
<dict>
22+
<key>BinaryPath</key>
23+
<string>libnostr_sdk_ffi.a</string>
24+
<key>LibraryIdentifier</key>
25+
<string>ios-arm64-simulator</string>
26+
<key>LibraryPath</key>
27+
<string>libnostr_sdk_ffi.a</string>
28+
<key>SupportedArchitectures</key>
29+
<array>
30+
<string>arm64</string>
31+
</array>
32+
<key>SupportedPlatform</key>
33+
<string>ios</string>
34+
<key>SupportedPlatformVariant</key>
35+
<string>simulator</string>
36+
</dict>
37+
</array>
38+
<key>CFBundlePackageType</key>
39+
<string>XFWK</string>
40+
<key>XCFrameworkFormatVersion</key>
41+
<string>1.0</string>
42+
</dict>
43+
</plist>

android/CMakeLists.txt

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,77 @@
1-
cmake_minimum_required(VERSION 3.4.1)
1+
# Generated by uniffi-bindgen-react-native
2+
cmake_minimum_required(VERSION 3.9.0)
23
project(NostrSdkReactNative)
34

45
set (CMAKE_VERBOSE_MAKEFILE ON)
5-
set (CMAKE_CXX_STANDARD 14)
6+
set (CMAKE_CXX_STANDARD 17)
67

7-
add_library(nostr-sdk-react-native SHARED
8-
../cpp/nostr-sdk-react-native.cpp
9-
cpp-adapter.cpp
8+
# Resolve the path to the uniffi-bindgen-react-native package
9+
execute_process(
10+
COMMAND node -p "require.resolve('uniffi-bindgen-react-native/package.json')"
11+
OUTPUT_VARIABLE UNIFFI_BINDGEN_PATH
12+
OUTPUT_STRIP_TRAILING_WHITESPACE
13+
)
14+
string(REGEX
15+
REPLACE "/package\\.json$" ""
16+
UNIFFI_BINDGEN_PATH ${UNIFFI_BINDGEN_PATH}
1017
)
1118

1219
# Specifies a path to native header files.
1320
include_directories(
14-
../cpp
21+
../cpp
22+
../cpp/generated
23+
24+
${UNIFFI_BINDGEN_PATH}/cpp/includes
25+
)
26+
27+
add_library(rust-nostr-nostr-sdk-react-native SHARED
28+
../cpp/rust-nostr-nostr-sdk-react-native.cpp
29+
../cpp/generated/nostr_sdk.cpp
30+
cpp-adapter.cpp
31+
)
32+
33+
# Set C++ compiler flags
34+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2")
35+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions")
36+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -frtti")
37+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector-all")
38+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
39+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
40+
41+
cmake_path(
42+
SET MY_RUST_LIB
43+
${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libnostr_sdk_ffi.a
44+
NORMALIZE
45+
)
46+
add_library(my_rust_lib STATIC IMPORTED)
47+
set_target_properties(my_rust_lib PROPERTIES IMPORTED_LOCATION ${MY_RUST_LIB})
48+
49+
# Add ReactAndroid libraries, being careful to account for different versions.
50+
find_package(ReactAndroid REQUIRED CONFIG)
51+
find_library(LOGCAT log)
52+
53+
# REACTNATIVE_MERGED_SO seems to be only be set in a build.gradle.kt file,
54+
# which we don't use. Thus falling back to version number sniffing.
55+
if (ReactAndroid_VERSION_MINOR GREATER_EQUAL 76)
56+
set(REACTNATIVE_MERGED_SO true)
57+
endif()
58+
59+
# https://github.com/react-native-community/discussions-and-proposals/discussions/816
60+
# This if-then-else can be removed once this library does not support version below 0.76
61+
if (REACTNATIVE_MERGED_SO)
62+
target_link_libraries(rust-nostr-nostr-sdk-react-native ReactAndroid::reactnative)
63+
else()
64+
target_link_libraries(rust-nostr-nostr-sdk-react-native
65+
ReactAndroid::turbomodulejsijni
66+
ReactAndroid::react_nativemodule_core
67+
)
68+
endif()
69+
70+
find_package(fbjni REQUIRED CONFIG)
71+
target_link_libraries(
72+
rust-nostr-nostr-sdk-react-native
73+
fbjni::fbjni
74+
ReactAndroid::jsi
75+
${LOGCAT}
76+
my_rust_lib
1577
)

android/build.gradle

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
1+
// Generated by uniffi-bindgen-react-native
2+
13
buildscript {
2-
ext.getExtOrDefault = {name ->
3-
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['NostrSdkReactNative_' + name]
4-
}
4+
// Buildscript is evaluated before everything else so we can't use getExtOrDefault
5+
def kotlin_version = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : project.properties["DummyLibForAndroid_kotlinVersion"]
56

67
repositories {
78
google()
89
mavenCentral()
910
}
1011

1112
dependencies {
12-
classpath "com.android.tools.build:gradle:8.7.2"
13+
classpath "com.android.tools.build:gradle:7.2.1"
1314
// noinspection DifferentKotlinGradleVersion
14-
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
15+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
1516
}
1617
}
1718

@@ -20,10 +21,20 @@ def reactNativeArchitectures() {
2021
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
2122
}
2223

24+
def isNewArchitectureEnabled() {
25+
return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
26+
}
27+
2328
apply plugin: "com.android.library"
2429
apply plugin: "kotlin-android"
2530

26-
apply plugin: "com.facebook.react"
31+
if (isNewArchitectureEnabled()) {
32+
apply plugin: "com.facebook.react"
33+
}
34+
35+
def getExtOrDefault(name) {
36+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["NostrSdkReactNative_" + name]
37+
}
2738

2839
def getExtOrIntegerDefault(name) {
2940
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["NostrSdkReactNative_" + name]).toInteger()
@@ -55,23 +66,20 @@ android {
5566
defaultConfig {
5667
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
5768
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
69+
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
5870

71+
buildFeatures {
72+
prefab true
73+
}
5974
externalNativeBuild {
6075
cmake {
61-
cppFlags "-frtti -fexceptions -Wall -fstack-protector-all"
62-
arguments "-DANDROID_STL=c++_shared"
76+
arguments '-DANDROID_STL=c++_shared'
6377
abiFilters (*reactNativeArchitectures())
64-
65-
buildTypes {
66-
debug {
67-
cppFlags "-O1 -g"
68-
}
69-
release {
70-
cppFlags "-O2"
71-
}
72-
}
7378
}
7479
}
80+
ndk {
81+
abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64"
82+
}
7583
}
7684

7785
externalNativeBuild {
@@ -101,10 +109,12 @@ android {
101109

102110
sourceSets {
103111
main {
104-
java.srcDirs += [
105-
"generated/java",
106-
"generated/jni"
107-
]
112+
if (isNewArchitectureEnabled()) {
113+
java.srcDirs += [
114+
"generated/java",
115+
"generated/jni"
116+
]
117+
}
108118
}
109119
}
110120
}
@@ -117,12 +127,17 @@ repositories {
117127
def kotlin_version = getExtOrDefault("kotlinVersion")
118128

119129
dependencies {
120-
implementation "com.facebook.react:react-android"
130+
// For < 0.71, this will be from the local maven repo
131+
// For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
132+
//noinspection GradleDynamicVersion
133+
implementation "com.facebook.react:react-native:+"
121134
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
122135
}
123136

124-
react {
125-
jsRootDir = file("../src/")
126-
libraryName = "NostrSdkReactNative"
127-
codegenJavaPackageName = "com.nostrsdkreactnative"
137+
if (isNewArchitectureEnabled()) {
138+
react {
139+
jsRootDir = file("../src/")
140+
libraryName = "NostrSdkReactNative"
141+
codegenJavaPackageName = "com.nostrsdkreactnative"
142+
}
128143
}

android/cpp-adapter.cpp

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,63 @@
1+
// Generated by uniffi-bindgen-react-native
12
#include <jni.h>
2-
#include "nostr-sdk-react-native.h"
3+
#include <jsi/jsi.h>
4+
#include <ReactCommon/CallInvokerHolder.h>
5+
#include "rust-nostr-nostr-sdk-react-native.h"
36

4-
extern "C"
5-
JNIEXPORT jdouble JNICALL
7+
namespace jsi = facebook::jsi;
8+
namespace react = facebook::react;
9+
10+
// Automated testing checks Java_com_nostrsdkreactnative_NostrSdkReactNativeModule and rustnostr_nostrsdkreactnative
11+
// by comparing the whole line here.
12+
/*
613
Java_com_nostrsdkreactnative_NostrSdkReactNativeModule_nativeMultiply(JNIEnv *env, jclass type, jdouble a, jdouble b) {
7-
return nostrsdkreactnative::multiply(a, b);
14+
return rustnostr_nostrsdkreactnative::multiply(a, b);
15+
}
16+
*/
17+
18+
// Installer coming from NostrSdkReactNativeModule
19+
extern "C"
20+
JNIEXPORT jboolean JNICALL
21+
Java_com_nostrsdkreactnative_NostrSdkReactNativeModule_nativeInstallRustCrate(
22+
JNIEnv *env,
23+
jclass type,
24+
jlong rtPtr,
25+
jobject callInvokerHolderJavaObj
26+
) {
27+
// https://github.com/realm/realm-js/blob/main/packages/realm/binding/android/src/main/cpp/io_realm_react_RealmReactModule.cpp#L122-L145
28+
// React Native uses the fbjni library for handling JNI, which has the concept of "hybrid objects",
29+
// which are Java objects containing a pointer to a C++ object. The CallInvokerHolder, which has the
30+
// invokeAsync method we want access to, is one such hybrid object.
31+
// Rather than reworking our code to use fbjni throughout, this code unpacks the C++ object from the Java
32+
// object `callInvokerHolderJavaObj` manually, based on reverse engineering the fbjni code.
33+
34+
// 1. Get the Java object referred to by the mHybridData field of the Java holder object
35+
auto callInvokerHolderClass = env->GetObjectClass(callInvokerHolderJavaObj);
36+
auto hybridDataField = env->GetFieldID(callInvokerHolderClass, "mHybridData", "Lcom/facebook/jni/HybridData;");
37+
auto hybridDataObj = env->GetObjectField(callInvokerHolderJavaObj, hybridDataField);
38+
39+
// 2. Get the destructor Java object referred to by the mDestructor field from the myHybridData Java object
40+
auto hybridDataClass = env->FindClass("com/facebook/jni/HybridData");
41+
auto destructorField =
42+
env->GetFieldID(hybridDataClass, "mDestructor", "Lcom/facebook/jni/HybridData$Destructor;");
43+
auto destructorObj = env->GetObjectField(hybridDataObj, destructorField);
44+
45+
// 3. Get the mNativePointer field from the mDestructor Java object
46+
auto destructorClass = env->FindClass("com/facebook/jni/HybridData$Destructor");
47+
auto nativePointerField = env->GetFieldID(destructorClass, "mNativePointer", "J");
48+
auto nativePointerValue = env->GetLongField(destructorObj, nativePointerField);
49+
50+
// 4. Cast the mNativePointer back to its C++ type
51+
auto nativePointer = reinterpret_cast<facebook::react::CallInvokerHolder*>(nativePointerValue);
52+
auto jsCallInvoker = nativePointer->getCallInvoker();
53+
54+
auto runtime = reinterpret_cast<jsi::Runtime *>(rtPtr);
55+
return rustnostr_nostrsdkreactnative::installRustCrate(*runtime, jsCallInvoker);
856
}
57+
58+
extern "C"
59+
JNIEXPORT jboolean JNICALL
60+
Java_com_nostrsdkreactnative_NostrSdkReactNativeModule_nativeCleanupRustCrate(JNIEnv *env, jclass type, jlong rtPtr) {
61+
auto runtime = reinterpret_cast<jsi::Runtime *>(rtPtr);
62+
return rustnostr_nostrsdkreactnative::cleanupRustCrate(*runtime);
63+
}
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
2+
<!-- Generated by uniffi-bindgen-react-native -->
13
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
24
package="com.nostrsdkreactnative">
3-
</manifest>
5+
</manifest>
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Generated by uniffi-bindgen-react-native
2+
package com.nostrsdkreactnative
3+
4+
import com.facebook.react.bridge.ReactApplicationContext
5+
import com.facebook.react.module.annotations.ReactModule
6+
import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder
7+
8+
@ReactModule(name = NostrSdkReactNativeModule.NAME)
9+
class NostrSdkReactNativeModule(reactContext: ReactApplicationContext) :
10+
NativeNostrSdkReactNativeSpec(reactContext) {
11+
12+
override fun getName(): String {
13+
return NAME
14+
}
15+
16+
// Two native methods implemented in cpp-adapter.cpp, and ultimately
17+
// rust-nostr-nostr-sdk-react-native.cpp
18+
19+
external fun nativeInstallRustCrate(runtimePointer: Long, callInvoker: CallInvokerHolder): Boolean
20+
external fun nativeCleanupRustCrate(runtimePointer: Long): Boolean
21+
22+
override fun installRustCrate(): Boolean {
23+
val context = this.reactApplicationContext
24+
return nativeInstallRustCrate(
25+
context.javaScriptContextHolder!!.get(),
26+
context.jsCallInvokerHolder!!
27+
)
28+
}
29+
30+
override fun cleanupRustCrate(): Boolean {
31+
return nativeCleanupRustCrate(
32+
this.reactApplicationContext.javaScriptContextHolder!!.get()
33+
)
34+
}
35+
36+
companion object {
37+
const val NAME = "NostrSdkReactNative"
38+
39+
init {
40+
System.loadLibrary("rust-nostr-nostr-sdk-react-native")
41+
}
42+
}
43+
}

0 commit comments

Comments
 (0)