Skip to content

Commit

Permalink
Introduce "headerPrefix" codegen option (#41956)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: #41956

By default, generated Cxx sources for components all end up in same directory. However the include declarations in them look like this:
```
#include <react/renderer/components/${libraryName}/ShadowNodes.h>
```
And not like this:
```
#include "ShadowNodes.h"
```
This works fine with Buck because it supports header prefixes.
To get this working with CocoaPods we define additional `HEADER_SEARCH_PATHS` for our `React-Codegen` pod.
This approach will not work if we want to generate code at the library level and check in the artifacts. That's because we don't have control over the Podspec there, and can't inject those additional `HEADER_SEARCH_PATHS`.

This diff adds the `headerPrefix` argument to the codegen entry point. It is `react/renderer/components/${libraryName}` by default, but can become empty if we want to generate code at the library level, and don't want to deal with this nested header structure.

*Note:* `RNCodegen` runs all the generators [in a loop](https://github.com/facebook/react-native/blob/main/packages/react-native-codegen/src/generators/RNCodegen.js#L263-L275), assuming that the all have same function signature So I had to add the `headerPrefix` argument to all the generators, even to the ones that don't really need it.

Changelog: [General][Added] - Introduce "headerPrefix" codegen option.

Reviewed By: zeyap

Differential Revision: D51811596

fbshipit-source-id: c5c3e1e571c7c4ea2f5354eb9a7b0df6b917fc0c
  • Loading branch information
dmytrorykun authored and facebook-github-bot committed Dec 20, 2023
1 parent b00569c commit dae4a11
Show file tree
Hide file tree
Showing 35 changed files with 165 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,13 @@ fixtures.forEach(fixture => {
it(`GenerateComponentDescriptorH can generate for '${fixture}'`, () => {
const libName = 'RNCodegenModuleFixtures';
const schema = parser.parseFile(`${FIXTURE_DIR}/${fixture}`);
const output = generator.generate(libName, schema);
const output = generator.generate(
libName,
schema,
undefined,
false,
`react/renderer/components/${libName}/`,
);
expect(Object.fromEntries(output)).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,13 @@ fixtures.forEach(fixture => {
it(`GenerateEventEmitterCpp can generate for '${fixture}'`, () => {
const libName = 'RNCodegenModuleFixtures';
const schema = parser.parseFile(`${FIXTURE_DIR}/${fixture}`);
const output = generator.generate(libName, schema);
const output = generator.generate(
libName,
schema,
undefined,
false,
`react/renderer/components/${libName}/`,
);
expect(Object.fromEntries(output)).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,13 @@ fixtures.forEach(fixture => {
it(`GeneratePropsCpp can generate for '${fixture}'`, () => {
const libName = 'RNCodegenModuleFixtures';
const schema = parser.parseFile(`${FIXTURE_DIR}/${fixture}`);
const output = generator.generate(libName, schema);
const output = generator.generate(
libName,
schema,
'',
false,
`react/renderer/components/${libName}/`,
);
expect(Object.fromEntries(output)).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ fixtures.forEach(fixture => {
it(`GenerateShadowNodeCpp can generate for '${fixture}'`, () => {
const libName = 'RNCodegenModuleFixtures';
const schema = parser.parseFile(`${FIXTURE_DIR}/${fixture}`);
const output = generator.generate(libName, schema, undefined, false);
const output = generator.generate(
libName,
schema,
'',
false,
`react/renderer/components/${libName}/`,
);
expect(Object.fromEntries(output)).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ fixtures.forEach(fixture => {
it(`GenerateShadowNodeH can generate for '${fixture}'`, () => {
const libName = 'RNCodegenModuleFixtures';
const schema = parser.parseFile(`${FIXTURE_DIR}/${fixture}`);
const output = generator.generate(libName, schema, undefined, false);
const output = generator.generate(
libName,
schema,
'',
false,
`react/renderer/components/${libName}/`,
);
expect(Object.fromEntries(output)).toMatchSnapshot();
});
});
33 changes: 23 additions & 10 deletions packages/react-native-codegen/src/generators/RNCodegen.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ type LibraryOptions = $ReadOnly<{
outputDirectory: string,
packageName?: string, // Some platforms have a notion of package, which should be configurable.
assumeNonnull: boolean,
useLocalIncludePaths?: boolean,
}>;

type SchemasOptions = $ReadOnly<{
Expand Down Expand Up @@ -232,16 +233,24 @@ module.exports = {
outputDirectory,
packageName,
assumeNonnull,
useLocalIncludePaths,
}: LibraryOptions,
{generators, test}: LibraryConfig,
): boolean {
schemaValidator.validate(schema);

const defaultHeaderPrefix = 'react/renderer/components';
const headerPrefix =
useLocalIncludePaths === true
? ''
: `${defaultHeaderPrefix}/${libraryName}/`;
function composePath(intermediate: string) {
return path.join(outputDirectory, intermediate, libraryName);
}

const componentIOSOutput = composePath('react/renderer/components/');
const componentIOSOutput = composePath(
useLocalIncludePaths === true ? '' : defaultHeaderPrefix,
);
const modulesIOSOutput = composePath('./');

const outputFoldersForGenerators = {
Expand All @@ -262,15 +271,19 @@ module.exports = {

for (const name of generators) {
for (const generator of LIBRARY_GENERATORS[name]) {
generator(libraryName, schema, packageName, assumeNonnull).forEach(
(contents: string, fileName: string) => {
generatedFiles.push({
name: fileName,
content: contents,
outputDir: outputFoldersForGenerators[name],
});
},
);
generator(
libraryName,
schema,
packageName,
assumeNonnull,
headerPrefix,
).forEach((contents: string, fileName: string) => {
generatedFiles.push({
name: fileName,
content: contents,
outputDir: outputFoldersForGenerators[name],
});
});
}
}
return checkOrWriteFiles(generatedFiles, test);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ type FilesOutput = Map<string, string>;

const FileTemplate = ({
componentDescriptors,
libraryName,
headerPrefix,
}: {
componentDescriptors: string,
libraryName: string,
headerPrefix: string,
}) => `
/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
Expand All @@ -33,7 +33,7 @@ const FileTemplate = ({
#pragma once
#include <react/renderer/components/${libraryName}/ShadowNodes.h>
#include <${headerPrefix}ShadowNodes.h>
#include <react/renderer/core/ConcreteComponentDescriptor.h>
namespace facebook::react {
Expand All @@ -54,6 +54,7 @@ module.exports = {
schema: SchemaType,
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
): FilesOutput {
const fileName = 'ComponentDescriptors.h';

Expand Down Expand Up @@ -85,7 +86,7 @@ module.exports = {

const replacedTemplate = FileTemplate({
componentDescriptors,
libraryName,
headerPrefix: headerPrefix ?? '',
});

return new Map([[fileName, replacedTemplate]]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,7 @@ module.exports = {
schema: SchemaType,
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
): FilesOutput {
const fileName = 'RCTComponentViewHelpers.h';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ type ComponentCollection = $ReadOnly<{

const FileTemplate = ({
events,
libraryName,
extraIncludes,
headerPrefix,
}: {
events: string,
libraryName: string,
extraIncludes: Set<string>,
headerPrefix: string,
}) => `
/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
Expand All @@ -47,7 +47,7 @@ const FileTemplate = ({
* ${'@'}generated by codegen project: GenerateEventEmitterCpp.js
*/
#include <react/renderer/components/${libraryName}/EventEmitters.h>
#include <${headerPrefix}EventEmitters.h>
${[...extraIncludes].join('\n')}
namespace facebook::react {
Expand Down Expand Up @@ -411,6 +411,7 @@ module.exports = {
schema: SchemaType,
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
): FilesOutput {
const moduleComponents: ComponentCollection = Object.keys(schema.modules)
.map(moduleName => {
Expand Down Expand Up @@ -442,9 +443,9 @@ module.exports = {

const fileName = 'EventEmitters.cpp';
const replacedTemplate = FileTemplate({
libraryName,
events: componentEmitters,
extraIncludes,
headerPrefix: headerPrefix ?? '',
});

return new Map([[fileName, replacedTemplate]]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ module.exports = {
schema: SchemaType,
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
): FilesOutput {
const moduleComponents: ComponentCollection = Object.keys(schema.modules)
.map(moduleName => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ const {convertDefaultTypeToString, getImports} = require('./CppHelpers');
type FilesOutput = Map<string, string>;

const FileTemplate = ({
libraryName,
imports,
componentClasses,
headerPrefix,
}: {
libraryName: string,
imports: string,
componentClasses: string,
headerPrefix: string,
}) => `
/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
Expand All @@ -35,7 +35,7 @@ const FileTemplate = ({
* ${'@'}generated by codegen project: GeneratePropsCpp.js
*/
#include <react/renderer/components/${libraryName}/Props.h>
#include <${headerPrefix}Props.h>
${imports}
namespace facebook::react {
Expand Down Expand Up @@ -104,6 +104,7 @@ module.exports = {
schema: SchemaType,
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
): FilesOutput {
const fileName = 'Props.cpp';
const allImports: Set<string> = new Set([
Expand Down Expand Up @@ -151,8 +152,8 @@ module.exports = {

const replacedTemplate = FileTemplate({
componentClasses: componentProps,
libraryName,
imports: Array.from(allImports).sort().join('\n').trim(),
headerPrefix: headerPrefix ?? '',
});

return new Map([[fileName, replacedTemplate]]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,7 @@ module.exports = {
schema: SchemaType,
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
): FilesOutput {
const fileName = 'Props.h';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ module.exports = {
schema: SchemaType,
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
): FilesOutput {
// TODO: This doesn't support custom package name yet.
const normalizedPackageName = 'com.facebook.react.viewmanagers';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ module.exports = {
schema: SchemaType,
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
): FilesOutput {
// TODO: This doesn't support custom package name yet.
const normalizedPackageName = 'com.facebook.react.viewmanagers';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ import type {SchemaType} from '../../CodegenSchema';
type FilesOutput = Map<string, string>;

const FileTemplate = ({
libraryName,
componentNames,
headerPrefix,
}: {
libraryName: string,
componentNames: string,
headerPrefix: string,
}) => `
/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
Expand All @@ -31,7 +31,7 @@ const FileTemplate = ({
* ${'@'}generated by codegen project: GenerateShadowNodeCpp.js
*/
#include <react/renderer/components/${libraryName}/ShadowNodes.h>
#include <${headerPrefix}ShadowNodes.h>
namespace facebook::react {
Expand All @@ -51,6 +51,7 @@ module.exports = {
schema: SchemaType,
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
): FilesOutput {
const fileName = 'ShadowNodes.cpp';

Expand Down Expand Up @@ -85,7 +86,7 @@ module.exports = {

const replacedTemplate = FileTemplate({
componentNames,
libraryName,
headerPrefix: headerPrefix ?? '',
});

return new Map([[fileName, replacedTemplate]]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,11 @@ import type {SchemaType} from '../../CodegenSchema';
type FilesOutput = Map<string, string>;

const FileTemplate = ({
imports,
libraryName,
componentClasses,
headerPrefix,
}: {
imports: string,
libraryName: string,
componentClasses: string,
headerPrefix: string,
}) => `
/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
Expand All @@ -35,8 +33,9 @@ const FileTemplate = ({
#pragma once
${imports}#include <react/renderer/components/${libraryName}/Props.h>
#include <react/renderer/components/${libraryName}/States.h>
#include <${headerPrefix}EventEmitters.h>
#include <${headerPrefix}Props.h>
#include <${headerPrefix}States.h>
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
#include <jsi/jsi.h>
Expand Down Expand Up @@ -72,6 +71,7 @@ module.exports = {
schema: SchemaType,
packageName?: string,
assumeNonnull: boolean = false,
headerPrefix?: string,
): FilesOutput {
const fileName = 'ShadowNodes.h';

Expand Down Expand Up @@ -109,12 +109,9 @@ module.exports = {
.filter(Boolean)
.join('\n\n');

const eventEmitterImport = `#include <react/renderer/components/${libraryName}/EventEmitters.h>\n`;

const replacedTemplate = FileTemplate({
componentClasses: moduleResults,
libraryName,
imports: eventEmitterImport,
headerPrefix: headerPrefix ?? '',
});

return new Map([[fileName, replacedTemplate]]);
Expand Down
Loading

0 comments on commit dae4a11

Please sign in to comment.