Skip to content

Commit cdf07d4

Browse files
authored
[NA] Move Codegen Docs back (facebook#4251)
1 parent e02692a commit cdf07d4

File tree

4 files changed

+283
-0
lines changed

4 files changed

+283
-0
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# The Codegen CLI
2+
3+
Calling Gradle or manually calling a script might be hard to remember and it requires a lot of cerimony.
4+
5+
To simplify it, we created a CLI tool that can help you running those tasks: the **Codegen** cli.
6+
7+
```shell
8+
npx react-native codegen [--path path] [--platform string] [--outputPath path]
9+
```
10+
11+
This command runs [react-native-codegen](https://www.npmjs.com/package/react-native-codegen) for your project. The following options are available:
12+
13+
- `--path` - Path to `package.json`. The default path is the current working directory.
14+
- `--platform` - Target platform. Supported values: `android`, `ios`, `all`. The default value is `all`.
15+
- `--outputPath` - Output path. The default value is the value defined in `codegenConfig.outputDir`.
16+
17+
## Examples
18+
19+
- Read `package.json` from the current working directory, generate code based on its codegenConfig.
20+
21+
```shell
22+
npx react-native codegen
23+
```
24+
25+
- Read `package.json` from the current working directory, generate iOS code in the location defined in the codegenConfig.
26+
27+
```shell
28+
npx react-native codegen --platform ios
29+
```
30+
31+
- Read `package.json` from `third-party/some-library`, generate Android code in `third-party/some-library/android/generated`.
32+
33+
```shell
34+
npx react-native codegen \
35+
--path third-party/some-library \
36+
--platform android \
37+
--outputPath third-party/some-library/android/generated
38+
```
39+
40+
## Including Generated Code into Libraries
41+
42+
The **Codegen** CLI is a great tool for library developers. It can be used to peek at the generated code to see which interfaces you need to implement. Or you can generate the code if you want to ship it in your library.
43+
44+
This setup has several benefits:
45+
46+
- No need to rely on the app to run **Codegen** for you, the generated code is always there.
47+
- The implementation files are always consistent with the generated interfaces.
48+
- No need to include two sets of files to support both architectures on Android. You can only keep the New Architecture one, and it is guaranteed to be backwards compatible.
49+
- No need to worry about **Codegen** version mismatch between what is used by the app, and what was used during library development.
50+
- Since all native code is there, it is possible to ship the native part of the library as a prebuild.
51+
52+
To enable this setup:
53+
54+
- Add the `includesGeneratedCode` property into your library's `codegenConfig` field in the `package.json` file. Set its value to `true`.
55+
- Run **Codegen** locally with the codegen CLI.
56+
- Update your `package.json` to include the generated code.
57+
- Update your `podspec` to include the generated code.
58+
- Update your `build.Gradle` file to include the generated code.
59+
- Update `cmakeListsPath` in `react-native.config.js` so that Gradle doesn't look for CMakeLists file in the build directory but instead in your outputDir.
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
# Using Codegen
2+
3+
This guide teaches how to:
4+
5+
- Configure **Codegen**.
6+
- Invoke it manually for each platform.
7+
8+
It also describes the generated code.
9+
10+
## Prerequisites
11+
12+
You always need a React Native app to generate the code properly, even when invoking the **Codegen** manually.
13+
14+
The **Codegen** process is tightly coupled with the build of the app, and the scripts are located in the `react-native` NPM package.
15+
16+
For the sake of this guide, create a project using the React Native CLI as follows:
17+
18+
```bash
19+
npx @react-native-community/cli@latest init SampleApp --version 0.76.0
20+
```
21+
22+
**Codegen** is used to generate the glue-code for your custom modules or components. See the guides for Turbo Native Modules and Fabric Native Components for more details on how to create them.
23+
24+
<!-- TODO: add links -->
25+
26+
## Configuring **Codegen**
27+
28+
**Codegen** can be configured in your app by modifying the `package.json` file. **Codegen** is controlled by a custom field called `codegenConfig`.
29+
30+
```json title="package.json"
31+
"codegenConfig": {
32+
"name": "<SpecName>",
33+
"type": "<types>",
34+
"jsSrcsDir": "<source_dir>",
35+
"android": {
36+
"javaPackageName": "<java.package.name>"
37+
}
38+
},
39+
```
40+
41+
You can add this snippet to your app and customise the various fields:
42+
43+
- `name:` This is the name that will be used to create files containig your specs. As a convention, It should have the suffix `Spec`, but this is not mandatory.
44+
- `type`: the type of code we need to generate. Allowed values are `modules`, `components`, `all`.
45+
- `modules:` use this value if you only need to generate code for Turbo Native Modules.
46+
- `components:` use this value if you only need to generate code for Native Fabric Components.
47+
- `all`: use this value if you have a mixture of components and modules.
48+
- `jsSrcsDir`: this is the root folder where all your specs live.
49+
- `android.javaPackageName`: this is an android specific setting to let **Codegen** generate the files in a custom package.
50+
51+
When **Codegen** runs, it searches among all the dependencies of the app, looking for JS files that respects some specific conventions, and it generates the required code:
52+
53+
- Turbo Native Modules requires that the spec files are prefixed with `Native`. For example, `NativeLocalStorage.ts` is a valid name for a spec file.
54+
- Native Fabric Components requires that the spec files are suffixed with `NativeComponent`. For example, `WebViewNativeComponent.tx` is a valid name for a spec file.
55+
56+
## Running **Codegen**
57+
58+
The rest of this guide assumes that you have a Native Turbo Module, a Native Fabric Component or both already set up in your project. We also assume that you have valid specification files in the `jsSrcsDir` specified in the `package.json`.
59+
60+
### Android
61+
62+
**Codegen** for Android is integrated with the React Native Gradle Plugin (RNGP). The RNGP contains a task that can be invoked that reads the configurations defined in the `package.json` file and execute **Codegen**. To run the gradle task, first navigate inside the `android `folder of your project. Then run:
63+
64+
```bash
65+
./gradlew generateCodegenArtifactsFromSchema
66+
```
67+
68+
This task invokes the `generateCodegenArtifactsFromSchema` command on all the the imported projects of the app (the app and all the node modules which are linked to it). It generates the code in the corresponding `node_modules/<dependency>` folder. For example, if you have a Fabric Native Component whose Node module is called `my-fabric-component`, the generated code is located in the `SampleApp/node_modules/my-fabric-component/android/build/generated/source/codegen` path. For the app, the code is generated in the `android/app/build/generated/source/codegen` folder.
69+
70+
#### The Generated Code
71+
72+
After running the gradle command above, you will find the codegen code in the `SampleApp/android/app/build` folder. The structure will look like this:
73+
74+
```
75+
build
76+
└── generated
77+
└── source
78+
└── codegen
79+
├── java
80+
│ └── com
81+
│ ├── facebook
82+
│ │ └── react
83+
│ │ └── viewmanagers
84+
│ │ ├── <nativeComponent>ManagerDelegate.java
85+
│ │ └── <nativeComponent>ManagerInterface.java
86+
│ └── sampleapp
87+
│ └── NativeLocalStorageSpec.java
88+
├── jni
89+
│ ├── <codegenConfig.name>-generated.cpp
90+
│ ├── <codegenConfig.name>.h
91+
│ ├── CMakeLists.txt
92+
│ └── react
93+
│ └── renderer
94+
│ └── components
95+
│ └── <codegenConfig.name>
96+
│ ├── <codegenConfig.name>JSI-generated.cpp
97+
│ ├── <codegenConfig.name>.h
98+
│ ├── ComponentDescriptors.cpp
99+
│ ├── ComponentDescriptors.h
100+
│ ├── EventEmitters.cpp
101+
│ ├── EventEmitters.h
102+
│ ├── Props.cpp
103+
│ ├── Props.h
104+
│ ├── ShadowNodes.cpp
105+
│ ├── ShadowNodes.h
106+
│ ├── States.cpp
107+
│ └── States.h
108+
└── schema.json
109+
```
110+
111+
The generated code is split in two folders:
112+
113+
- `java` which contains the platform specific code
114+
- `jni` which contains the C++ code required to let JS and Java interac correctly.
115+
116+
In the `java` folder, you can find the Fabric Native component generated code in the `com/facebook/viewmanagers` subfolder.
117+
118+
- the `<nativeComponent>ManagerDelegate.java` contains the methods that the `ViewManager` can call on the custom Native Component
119+
- the `<nativeComponent>ManagerInterface.java` contains the interface of the `ViewManager`.
120+
121+
In the folder whose name was setup in the `codegenConfig.android.javaPackageName`, instead, you can find the abstract class that a Turbo Native Module has to implement to carry out its tasks.
122+
123+
In the `jni` folder, finally, there is all the boilerplate code to connect JS to Android.
124+
125+
- `<codegenConfig.name>.h` this contains the interface of your custom C++ Turbo Native Modules.
126+
- `<codegenConfig.name>-generated.cpp` this contains the glue code of your custom custom C++ Turbo Native Modules.
127+
- `react/renderer/components/<codegenConfig.name>`: this folder contains all the glue-code required by your custom component.
128+
129+
This structure has been generated by using the value `all` for the `codegenConfig.type` field. If you use the value `modules`, expect to see no `react/renderer/components/` folder. If you use the value `components`, expect not to see any of the other files.
130+
131+
### iOS
132+
133+
**Codegen** for iOS relies on some Node scripts that are invoked during the build process. The scripts are located in the `SampleApp/node_modules/react-native/scripts/` folder.
134+
135+
The main script is the `generate-Codegen-artifacts.js` script. To invoke the script, you can run this command from the root folder of your app:
136+
137+
```bash
138+
node node_modules/react-native/scripts/generate-Codegen-artifacts.js \
139+
--path <path/to/your/app> \
140+
--outputPath <an/output/path> \
141+
--targetPlatform <android | ios>
142+
```
143+
144+
where:
145+
146+
- `--path` is the path to the root folder of your app.
147+
- `--outputPath` is the destination where **Codegen** will write the generated files.
148+
- `--targetPlatform` is the platform you'd like to generate the code for.
149+
150+
#### The Generated Code
151+
152+
Running the script with these arguments:
153+
154+
```shell
155+
node node_modules/react-native/scripts/generate-Codegen-artifacts.js \
156+
--path . \
157+
--outputPath ios/ \
158+
--targetPlatform ios
159+
```
160+
161+
Will generate these files in the `ios/build` folder:
162+
163+
```
164+
build
165+
└── generated
166+
└── ios
167+
├── <codegenConfig.name>
168+
│ ├── <codegenConfig.name>-generated.mm
169+
│ └── <codegenConfig.name>.h
170+
├── <codegenConfig.name>JSI-generated.cpp
171+
├── <codegenConfig.name>JSI.h
172+
├── FBReactNativeSpec
173+
│ ├── FBReactNativeSpec-generated.mm
174+
│ └── FBReactNativeSpec.h
175+
├── FBReactNativeSpecJSI-generated.cpp
176+
├── FBReactNativeSpecJSI.h
177+
├── RCTModulesConformingToProtocolsProvider.h
178+
├── RCTModulesConformingToProtocolsProvider.mm
179+
└── react
180+
└── renderer
181+
└── components
182+
└── <codegenConfig.name>
183+
├── ComponentDescriptors.cpp
184+
├── ComponentDescriptors.h
185+
├── EventEmitters.cpp
186+
├── EventEmitters.h
187+
├── Props.cpp
188+
├── Props.h
189+
├── RCTComponentViewHelpers.h
190+
├── ShadowNodes.cpp
191+
├── ShadowNodes.h
192+
├── States.cpp
193+
└── States.h
194+
```
195+
196+
Part of these generated files are used by React Native in the Core. Then there are a set of files which contains the same name you specified in the package.json `codegenConfig.name` field.
197+
198+
- `<codegenConfig.name>/<codegenConfig.name>.h`: this contains the interface of your custom iOS Turbo Native Modules.
199+
- `<codegenConfig.name>/<codegenConfig.name>-generated.mm`: this contains the glue code of your custom iOS Turbo Native Modules.
200+
- `<codegenConfig.name>JSI.h`: this contains the interface of your custom C++ Turbo Native Modules.
201+
- `<codegenConfig.name>JSI-generated.h`: this contains the glue code of your custom custom C++ Turbo Native Modules.
202+
- `react/renderer/components/<codegenConfig.name>`: this folder contains all the glue-code required by your custom component.
203+
204+
This structure has been generated by using the value `all` for the `codegenConfig.type` field. If you use the value `modules`, expect to see no `react/renderer/components/` folder. If you use the value `components`, expect not to see any of the other files.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# What is Codegen?
2+
3+
**Codegen** is a tool to avoid writing a lot of repetitive code. Using Codegen **is not mandatory**: you can write all the generated manually. However, **Codegen** generates scaffolding code that could save you a lot of time.
4+
5+
React Native invokes **Codegen** automatically every time an iOS or Android app is built. Occasionally, you would like to manually run the **Codegen** scripts to know which types and files are actually generated: this is a common scenario when developing Turbo Native Modules and Fabric Native Components.
6+
7+
<!-- TODO: Add links to TM and FC -->
8+
9+
## How does Codegen works
10+
11+
**Codegen** is a process that is tightly coupled with a React Native app. The **Codegen** scripts live inside the `react-native` NPM package and the apps calls those scripts at build time.
12+
13+
**Codegen** crawls the folders in your project, starting form a directory you specify in your `package.json`, looking for some specific JS files that contains the specificiation (or specs) for your custom modules and components. Spec files are JS files written in a typed dialect: React Native currently supports Flow and TypeScript.
14+
15+
Every time **Codegen** finds a spec files, it generates the boilerplate code associated to it. **Codegen** generates some C++ glue-code and then it generates platform-specific code, using Java for Android and Objective-C++ for iOS.

website/sidebars.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@
7777
"profile-hermes"
7878
],
7979
"JavaScript Runtime": ["javascript-environment", "timers", "hermes"],
80+
"Codegen": [
81+
"the-new-architecture/what-is-codegen",
82+
"the-new-architecture/using-codegen",
83+
"the-new-architecture/codegen-cli"
84+
],
8085
"Android and iOS guides": [
8186
{
8287
"type": "category",

0 commit comments

Comments
 (0)