Skip to content

Commit 6588c5c

Browse files
authored
feat: added possibility to start module with C++ code enabled (#30)
1 parent 87f5a39 commit 6588c5c

File tree

15 files changed

+151
-11
lines changed

15 files changed

+151
-11
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ If you want to create your own React Native module, scaffolding the project can
1414
- [ESLint](https://eslint.org/), [Prettier](https://prettier.io/), [TypeScript](https://www.typescriptlang.org/) and [Husky](https://github.com/typicode/husky) pre-configured
1515
- Bob pre-configured to compile your files
1616
- CircleCI pre-configured to run tests on the CI
17+
- Use C++ code to boost performance of your modules
1718

1819
<img src="assets/bob-create.gif" width="480px" height="auto">
1920

@@ -26,6 +27,7 @@ Bob can build code for following targets:
2627
- Flow definitions (copies .js files to .flow files)
2728
- TypeScript definitions (uses `tsc` to generate declaration files)
2829
- Android AAR files
30+
- C++ modules
2931

3032
## Why
3133

src/create.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import pack from '../package.json';
1212

1313
const TEMPLATE = path.resolve(__dirname, '../templates/library');
1414
const BINARIES = /(gradlew|\.(jar|keystore|png|jpg|gif))$/;
15+
const CPP_FILES = path.resolve(__dirname, '../templates/cppLibrary');
1516

1617
export default async function create(argv: yargs.Arguments<any>) {
1718
const folder = path.join(process.cwd(), argv.name);
@@ -51,6 +52,7 @@ export default async function create(argv: yargs.Arguments<any>) {
5152
authorEmail,
5253
authorUrl,
5354
githubUrl: repo,
55+
useCpp,
5456
} = (await inquirer.prompt([
5557
{
5658
type: 'input',
@@ -118,13 +120,20 @@ export default async function create(argv: yargs.Arguments<any>) {
118120
},
119121
validate: input => /^https?:\/\//.test(input) || 'Must be a valid URL',
120122
},
123+
{
124+
type: 'confirm',
125+
name: 'useCpp',
126+
message: 'Does your library use C++ code?',
127+
default: false,
128+
},
121129
])) as {
122130
slug: string;
123131
description: string;
124132
authorName: string;
125133
authorEmail: string;
126134
authorUrl: string;
127135
githubUrl: string;
136+
useCpp: boolean;
128137
};
129138

130139
const project = slug.replace(/^(react-native-|@[^/]+\/)/, '');
@@ -143,6 +152,7 @@ export default async function create(argv: yargs.Arguments<any>) {
143152
.slice(1)}`,
144153
package: slug.replace(/[^a-z0-9]/g, '').toLowerCase(),
145154
podspec: slug.replace(/[^a-z0-9]+/g, '-').replace(/^-/, ''),
155+
useCpp,
146156
},
147157
author: {
148158
name: authorName,
@@ -176,6 +186,9 @@ export default async function create(argv: yargs.Arguments<any>) {
176186
};
177187

178188
await copyDir(TEMPLATE, folder);
189+
if (options.project.useCpp) {
190+
await copyDir(CPP_FILES, folder);
191+
}
179192

180193
try {
181194
await spawn.sync(
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
cmake_minimum_required(VERSION 3.4.1)
2+
3+
set (CMAKE_VERBOSE_MAKEFILE ON)
4+
set (CMAKE_CXX_STANDARD 11)
5+
6+
add_library(cpp
7+
SHARED
8+
../cpp/example.cpp
9+
cpp-adapter.cpp
10+
)
11+
12+
# Specifies a path to native header files.
13+
include_directories(
14+
../cpp
15+
)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#include <jni.h>
2+
#include "example.h"
3+
4+
extern "C"
5+
JNIEXPORT jint JNICALL
6+
Java_com_<%= project.package %>_<%= project.name %>Module_nativeMultiply(JNIEnv *env, jclass type, jint a, jint b) {
7+
return example::multiply(a, b);
8+
}

templates/cppLibrary/cpp/example.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#include "example.h"
2+
3+
namespace example {
4+
int multiply(int a, int b) {
5+
return a * b;
6+
}
7+
}

templates/cppLibrary/cpp/example.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#ifndef EXAMPLE_H
2+
#define EXAMPLE_H
3+
4+
namespace example {
5+
int multiply(int a, int b);
6+
}
7+
8+
#endif /* EXAMPLE_H */

templates/library/<%= project.podspec %>.podspec

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,12 @@ Pod::Spec.new do |s|
1313
s.platforms = { :ios => "9.0" }
1414
s.source = { :git => "<%= repo %>.git", :tag => "#{s.version}" }
1515

16-
s.source_files = "ios/**/*.{h,m}"
16+
s.source_files = "ios/**/*.{h,m,mm}"
1717

18+
<% if(project.useCpp==true){ %>
19+
s.source_files = "ios/**/*.{h,m,mm}", "cpp/**/*.{h,cpp}"
20+
<% } else{ %>
21+
s.source_files = "ios/**/*.{h,m,mm}"
22+
<% } %>
1823
s.dependency "React"
1924
end

templates/library/android/build.gradle

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,22 @@ android {
3333
targetSdkVersion getExtOrIntegerDefault('targetSdkVersion')
3434
versionCode 1
3535
versionName "1.0"
36+
<%if (project.useCpp==true) {%>
37+
externalNativeBuild {
38+
cmake {
39+
cppFlags "-O2 -frtti -fexceptions -Wall -fstack-protector-all"
40+
abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
41+
}
42+
}
43+
<%}%>
44+
}
45+
<%if (project.useCpp==true) {%>
46+
externalNativeBuild {
47+
cmake {
48+
path "CMakeLists.txt"
49+
}
3650
}
51+
<%}%>
3752
buildTypes {
3853
release {
3954
minifyEnabled false

templates/library/android/src/main/java/com/<%= project.package %>/<%= project.name %>Module.kt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,23 @@ class <%= project.name %>Module(reactContext: ReactApplicationContext) : ReactCo
1717
fun getDeviceName(promise: Promise) {
1818
promise.resolve(android.os.Build.MODEL)
1919
}
20+
<%if (project.useCpp==true) {%>
21+
22+
@ReactMethod
23+
fun multiply(a: Int, b: Int, promise: Promise) {
24+
promise.resolve(nativeMultiply(a, b));
25+
}
26+
27+
external fun nativeMultiply(a: Int, b: Int): Int;
28+
29+
companion object
30+
{
31+
32+
// Used to load the 'native-lib' library on application startup.
33+
init
34+
{
35+
System.loadLibrary("cpp")
36+
}
37+
}
38+
<%}%>
2039
}

templates/library/example/src/App.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,24 @@ import <%= project.name %> from '<%= project.slug %>';
44

55
export default function App() {
66
const [deviceName, setDeviceName] = React.useState('');
7+
<%if (project.useCpp==true) {%>
8+
const [value, setValue] = React.useState();
9+
<%}%>
10+
711

812
React.useEffect(() => {
913
<%= project.name %>.getDeviceName().then(setDeviceName);
14+
<%if (project.useCpp==true) {%>
15+
<%= project.name %>.multiply(2, 3).then(setValue);
16+
<%}%>
1017
}, []);
1118

1219
return (
1320
<View style={styles.container}>
1421
<Text>Device name: {deviceName}</Text>
22+
<%if (project.useCpp==true) {%>
23+
<Text>C++ mulitply value: {value}</Text>
24+
<%}%>
1525
</View>
1626
);
1727
}

0 commit comments

Comments
 (0)