Skip to content

Commit

Permalink
checkpoint:
Browse files Browse the repository at this point in the history
- fixed iOS issues and added all functions already written for android
- downgrade RN version for example
- improved READM instructions for adding more bindings
- changed cbindgen config to generate C headers
  • Loading branch information
v-almonacid committed Jul 2, 2020
1 parent dc6390c commit 0b87dde
Show file tree
Hide file tree
Showing 31 changed files with 1,129 additions and 346 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Expand Up @@ -7,6 +7,9 @@
node_modules/
npm-debug.log
yarn-error.log
package-lock.json
yarn.lock


# Xcode
#
Expand Down
35 changes: 25 additions & 10 deletions README.md
@@ -1,3 +1,5 @@
>DISCLAIMER: the code contained in this repo is experimental and still in WIP status.
# react-native-haskell-shelley

## Getting started
Expand All @@ -22,34 +24,47 @@ HaskellShelley;

Note: the terms function and method may be used interchangeably.

We'll start from the lowest level (rust) up to the highest level (JS).
The process is basically as follows: we start by writting a rust wrapper of some struct method from our target rust library. Both iOS and Android require specific rust wrappers, so there are separate folder (`rust/ios` and `rust/android`). When this project is compiled by the host react native app, all the wrappers are transformed into a native library. In Android, java can directly interact with the rust binaries (the instructions for compiling our rust library are in `build.gradle`), while in iOS there is an additional step in which the rust library is transformed into C, with which can we easily interact with through Objective-C. This intermediate step is contained in `ios/build.sh`, where we basically use `cbindgen` to automatically generate C binaries as well as C headers (which are written in `rust/include/react_native_haskell_shelley.h`).
After writing the corresponding iOS and Android wrappers, we finally just write a simple JS library in `index.js` and define its types in `index.d.ts`.

### Android
// TODO

For every new class:

- Add a new rust module named `<class_name.rs>` (snake_case) in `rust/src/android/`. Here is where we add rust wrappers of the corresponding rust struct methods from the library we want to bind. You can check other modules to see how this is done in `rust/src/android/`.
- Add a `use` declaration in `rust/src/android/mod.rs`
- ...


Now you are ready to add functions for your class/rust structure.

For every new function in the module:
- Declare an equivalent java function to the target rust function in `android/src/main/java/io/emurgo/rnhaskellshelley/Native.java`. The function name must be in camelCase and should respect the name given to the corresponding rust function (note that the rust functions include a prefix in the form `Java_io_emurgo_rnhaskellshelley_Native`).
- Add a rust wrapper of the form: `pub unsafe extern "C" fn Java_io_emurgo_rnhaskellshelley_Native_functionNameInCamelCase`
- Declare an equivalent java function to the target rust function in `android/src/main/java/io/emurgo/rnhaskellshelley/Native.java`. The function name must be in camelCase and
corresponds to the last part (in camelCase) of the rust wrapper signature mentioned above.

- Add the implementation of the java function that will be exposed to react native in `android/src/main/java/io/emurgo/rnhaskellshelley/HaskellShelleyModule.java`.
- Add the implementation of the java function that will be exposed to react native in `android/src/main/java/io/emurgo/rnhaskellshelley/HaskellShelleyModule.java`. Note that the types and signatures in `HaskellShelleyModule.java` are different from `Native.jave`. In the former, we use java types while in the later we use rust types, ie., we match the signatures of the corresponding rust wrappers.

### iOS
// TODO

For every new class:

- Add a new rust module named `<class_name.rs>` (snake_case) in `rust/src/ios/`.
- Add a `use` declaration in `rust/src/ios/mod.rs`

As you may have noticed, the two steps above are equivalent to those with Android. The difference is that the rust wrappers are written differently.

For every new function in the module:
- Add a rust wrapper of the form: `pub unsafe extern "C" fn function_name_in_snake_case`
- Write a iOS-native wrapper in Objective-C in `ios/HaskellShelley.m`. In contrast to Android (java), the iOS native wrappers can't directly interact with rust so we actually use a C library.


### Additional steps in Rust

- Add new class in `rust/src/ptr_impl.rs`
- Add new classes in `rust/src/ptr_impl.rs`

### Javascript
// TODO

For new classes:
For new classes and methods:

1. Add the javascript class signature in `index.d.ts`
2. Add the javascript class implementation `index.js`
3.
4 changes: 2 additions & 2 deletions example/ios/Podfile.lock
Expand Up @@ -175,7 +175,7 @@ SPEC CHECKSUMS:
React-jsi: 8e128c4d0d8febc2977ef617d1c09bb54326069c
React-jsiexecutor: 7a3554f703a58963ec80b860144ea0f0e9b910e1
React-jsinspector: d4ed52225912efe0019bb7f1a225aec20f23049a
react-native-haskell-shelley: 882dc7ce4308ebe727d032669d245b18661cd387
react-native-haskell-shelley: f46f8f75597882d5ca69bccadd3cfdea75bf9457
React-RCTActionSheet: b27ff3cf3a68f917c46d2b94abf938b625b96570
React-RCTAnimation: 9e4708e5bd65fca8285ce7c0aa076f3f4fa5c2f8
React-RCTBlob: 6eafcc3a24f33785692a7be24918ade607bc8719
Expand All @@ -188,6 +188,6 @@ SPEC CHECKSUMS:
React-RCTWebSocket: fca087d583724aa0e5fef7d911f0f2a28d0f2736
yoga: 616fde658be980aa60a2158835170f3f9c2d04b4

PODFILE CHECKSUM: b60392e8fc849f5da30c5bbfadedc5791f069a17
PODFILE CHECKSUM: 5a605fb21b09bb0bd53cf39d1d084327693cb446

COCOAPODS: 1.9.1
57 changes: 43 additions & 14 deletions example/ios/example.xcodeproj/project.pbxproj
Expand Up @@ -16,7 +16,7 @@
2D02E4BD1E0B4A84006451C7 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
2D02E4BF1E0B4AB3006451C7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
2DCD954D1E0B4F2C00145EB5 /* exampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* exampleTests.m */; };
C71734745A1BCAFC7040D8A6 /* libPods-example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ABE0167FFB8D949968EEDA70 /* libPods-example.a */; };
65E63CD663AD11EE62079316 /* libPods-example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D6723D4F8C473AB122264FFE /* libPods-example.a */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -50,11 +50,11 @@
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = example/main.m; sourceTree = "<group>"; };
2D02E47B1E0B4A5D006451C7 /* example-tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "example-tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
2D02E4901E0B4A5D006451C7 /* example-tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "example-tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
8B67A980E087C4CF4FC3A21C /* Pods-example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example.release.xcconfig"; path = "Target Support Files/Pods-example/Pods-example.release.xcconfig"; sourceTree = "<group>"; };
ABE0167FFB8D949968EEDA70 /* libPods-example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-example.a"; sourceTree = BUILT_PRODUCTS_DIR; };
37321E0EDDA66DD4C27807BE /* Pods-example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example.debug.xcconfig"; path = "Target Support Files/Pods-example/Pods-example.debug.xcconfig"; sourceTree = "<group>"; };
98E052EBE6D82947399E21D2 /* Pods-example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example.release.xcconfig"; path = "Target Support Files/Pods-example/Pods-example.release.xcconfig"; sourceTree = "<group>"; };
D6723D4F8C473AB122264FFE /* libPods-example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-example.a"; sourceTree = BUILT_PRODUCTS_DIR; };
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
ED2971642150620600B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS12.0.sdk/System/Library/Frameworks/JavaScriptCore.framework; sourceTree = DEVELOPER_DIR; };
F9B632AF965E6CE0FC609CCF /* Pods-example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example.debug.xcconfig"; path = "Target Support Files/Pods-example/Pods-example.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand All @@ -69,7 +69,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
C71734745A1BCAFC7040D8A6 /* libPods-example.a in Frameworks */,
65E63CD663AD11EE62079316 /* libPods-example.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -126,7 +126,7 @@
children = (
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
ED2971642150620600B7C4FE /* JavaScriptCore.framework */,
ABE0167FFB8D949968EEDA70 /* libPods-example.a */,
D6723D4F8C473AB122264FFE /* libPods-example.a */,
);
name = Frameworks;
sourceTree = "<group>";
Expand Down Expand Up @@ -167,10 +167,9 @@
C708B295F8C973BE38578588 /* Pods */ = {
isa = PBXGroup;
children = (
F9B632AF965E6CE0FC609CCF /* Pods-example.debug.xcconfig */,
8B67A980E087C4CF4FC3A21C /* Pods-example.release.xcconfig */,
37321E0EDDA66DD4C27807BE /* Pods-example.debug.xcconfig */,
98E052EBE6D82947399E21D2 /* Pods-example.release.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "<group>";
};
Expand Down Expand Up @@ -199,7 +198,7 @@
isa = PBXNativeTarget;
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "example" */;
buildPhases = (
E23FCEBA5C9D445706642F35 /* [CP] Check Pods Manifest.lock */,
99ACC3E798C5049008A2B617 /* [CP] Check Pods Manifest.lock */,
FD10A7F022414F080027D42C /* Start Packager */,
13B07F871A680F5B00A75B9A /* Sources */,
13B07F8C1A680F5B00A75B9A /* Frameworks */,
Expand Down Expand Up @@ -281,6 +280,7 @@
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
Base,
);
Expand Down Expand Up @@ -344,7 +344,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh";
shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh\n";
};
2D02E4CB1E0B4B27006451C7 /* Bundle React Native Code And Images */ = {
isa = PBXShellScriptBuildPhase;
Expand All @@ -360,7 +360,7 @@
shellPath = /bin/sh;
shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh";
};
E23FCEBA5C9D445706642F35 /* [CP] Check Pods Manifest.lock */ = {
99ACC3E798C5049008A2B617 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
Expand Down Expand Up @@ -528,11 +528,38 @@
};
13B07F941A680F5B00A75B9A /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = F9B632AF965E6CE0FC609CCF /* Pods-example.debug.xcconfig */;
baseConfigurationReference = 37321E0EDDA66DD4C27807BE /* Pods-example.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = NO;
HEADER_SEARCH_PATHS = (
"${SRCROOT}/../../../ios/Pods/Headers/**",
"$(inherited)",
"\"${PODS_ROOT}/Headers/Public\"",
"\"${PODS_ROOT}/Headers/Public/DoubleConversion\"",
"\"${PODS_ROOT}/Headers/Public/React-Core\"",
"\"${PODS_ROOT}/Headers/Public/React-DevSupport\"",
"\"${PODS_ROOT}/Headers/Public/React-RCTActionSheet\"",
"\"${PODS_ROOT}/Headers/Public/React-RCTAnimation\"",
"\"${PODS_ROOT}/Headers/Public/React-RCTBlob\"",
"\"${PODS_ROOT}/Headers/Public/React-RCTImage\"",
"\"${PODS_ROOT}/Headers/Public/React-RCTLinking\"",
"\"${PODS_ROOT}/Headers/Public/React-RCTNetwork\"",
"\"${PODS_ROOT}/Headers/Public/React-RCTSettings\"",
"\"${PODS_ROOT}/Headers/Public/React-RCTText\"",
"\"${PODS_ROOT}/Headers/Public/React-RCTVibration\"",
"\"${PODS_ROOT}/Headers/Public/React-RCTWebSocket\"",
"\"${PODS_ROOT}/Headers/Public/React-cxxreact\"",
"\"${PODS_ROOT}/Headers/Public/React-fishhook\"",
"\"${PODS_ROOT}/Headers/Public/React-jsi\"",
"\"${PODS_ROOT}/Headers/Public/React-jsiexecutor\"",
"\"${PODS_ROOT}/Headers/Public/React-jsinspector\"",
"\"${PODS_ROOT}/Headers/Public/glog\"",
"\"${PODS_ROOT}/Headers/Public/react-native-haskell-shelley\"",
"\"${PODS_ROOT}/Headers/Public/yoga\"",
"\"${PODS_ROOT}/Headers/Public/Folly\"",
);
INFOPLIST_FILE = example/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_LDFLAGS = (
Expand All @@ -548,7 +575,7 @@
};
13B07F951A680F5B00A75B9A /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 8B67A980E087C4CF4FC3A21C /* Pods-example.release.xcconfig */;
baseConfigurationReference = 98E052EBE6D82947399E21D2 /* Pods-example.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = 1;
Expand Down Expand Up @@ -721,6 +748,7 @@
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
s = "";
};
name = Debug;
};
Expand Down Expand Up @@ -767,6 +795,7 @@
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
s = "";
};
name = Release;
};
Expand Down
Expand Up @@ -14,10 +14,10 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "83CBBA2D1A601D0E00E9B192"
BuildableName = "libReact.a"
BlueprintIdentifier = "1BEE828C124E6416179B904A9F66D794"
BuildableName = "React"
BlueprintName = "React"
ReferencedContainer = "container:../node_modules/react-native/React/React.xcodeproj">
ReferencedContainer = "container:Pods/Pods.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
Expand All @@ -36,7 +36,7 @@
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForRunning = "NO"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "YES">
Expand All @@ -55,6 +55,15 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "example.app"
BlueprintName = "example"
ReferencedContainer = "container:example.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO">
Expand All @@ -67,17 +76,6 @@
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "example.app"
BlueprintName = "example"
ReferencedContainer = "container:example.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
Expand All @@ -99,8 +97,6 @@
ReferencedContainer = "container:example.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
Expand Down
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
5 changes: 4 additions & 1 deletion example/package.json
Expand Up @@ -25,6 +25,9 @@
"react-test-renderer": "16.8.6"
},
"jest": {
"preset": "react-native"
"preset": "react-native",
"modulePathIgnorePatterns": [
"<rootDir>/build"
]
}
}

0 comments on commit 0b87dde

Please sign in to comment.