Skip to content

Commit

Permalink
Codegen: Generate module C++ lookup function for JNI next to the spec…
Browse files Browse the repository at this point in the history
… classes

Summary:
The TurboModule system requires a lookup function to map the spec name (name used in JS) to the C++ TurboModule subclass. This is a pure C function. For now, generate one lookup function per set of modules found in the codegen schema.

Changelog: [Internal]

Reviewed By: hramos

Differential Revision: D23618281

fbshipit-source-id: 889e07bdd4f2e5e93c4d14e60225f5b0c6683917
  • Loading branch information
fkgozali authored and facebook-github-bot committed Sep 11, 2020
1 parent e26c280 commit 0351c57
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 19 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ project.xcworkspace

# Gradle
/build/
/packages/react-native-codegen/android/build/
/packages/react-native-codegen/android/gradlePlugin-build/gradlePlugin/build
/packages/rn-tester/android/app/build/
/packages/rn-tester/android/app/gradle/
/packages/rn-tester/android/app/gradlew
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,20 +105,19 @@ public void apply(final Project project) {
extension.codegenJavaPackageName,
new File(generatedSrcDir, "java"));
});
// TODO: generate JNI C++ files.
task.commandLine("echo");
} else {
ImmutableList<String> execCommands =
new ImmutableList.Builder<String>()
.add("yarn")
.addAll(ImmutableList.copyOf(extension.nodeExecutableAndArgs))
.add(extension.codegenGenerateNativeModuleSpecsCLI().getAbsolutePath())
.add("android")
.add(generatedSchemaFile.getAbsolutePath())
.add(outputDir.getAbsolutePath())
.build();
task.commandLine(execCommands);
}

ImmutableList<String> execCommands =
new ImmutableList.Builder<String>()
.add("yarn")
.addAll(ImmutableList.copyOf(extension.nodeExecutableAndArgs))
.add(extension.codegenGenerateNativeModuleSpecsCLI().getAbsolutePath())
.add("android")
.add(generatedSchemaFile.getAbsolutePath())
.add(outputDir.getAbsolutePath())
.add(extension.libraryName)
.build();
task.commandLine(execCommands);
});

// 4. Add dependencies & generated sources to the project.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,24 @@

package com.facebook.react.codegen.plugin;

import com.google.common.base.CaseFormat;
import java.io.File;
import java.util.StringTokenizer;
import org.gradle.api.Project;

public class CodegenPluginExtension {
// TODO: Remove beta.
public String codegenJavaPackageName = "com.facebook.fbreact.specs.beta";
public boolean enableCodegen = false;
public File jsRootDir;
public String libraryName;
public String[] nodeExecutableAndArgs = {"node"};
public File reactNativeRootDir;
public boolean useJavaGenerator = false;

public CodegenPluginExtension(final Project project) {
this.reactNativeRootDir = new File(project.getRootDir(), "node_modules/react-native");
this.libraryName = projectPathToLibraryName(project.getPath());
}

public File codegenDir() {
Expand All @@ -34,4 +38,16 @@ public File codegenGenerateSchemaCLI() {
public File codegenGenerateNativeModuleSpecsCLI() {
return new File(this.reactNativeRootDir, "scripts/generate-native-modules-specs-cli.js");
}

private String projectPathToLibraryName(final String projectPath) {
final StringTokenizer tokenizer = new StringTokenizer(projectPath, ":-_.");
final StringBuilder nameBuilder = new StringBuilder();

while (tokenizer.hasMoreTokens()) {
nameBuilder.append(CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, tokenizer.nextToken()));
}
nameBuilder.append("Spec");

return nameBuilder.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ Native::_MODULE_NAME_::SpecJSI::Native::_MODULE_NAME_::SpecJSI(const JavaTurboMo
::_PROPERTIES_MAP_::
}`.trim();

const oneModuleLookupTemplate = ` if (moduleName == "::_MODULE_NAME_::") {
return std::make_shared<Native::_MODULE_NAME_::SpecJSI>(params);
}`;

const template = `
/**
* Copyright (c) Facebook, Inc. and its affiliates.
Expand All @@ -61,6 +65,10 @@ namespace react {
::_MODULES_::
std::shared_ptr<TurboModule> ::_LIBRARY_NAME_::_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params) {
::_MODULE_LOOKUP_::
}
} // namespace react
} // namespace facebook
`;
Expand Down Expand Up @@ -323,10 +331,17 @@ module.exports = {
})
.join('\n');

const moduleLookup = Object.keys(nativeModules)
.map(name => {
return oneModuleLookupTemplate.replace(/::_MODULE_NAME_::/g, name);
})
.join('\n');

const fileName = `${moduleSpecName}-generated.cpp`;
const replacedTemplate = template
.replace(/::_MODULES_::/g, modules)
.replace(/::_LIBRARY_NAME_::/g, libraryName)
.replace(/::_MODULE_LOOKUP_::/g, moduleLookup)
.replace(/::_INCLUDE_::/g, `"${moduleSpecName}.h"`);
return new Map([[fileName, replacedTemplate]]);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ namespace react {
::_MODULES_::
std::shared_ptr<TurboModule> ::_LIBRARY_NAME_::_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params);
} // namespace react
} // namespace facebook
`;
Expand Down Expand Up @@ -71,8 +73,9 @@ module.exports = {
.join('\n');

const fileName = `${moduleSpecName}.h`;
const replacedTemplate = template.replace(/::_MODULES_::/g, modules);

const replacedTemplate = template
.replace(/::_MODULES_::/g, modules)
.replace(/::_LIBRARY_NAME_::/g, libraryName);
return new Map([[fileName, replacedTemplate]]);
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const JavaTurboMo
methodMap_[\\"getArrays\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getArrays};
}
std::shared_ptr<TurboModule> COMPLEX_OBJECTS_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params) {
if (moduleName == \\"SampleTurboModule\\") {
return std::make_shared<NativeSampleTurboModuleSpecJSI>(params);
}
}
} // namespace react
} // namespace facebook
",
Expand Down Expand Up @@ -72,6 +78,12 @@ NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const JavaTurboMo
}
std::shared_ptr<TurboModule> EMPTY_NATIVE_MODULES_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params) {
if (moduleName == \\"SampleTurboModule\\") {
return std::make_shared<NativeSampleTurboModuleSpecJSI>(params);
}
}
} // namespace react
} // namespace facebook
",
Expand Down Expand Up @@ -107,6 +119,12 @@ NativeAliasTurboModuleSpecJSI::NativeAliasTurboModuleSpecJSI(const JavaTurboModu
methodMap_[\\"cropImage\\"] = MethodMetadata {1, __hostFunction_NativeAliasTurboModuleSpecJSI_cropImage};
}
std::shared_ptr<TurboModule> NATIVE_MODULES_WITH_TYPE_ALIASES_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params) {
if (moduleName == \\"AliasTurboModule\\") {
return std::make_shared<NativeAliasTurboModuleSpecJSI>(params);
}
}
} // namespace react
} // namespace facebook
",
Expand Down Expand Up @@ -190,6 +208,18 @@ NativeExceptionsManagerSpecJSI::NativeExceptionsManagerSpecJSI(const JavaTurboMo
methodMap_[\\"dismissRedbox\\"] = MethodMetadata {0, __hostFunction_NativeExceptionsManagerSpecJSI_dismissRedbox};
}
std::shared_ptr<TurboModule> REAL_MODULE_EXAMPLE_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params) {
if (moduleName == \\"CameraRollManager\\") {
return std::make_shared<NativeCameraRollManagerSpecJSI>(params);
}
if (moduleName == \\"ImagePickerIOS\\") {
return std::make_shared<NativeImagePickerIOSSpecJSI>(params);
}
if (moduleName == \\"ExceptionsManager\\") {
return std::make_shared<NativeExceptionsManagerSpecJSI>(params);
}
}
} // namespace react
} // namespace facebook
",
Expand Down Expand Up @@ -273,6 +303,12 @@ NativeSampleTurboModuleSpecJSI::NativeSampleTurboModuleSpecJSI(const JavaTurboMo
methodMap_[\\"getValueWithPromise\\"] = MethodMetadata {1, __hostFunction_NativeSampleTurboModuleSpecJSI_getValueWithPromise};
}
std::shared_ptr<TurboModule> SIMPLE_NATIVE_MODULES_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params) {
if (moduleName == \\"SampleTurboModule\\") {
return std::make_shared<NativeSampleTurboModuleSpecJSI>(params);
}
}
} // namespace react
} // namespace facebook
",
Expand Down Expand Up @@ -317,6 +353,15 @@ NativeSample2TurboModuleSpecJSI::NativeSample2TurboModuleSpecJSI(const JavaTurbo
methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc};
}
std::shared_ptr<TurboModule> TWO_MODULES_DIFFERENT_FILES_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params) {
if (moduleName == \\"SampleTurboModule\\") {
return std::make_shared<NativeSampleTurboModuleSpecJSI>(params);
}
if (moduleName == \\"Sample2TurboModule\\") {
return std::make_shared<NativeSample2TurboModuleSpecJSI>(params);
}
}
} // namespace react
} // namespace facebook
",
Expand Down Expand Up @@ -359,6 +404,15 @@ NativeSample2TurboModuleSpecJSI::NativeSample2TurboModuleSpecJSI(const JavaTurbo
methodMap_[\\"voidFunc\\"] = MethodMetadata {0, __hostFunction_NativeSample2TurboModuleSpecJSI_voidFunc};
}
std::shared_ptr<TurboModule> TWO_MODULES_SAME_FILE_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params) {
if (moduleName == \\"SampleTurboModule\\") {
return std::make_shared<NativeSampleTurboModuleSpecJSI>(params);
}
if (moduleName == \\"Sample2TurboModule\\") {
return std::make_shared<NativeSample2TurboModuleSpecJSI>(params);
}
}
} // namespace react
} // namespace facebook
",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public:
};
std::shared_ptr<TurboModule> COMPLEX_OBJECTS_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params);
} // namespace react
} // namespace facebook
",
Expand Down Expand Up @@ -64,6 +66,8 @@ public:
};
std::shared_ptr<TurboModule> EMPTY_NATIVE_MODULES_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params);
} // namespace react
} // namespace facebook
",
Expand Down Expand Up @@ -99,6 +103,8 @@ public:
};
std::shared_ptr<TurboModule> NATIVE_MODULES_WITH_TYPE_ALIASES_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params);
} // namespace react
} // namespace facebook
",
Expand Down Expand Up @@ -150,6 +156,8 @@ public:
};
std::shared_ptr<TurboModule> REAL_MODULE_EXAMPLE_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params);
} // namespace react
} // namespace facebook
",
Expand Down Expand Up @@ -185,6 +193,8 @@ public:
};
std::shared_ptr<TurboModule> SIMPLE_NATIVE_MODULES_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params);
} // namespace react
} // namespace facebook
",
Expand Down Expand Up @@ -228,6 +238,8 @@ public:
};
std::shared_ptr<TurboModule> TWO_MODULES_DIFFERENT_FILES_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params);
} // namespace react
} // namespace facebook
",
Expand Down Expand Up @@ -271,6 +283,8 @@ public:
};
std::shared_ptr<TurboModule> TWO_MODULES_SAME_FILE_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params);
} // namespace react
} // namespace facebook
",
Expand Down
8 changes: 4 additions & 4 deletions scripts/generate-native-modules-specs-cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@ const mkdirp = require('mkdirp');
const os = require('os');
const path = require('path');

function generateSpec(platform, schemaPath, outputDirectory) {
const libraryName = 'FBReactNativeSpec';
const moduleSpecName = 'FBReactNativeSpec';
function generateSpec(platform, schemaPath, outputDirectory, libraryName) {
const moduleSpecName = libraryName;
const schemaText = fs.readFileSync(schemaPath, 'utf-8');

if (schemaText == null) {
Expand Down Expand Up @@ -97,7 +96,8 @@ function main() {
const platform = args[0];
const schemaPath = args[1];
const outputDir = args[2];
generateSpec(platform, schemaPath, outputDir);
const libraryName = args[3] || 'FBReactNativeSpec';
generateSpec(platform, schemaPath, outputDir, libraryName);
}

main();

0 comments on commit 0351c57

Please sign in to comment.