mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Summary: This Diff introduces some changes in the CodeGen to properly generate the types in the right folder. ## Issue The codegen on iOS defines the output folder once, before creating the generated code. When the code we have to generate is just a TurboModule (TM) or a Fabric Component (FC), this mechanism works properly. However, if a library has to generate both TM and FC, actually using the library type `all`, all the code is generated using the TurboModules' output folder. (**Note:** Android only works in this way) This generates invalid code because all the FC's `#import` directives assumes that the code is generated in the FC output path which, in this case, is not. ## Solution The adopted solution moves the responsibility to decide where the files has to be generated to the CodeGen step instead of in the preparatory phases. The two paths are precomputed in the `generate-artifacts.js` script (the entry point for the CodeGen) and they are passed to all the scripts that requires them. Once they reach the `RNCodegen.js` file, the generators creates the files and save them in the proper paths. ## Changelog [iOS][Changed] - CodeGen now supports the `"all"` library type. Reviewed By: cortinico, dmitryrykun Differential Revision: D35820848 fbshipit-source-id: ce7f5393936e2ae17f8b2c970f6a011d27f641f2
191 lines
4.6 KiB
JavaScript
191 lines
4.6 KiB
JavaScript
/**
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @format
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
let RNCodegen;
|
|
try {
|
|
RNCodegen = require('../packages/react-native-codegen/lib/generators/RNCodegen.js');
|
|
} catch (e) {
|
|
RNCodegen = require('react-native-codegen/lib/generators/RNCodegen.js');
|
|
if (!RNCodegen) {
|
|
throw 'RNCodegen not found.';
|
|
}
|
|
}
|
|
|
|
const fs = require('fs');
|
|
const mkdirp = require('mkdirp');
|
|
const path = require('path');
|
|
const yargs = require('yargs');
|
|
|
|
const argv = yargs
|
|
.option('p', {
|
|
alias: 'platform',
|
|
describe: 'Platform to generate native code artifacts for.',
|
|
})
|
|
.option('s', {
|
|
alias: 'schemaPath',
|
|
describe: 'The path to the schema file.',
|
|
})
|
|
.option('o', {
|
|
alias: 'outputDir',
|
|
describe:
|
|
'DEPRECATED - Path to directory where native code source files should be saved.',
|
|
})
|
|
.option('n', {
|
|
alias: 'libraryName',
|
|
describe: 'Name of specs library.',
|
|
default: 'FBReactNativeSpec',
|
|
})
|
|
.option('j', {
|
|
alias: 'javaPackageName',
|
|
describe: 'Name of Java package.',
|
|
default: 'com.facebook.fbreact.specs',
|
|
})
|
|
.option('t', {
|
|
alias: 'libraryType',
|
|
describe: 'all, components, or modules.',
|
|
default: 'all',
|
|
})
|
|
.option('c', {
|
|
alias: 'componentsOutputDir',
|
|
describe: 'Output directory for the codeGen for Fabric Components',
|
|
})
|
|
.option('m', {
|
|
alias: 'modulesOutputDirs',
|
|
describe: 'Output directory for the codeGen for TurboModules',
|
|
})
|
|
.usage('Usage: $0 <args>')
|
|
.demandOption(
|
|
['platform', 'schemaPath', 'outputDir'],
|
|
'Please provide platform, schema path, and output directory.',
|
|
).argv;
|
|
|
|
const GENERATORS = {
|
|
all: {
|
|
android: ['componentsAndroid', 'modulesAndroid'],
|
|
ios: ['componentsIOS', 'modulesIOS'],
|
|
},
|
|
components: {
|
|
android: ['componentsAndroid'],
|
|
ios: ['componentsIOS'],
|
|
},
|
|
modules: {
|
|
android: ['modulesAndroid'],
|
|
ios: ['modulesIOS'],
|
|
},
|
|
};
|
|
|
|
function deprecated_createOutputDirectoryIfNeeded(
|
|
outputDirectory,
|
|
libraryName,
|
|
) {
|
|
if (!outputDirectory) {
|
|
outputDirectory = path.resolve(__dirname, '..', 'Libraries', libraryName);
|
|
}
|
|
mkdirp.sync(outputDirectory);
|
|
}
|
|
|
|
function createFolderIfDefined(folder) {
|
|
if (folder) {
|
|
mkdirp.sync(folder);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This function read a JSON schema from a path and parses it.
|
|
* It throws if the schema don't exists or it can't be parsed.
|
|
*
|
|
* @parameter schemaPath: the path to the schema
|
|
* @return a valid schema
|
|
* @throw an Error if the schema doesn't exists in a given path or if it can't be parsed.
|
|
*/
|
|
function readAndParseSchema(schemaPath) {
|
|
const schemaText = fs.readFileSync(schemaPath, 'utf-8');
|
|
|
|
if (schemaText == null) {
|
|
throw new Error(`Can't find schema at ${schemaPath}`);
|
|
}
|
|
|
|
try {
|
|
return JSON.parse(schemaText);
|
|
} catch (err) {
|
|
throw new Error(`Can't parse schema to JSON. ${schemaPath}`);
|
|
}
|
|
}
|
|
|
|
function validateLibraryType(libraryType) {
|
|
if (GENERATORS[libraryType] == null) {
|
|
throw new Error(`Invalid library type. ${libraryType}`);
|
|
}
|
|
}
|
|
|
|
function generateSpec(
|
|
platform,
|
|
schemaPath,
|
|
outputDirectory,
|
|
libraryName,
|
|
packageName,
|
|
libraryType,
|
|
componentsOutputDir,
|
|
modulesOutputDirs,
|
|
) {
|
|
validateLibraryType(libraryType);
|
|
|
|
let schema = readAndParseSchema(schemaPath);
|
|
|
|
createFolderIfDefined(componentsOutputDir);
|
|
createFolderIfDefined(modulesOutputDirs);
|
|
deprecated_createOutputDirectoryIfNeeded(outputDirectory, libraryName);
|
|
|
|
RNCodegen.generate(
|
|
{
|
|
libraryName,
|
|
schema,
|
|
outputDirectory,
|
|
packageName,
|
|
componentsOutputDir,
|
|
modulesOutputDirs,
|
|
},
|
|
{
|
|
generators: GENERATORS[libraryType][platform],
|
|
},
|
|
);
|
|
|
|
if (platform === 'android') {
|
|
// Move all components C++ files to a structured jni folder for now.
|
|
// Note: this should've been done by RNCodegen's generators, but:
|
|
// * the generators don't support platform option yet
|
|
// * this subdir structure is Android-only, not applicable to iOS
|
|
const files = fs.readdirSync(outputDirectory);
|
|
const jniOutputDirectory = `${outputDirectory}/jni/react/renderer/components/${libraryName}`;
|
|
mkdirp.sync(jniOutputDirectory);
|
|
files
|
|
.filter(f => f.endsWith('.h') || f.endsWith('.cpp'))
|
|
.forEach(f => {
|
|
fs.renameSync(`${outputDirectory}/${f}`, `${jniOutputDirectory}/${f}`);
|
|
});
|
|
}
|
|
}
|
|
|
|
function main() {
|
|
generateSpec(
|
|
argv.platform,
|
|
argv.schemaPath,
|
|
argv.outputDir,
|
|
argv.libraryName,
|
|
argv.javaPackageName,
|
|
argv.libraryType,
|
|
argv.componentsOutputDir,
|
|
argv.modulesOutputDirs,
|
|
);
|
|
}
|
|
|
|
main();
|