Skip to content

Commit

Permalink
Update CodeGen to leverage the outputDir as suggested in diff review (
Browse files Browse the repository at this point in the history
#33729)

Summary:
Pull Request resolved: #33729

This PR addresses [this comment](https://www.internalfb.com/diff/D35820848?dst_version_fbid=496290878846487&transaction_fbid=355967423221044).

It makes the CodeGen to the `outputDir` as base directory for the codegen.

Finally, it updates the unit tests accordingly.

## Changelog
[iOS][Changed] - use `outputDir` as base directory for the codegen and remove the possibility to customize the intermediate path. The generated code requires specific paths in the `#include` directive.

Reviewed By: cortinico, dmitryrykun

Differential Revision: D35935282

fbshipit-source-id: 1f044852c27d2e14b031613592bc4b941f366218
  • Loading branch information
Riccardo Cipolleschi authored and facebook-github-bot committed Apr 28, 2022
1 parent 5205c4a commit c732728
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 123 deletions.
4 changes: 2 additions & 2 deletions packages/react-native-codegen/DEFS.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -220,14 +220,14 @@ def rn_codegen_modules(
# iOS Buck build isn't fully working in OSS, so let's skip it for OSS for now.
fb_native.genrule(
name = generate_module_hobjcpp_name,
cmd = "cp $(location :{})/{}.h $OUT".format(generate_fixtures_rule_name, name),
cmd = "cp $(location :{})/{}/{}.h $OUT".format(generate_fixtures_rule_name, name, name),
out = "{}.h".format(name),
labels = ["codegen_rule"],
)

fb_native.genrule(
name = generate_module_mm_name,
cmd = "cp $(location :{})/{}-generated.mm $OUT".format(generate_fixtures_rule_name, name),
cmd = "cp $(location :{})/{}/{}-generated.mm $OUT".format(generate_fixtures_rule_name, name, name),
out = "{}-generated.mm".format(name),
labels = ["codegen_rule"],
)
Expand Down
15 changes: 9 additions & 6 deletions packages/react-native-codegen/src/generators/RNCodegen.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ type LibraryOptions = $ReadOnly<{
outputDirectory: string,
packageName?: string, // Some platforms have a notion of package, which should be configurable.
assumeNonnull: boolean,
componentsOutputDir?: string, // optional for backward compatibility
modulesOutputDir?: string, // optional for backward compatibility
}>;

type SchemasOptions = $ReadOnly<{
Expand Down Expand Up @@ -195,16 +193,21 @@ module.exports = {
outputDirectory,
packageName,
assumeNonnull,
componentsOutputDir,
modulesOutputDir,
}: LibraryOptions,
{generators, test}: LibraryConfig,
): boolean {
schemaValidator.validate(schema);

function composePath(intermediate) {
return path.join(outputDirectory, intermediate, libraryName);
}

const componentIOSOutput = composePath('react/renderer/components/');
const modulesIOSOutput = composePath('./');

const outputFoldersForGenerators = {
componentsIOS: componentsOutputDir ?? outputDirectory, // fallback for backward compatibility
modulesIOS: modulesOutputDir ?? outputDirectory, // fallback for backward compatibility
componentsIOS: componentIOSOutput,
modulesIOS: modulesIOSOutput,
descriptors: outputDirectory,
events: outputDirectory,
props: outputDirectory,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,17 @@ const rnCodegen = require('../RNCodegen.js');
const fixture = require('../__test_fixtures__/fixtures.js');
const path = require('path');

const invalidDirectory = 'invalid/';
const outputDirectory = 'tmp/out/';
const packageName = 'na';
const componentsOutputDir = 'react/renderer/components/library';
const modulesOutputDir = 'library';

describe('RNCodegen.generate', () => {
it('when type `all`', () => {
beforeEach(() => {
jest.resetModules();
});
it('when type `all`, with default paths', () => {
const componentsOutputDir = 'react/renderer/components/library';
const modulesOutputDir = 'library';

const expectedPaths = {
'library.h': modulesOutputDir,
'library-generated.mm': modulesOutputDir,
Expand All @@ -43,7 +47,10 @@ describe('RNCodegen.generate', () => {
let receivedDir = path.dirname(location);
let receivedBasename = path.basename(location);

let expectedPath = expectedPaths[receivedBasename];
let expectedPath = path.join(
outputDirectory,
expectedPaths[receivedBasename],
);
expect(receivedDir).toEqual(expectedPath);
},
}));
Expand All @@ -52,11 +59,9 @@ describe('RNCodegen.generate', () => {
{
libraryName: 'library',
schema: fixture.all,
outputDirectory: invalidDirectory,
outputDirectory: outputDirectory,
packageName: packageName,
assumeNonnull: true,
componentsOutputDir: componentsOutputDir,
modulesOutputDir: modulesOutputDir,
},
{
generators: ['componentsIOS', 'modulesIOS'],
Expand Down
42 changes: 7 additions & 35 deletions scripts/codegen/__tests__/generate-artifacts-executor-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,38 +24,19 @@ describe('generateCode', () => {
const rnRoot = path.join(__dirname, '../..');
const libraryType = 'all';

const tmpComponentOutDirs = path.join(tmpDir, 'out', 'components');
const tmpNativeModulesOutDir = path.join(tmpDir, 'out', 'nativeModules');
const iOSComponentOutDirs = path.join(
iosOutputDir,
'react/renderer/components',
library.config.name,
);
const iOSNativeModulesOutDir = path.join(
iosOutputDir,
'./',
library.config.name,
);
const tmpOutDir = path.join(tmpDir, 'out');

// mock used functions
let mkdirSyncInvocationCount = 0;
jest.mock('fs', () => ({
readdirSync: dirpath => {
return ['test/dir']; //we only require to return something, so that the folder is not empty.
},
mkdirSync: (location, config) => {
if (mkdirSyncInvocationCount === 0) {
expect(location).toEqual(tmpComponentOutDirs);
expect(location).toEqual(tmpOutDir);
}
if (mkdirSyncInvocationCount === 1) {
expect(location).toEqual(tmpNativeModulesOutDir);
}
if (mkdirSyncInvocationCount === 2) {
expect(location).toEqual(iOSComponentOutDirs);
}
if (mkdirSyncInvocationCount === 3) {
expect(location).toEqual(iOSNativeModulesOutDir);
expect(location).toEqual(iosOutputDir);
}

mkdirSyncInvocationCount += 1;
},
}));
Expand All @@ -70,30 +51,21 @@ describe('generateCode', () => {
)} \
--platform ios \
--schemaPath ${pathToSchema} \
--outputDir ${tmpNativeModulesOutDir} \
--componentsOutputDir ${tmpComponentOutDirs} \
--modulesOutputDirs ${tmpNativeModulesOutDir} \
--outputDir ${tmpOutDir} \
--libraryName ${library.config.name} \
--libraryType ${libraryType}`;
expect(command).toEqual(expectedCommand);
}

if (execSyncInvocationCount === 1) {
expect(command).toEqual(
`cp -R ${tmpComponentOutDirs}/* ${iOSComponentOutDirs}`,
);
}
if (execSyncInvocationCount === 2) {
expect(command).toEqual(
`cp -R ${tmpNativeModulesOutDir}/* ${iOSNativeModulesOutDir}`,
);
expect(command).toEqual(`cp -R ${tmpOutDir}/* ${iosOutputDir}`);
}

execSyncInvocationCount += 1;
},
}));

underTest._generateCode(iosOutputDir, library, tmpDir, node, pathToSchema);
expect(mkdirSyncInvocationCount).toBe(4);
expect(mkdirSyncInvocationCount).toBe(2);
});
});
22 changes: 11 additions & 11 deletions scripts/codegen/__tests__/generate-specs-cli-executor-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,20 @@

const sut = require('../generate-specs-cli-executor');
const fixtures = require('../__test_fixtures__/fixtures');
const path = require('path');

describe('generateSpec', () => {
it('invokes RNCodegen with the right params', () => {
const platform = 'ios';
const libraryType = 'all';
const schemaPath = './';
const componentsOutputDir =
'app/ios/build/generated/ios/react/renderer/components/library';
const modulesOutputDir = 'app/ios/build/generated/ios/./library';
const outputDirectory = 'app/ios/build/generated/ios';
const componentsOutputDir = path.normalize(
'app/ios/build/generated/ios/react/renderer/components/library',
);
const modulesOutputDir = path.normalize(
'app/ios/build/generated/ios/library',
);
const outputDirectory = path.normalize('app/ios/build/generated/ios');
const libraryName = 'library';
const packageName = 'com.library';
const generators = ['componentsIOS', 'modulesIOS'];
Expand All @@ -38,15 +42,15 @@ describe('generateSpec', () => {
jest.mock('mkdirp', () => ({
sync: folder => {
if (mkdirpSyncInvoked === 0) {
expect(folder).toBe(componentsOutputDir);
expect(folder).toBe(outputDirectory);
}

if (mkdirpSyncInvoked === 1) {
expect(folder).toBe(modulesOutputDir);
expect(folder).toBe(componentsOutputDir);
}

if (mkdirpSyncInvoked === 2) {
expect(folder).toBe(outputDirectory);
expect(folder).toBe(modulesOutputDir);
}

mkdirpSyncInvoked += 1;
Expand All @@ -65,8 +69,6 @@ describe('generateSpec', () => {
expect(libraryConfig.schema).toStrictEqual(fixtures.schema);
expect(libraryConfig.outputDirectory).toBe(outputDirectory);
expect(libraryConfig.packageName).toBe(packageName);
expect(libraryConfig.componentsOutputDir).toBe(componentsOutputDir);
expect(libraryConfig.modulesOutputDir).toBe(modulesOutputDir);

expect(generatorConfigs.generators).toStrictEqual(generators);
expect(generatorConfigs.test).toBeUndefined();
Expand All @@ -81,8 +83,6 @@ describe('generateSpec', () => {
libraryName,
packageName,
libraryType,
componentsOutputDir,
modulesOutputDir,
);

expect(mkdirpSyncInvoked).toBe(3);
Expand Down
45 changes: 6 additions & 39 deletions scripts/codegen/generate-artifacts-executor.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,6 @@ function executeNodeScript(node, script) {
execSync(`${node} ${script}`);
}

function isDirEmpty(dirPath) {
return fs.readdirSync(dirPath).length === 0;
}

function isAppRootValid(appRootDir) {
if (appRootDir == null) {
console.error('Missing path to React Native application');
Expand Down Expand Up @@ -212,57 +208,28 @@ function generateSchema(tmpDir, library, node, codegenCliPath) {
}

function generateCode(iosOutputDir, library, tmpDir, node, pathToSchema) {
function composePath(intermediate) {
return path.join(iosOutputDir, intermediate, library.config.name);
}

const outputDirsIOS = {
components: composePath('react/renderer/components'),
nativeModules: composePath('./'),
};

const tempOutputDirs = {
components: path.join(tmpDir, 'out', 'components'),
nativeModules: path.join(tmpDir, 'out', 'nativeModules'),
};

// ...then generate native code artifacts.
const libraryTypeArg = library.config.type
? `--libraryType ${library.config.type}`
: '';

Object.entries(tempOutputDirs).forEach(([type, dirPath]) => {
fs.mkdirSync(dirPath, {recursive: true});
});

const deprecated_outputDir =
library.config.type === 'components'
? tempOutputDirs.components
: tempOutputDirs.nativeModules;
const tmpOutputDir = path.join(tmpDir, 'out');
fs.mkdirSync(tmpOutputDir, {recursive: true});

executeNodeScript(
node,
`${path.join(RN_ROOT, 'scripts', 'generate-specs-cli.js')} \
--platform ios \
--schemaPath ${pathToSchema} \
--outputDir ${deprecated_outputDir} \
--componentsOutputDir ${tempOutputDirs.components} \
--modulesOutputDirs ${tempOutputDirs.nativeModules} \
--outputDir ${tmpOutputDir} \
--libraryName ${library.config.name} \
${libraryTypeArg}`,
);

// Finally, copy artifacts to the final output directory.
Object.entries(outputDirsIOS).forEach(([type, dirPath]) => {
const outDir = tempOutputDirs[type];
if (isDirEmpty(outDir)) {
return; // cp fails if we try to copy something empty.
}

fs.mkdirSync(dirPath, {recursive: true});
execSync(`cp -R ${outDir}/* ${dirPath}`);
console.log(`[Codegen] Generated artifacts: ${dirPath}`);
});
fs.mkdirSync(iosOutputDir, {recursive: true});
execSync(`cp -R ${tmpOutputDir}/* ${iosOutputDir}`);
console.log(`[Codegen] Generated artifacts: ${iosOutputDir}`);
}

function generateNativeCodegenFiles(
Expand Down
22 changes: 11 additions & 11 deletions scripts/codegen/generate-specs-cli-executor.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,7 @@ const GENERATORS = {
},
};

function deprecated_createOutputDirectoryIfNeeded(
outputDirectory,
libraryName,
) {
function createOutputDirectoryIfNeeded(outputDirectory, libraryName) {
if (!outputDirectory) {
outputDirectory = path.resolve(__dirname, '..', 'Libraries', libraryName);
}
Expand Down Expand Up @@ -81,25 +78,28 @@ function generateSpec(
libraryName,
packageName,
libraryType,
componentsOutputDir,
modulesOutputDir,
) {
validateLibraryType(libraryType);

let schema = readAndParseSchema(schemaPath);

createFolderIfDefined(componentsOutputDir);
createFolderIfDefined(modulesOutputDir);
deprecated_createOutputDirectoryIfNeeded(outputDirectory, libraryName);
createOutputDirectoryIfNeeded(outputDirectory, libraryName);
function composePath(intermediate) {
return path.join(outputDirectory, intermediate, libraryName);
}

// These are hardcoded and should not be changed.
// The codegen creates some C++ code with #include directive
// which uses these paths. Those directive are not customizable yet.
createFolderIfDefined(composePath('react/renderer/components/'));
createFolderIfDefined(composePath('./'));

RNCodegen.generate(
{
libraryName,
schema,
outputDirectory,
packageName,
componentsOutputDir,
modulesOutputDir,
},
{
generators: GENERATORS[libraryType][platform],
Expand Down
12 changes: 1 addition & 11 deletions scripts/generate-specs-cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const argv = yargs
.option('o', {
alias: 'outputDir',
describe:
'DEPRECATED - Path to directory where native code source files should be saved.',
'Path to the root directory where native code source files should be saved.',
})
.option('n', {
alias: 'libraryName',
Expand All @@ -41,14 +41,6 @@ const argv = yargs
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'],
Expand All @@ -63,8 +55,6 @@ function main() {
argv.libraryName,
argv.javaPackageName,
argv.libraryType,
argv.componentsOutputDir,
argv.modulesOutputDirs,
);
}

Expand Down

0 comments on commit c732728

Please sign in to comment.