Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add separateDataFiles to @rnw/cli and @rnw/codegen #11990

Merged
merged 13 commits into from
Aug 14, 2023
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "Add `separateDataFiles` to @rnw/cli and @rnw/codegen",
"packageName": "@react-native-windows/cli",
"email": "53799235+ZihanChen-MSFT@users.noreply.github.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "Add `separateDataFiles` to @rnw/cli and @rnw/codegen",
"packageName": "@react-native-windows/codegen",
"email": "53799235+ZihanChen-MSFT@users.noreply.github.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "Add `separateDataFiles` to @rnw/cli and @rnw/codegen",
"packageName": "react-native-windows",
"email": "53799235+ZihanChen-MSFT@users.noreply.github.com",
"dependentChangeType": "patch"
}
20 changes: 19 additions & 1 deletion packages/@react-native-windows/cli/src/codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,24 @@ export class CodeGenWindows {
'InvalidCodegenConfig',
`Value of ${chalk.bold(
'codegenConfig.windows.cppStringType',
)} package.json should be either 'std::string' or 'std::wstring'`,
)} in package.json should be either 'std::string' or 'std::wstring'`,
);
}
}

let separateDataTypes = true;
if (pkgJson.codegenConfig.windows.separateDataTypes !== undefined) {
switch (pkgJson.codegenConfig.windows.separateDataTypes) {
case true:
case false:
separateDataTypes = pkgJson.codegenConfig.windows.separateDataTypes;
break;
default:
throw new CodedError(
'InvalidCodegenConfig',
`Value of ${chalk.bold(
'codegenConfig.windows.separateDataTypes',
)} in package.json should be either true or false`,
);
}
}
Expand Down Expand Up @@ -138,6 +155,7 @@ export class CodeGenWindows {
}**/*Native*.[jt]s`,
],
cppStringType,
separateDataTypes,
libraryName: projectName,
methodOnly: false,
modulesCxx: generators.indexOf('modulesCxx') !== -1,
Expand Down
5 changes: 5 additions & 0 deletions packages/@react-native-windows/codegen/src/Cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ const argv = yargs.options({
'C++ string type in generated code, should be "std::string" or "std::wstring"',
default: 'std::string',
},
separateDataTypes: {
type: 'boolean',
describe: 'generate data types in a separate file',
default: false,
},
}).argv;

if ((argv.file && argv.files) || (!argv.file && !argv.files)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,16 @@ export type {CppStringTypes} from './ObjectTypes';

type FilesOutput = Map<string, string>;

const moduleTemplate = `
/*
const headerTemplate = `/*
* This file is auto-generated from a NativeModule spec file in js.
*
* This is a C++ Spec class that should be used with MakeTurboModuleProvider to register native modules
* in a way that also verifies at compile time that the native module matches the interface required
* by the TurboModule JS spec.
*/
#pragma once
#pragma once`;

#include <NativeModules.h>
#include <tuple>

namespace ::_NAMESPACE_:: {
::_MODULE_CUSTPM_TYPES_::
::_MODULE_CUSTPM_TYPES_REFLECTION_::
const specTemplate = `::_MODULE_CUSTPM_TYPES_REFLECTION_::
struct ::_MODULE_NAME_::Spec : winrt::Microsoft::ReactNative::TurboModuleSpec {
::_MODULE_MEMBERS_TUPLES_::

Expand All @@ -41,7 +35,44 @@ struct ::_MODULE_NAME_::Spec : winrt::Microsoft::ReactNative::TurboModuleSpec {
::_MODULE_MEMBERS_CHECKS_::

::_MODULE_MEMBERS_ERRORS_::
}
}`;

const typeOnlyTemplate = `
${headerTemplate}

#include <string>
#include <optional>
#include <functional>
#include <vector>

namespace ::_NAMESPACE_:: {
::_MODULE_CUSTPM_TYPES_::
} // namespace ::_NAMESPACE_::
`;

const moduleOnlyTemplate = `
${headerTemplate}

::_TYPE_DEFINITION_INCLUDE_::
#include <NativeModules.h>
#include <tuple>

namespace ::_NAMESPACE_:: {
${specTemplate}
};

} // namespace ::_NAMESPACE_::
`;

const allInOneTemplate = `
${headerTemplate}

#include <NativeModules.h>
#include <tuple>

namespace ::_NAMESPACE_:: {
::_MODULE_CUSTPM_TYPES_::
${specTemplate}
};

} // namespace ::_NAMESPACE_::
Expand All @@ -51,10 +82,12 @@ export function createNM2Generator({
methodOnly,
namespace,
cppStringType,
separateDataTypes,
}: {
methodOnly: boolean;
namespace: string;
cppStringType: CppStringTypes;
separateDataTypes: boolean;
}) {
return (
_libraryName: string,
Expand Down Expand Up @@ -110,17 +143,42 @@ ${errors}`;
cppStringType,
});

files.set(
`Native${preferredModuleName}Spec.g.h`,
moduleTemplate
const customTypesExist = customTypes !== '';

const replaceContent = function (template: string): string {
return template
.replace(/::_MODULE_CUSTPM_TYPES_::/g, customTypes)
.replace(/::_MODULE_CUSTPM_TYPES_REFLECTION_::/g, customReflection)
.replace(/::_MODULE_MEMBERS_TUPLES_::/g, tuples.substring(1))
.replace(/::_MODULE_MEMBERS_CHECKS_::/g, checks.substring(1))
.replace(/::_MODULE_MEMBERS_ERRORS_::/g, errors)
.replace(/::_MODULE_NAME_::/g, preferredModuleName)
.replace(/::_NAMESPACE_::/g, namespace),
);
.replace(
/::_TYPE_DEFINITION_INCLUDE_::/g,
customTypesExist
? `// #include "Native${preferredModuleName}DataTypes.g.h" before this file to use the generated type definition`
: '',
)
.replace(/::_NAMESPACE_::/g, namespace);
};

if (separateDataTypes) {
if (customTypesExist) {
files.set(
`Native${preferredModuleName}DataTypes.g.h`,
replaceContent(typeOnlyTemplate),
);
}
files.set(
`Native${preferredModuleName}Spec.g.h`,
replaceContent(moduleOnlyTemplate),
);
} else {
files.set(
`Native${preferredModuleName}Spec.g.h`,
replaceContent(allInOneTemplate),
);
}
}
}

Expand Down
5 changes: 5 additions & 0 deletions packages/@react-native-windows/codegen/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export interface SharedOptions {
namespace: string;
outputDirectory: string;
cppStringType: CppStringTypes;
separateDataTypes: boolean;
}

interface Options extends SharedOptions {
Expand Down Expand Up @@ -216,6 +217,7 @@ export function generate(
namespace,
outputDirectory,
cppStringType,
separateDataTypes,
moduleSpecName,
schema,
}: Options,
Expand All @@ -240,6 +242,7 @@ export function generate(
methodOnly,
namespace,
cppStringType,
separateDataTypes,
});

const generateJsiModuleH = require(path.resolve(
Expand Down Expand Up @@ -369,6 +372,7 @@ export function runCodeGen(options: CodeGenOptions): boolean {
namespace,
outputDirectory,
cppStringType,
separateDataTypes,
} = options;
return generate(
{
Expand All @@ -380,6 +384,7 @@ export function runCodeGen(options: CodeGenOptions): boolean {
namespace,
outputDirectory,
cppStringType,
separateDataTypes,
moduleSpecName,
schema,
},
Expand Down
24 changes: 24 additions & 0 deletions packages/sample-apps/codegen/NativeMyModuleDataTypes.g.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@

/*
* This file is auto-generated from a NativeModule spec file in js.
*
* This is a C++ Spec class that should be used with MakeTurboModuleProvider to register native modules
* in a way that also verifies at compile time that the native module matches the interface required
* by the TurboModule JS spec.
*/
#pragma once

#include <string>
#include <optional>
#include <functional>
#include <vector>

namespace SampleLibraryCodegen {

struct MyModuleSpec_Constants {
bool const1;
double const2;
std::string const3;
};

} // namespace SampleLibraryCodegen
8 changes: 1 addition & 7 deletions packages/sample-apps/codegen/NativeMyModuleSpec.g.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,12 @@
*/
#pragma once

// #include "NativeMyModuleDataTypes.g.h" before this file to use the generated type definition
#include <NativeModules.h>
#include <tuple>

namespace SampleLibraryCodegen {

struct MyModuleSpec_Constants {
bool const1;
double const2;
std::string const3;
};


inline winrt::Microsoft::ReactNative::FieldMap GetStructInfo(MyModuleSpec_Constants*) noexcept {
winrt::Microsoft::ReactNative::FieldMap fieldMap {
{L"const1", &MyModuleSpec_Constants::const1},
Expand Down
4 changes: 3 additions & 1 deletion packages/sample-apps/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"@babel/eslint-parser": "^7.20.0",
"@babel/runtime": "^7.8.4",
"@react-native-windows/codegen": "0.0.0-canary.67",
"@react-native-windows/cli": "0.0.0-canary.183",
"@rnw-scripts/babel-react-native-config": "0.0.0",
"@rnw-scripts/eslint-config": "1.2.2",
"@rnw-scripts/just-task": "2.3.15",
Expand All @@ -39,7 +40,8 @@
"type": "modules",
"jsSrcsDir": "src",
"windows": {
"namespace": "SampleLibraryCodegen"
"namespace": "SampleLibraryCodegen",
"separateDataFiles": true
}
},
"engines": {
Expand Down
4 changes: 4 additions & 0 deletions packages/sample-apps/windows/SampleLibraryCPP/MyModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@

#pragma once

// a demo of setting codegenConfig.windows.separateDataTypes to true in package.json
// it generates data types in a separate file, but one doesn't include another
// including them in a expected order is required
#include "..\..\codegen\NativeMyModuleDataTypes.g.h"
#include "..\..\codegen\NativeMyModuleSpec.g.h"
#include "DebugHelpers.h"

Expand Down