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

chore: change gradle task for copying to new archs into JS scripts #2224

Merged
merged 21 commits into from
Jul 10, 2024
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
4eaf9fe
chore: change gradle task for copying to new archs into JS scripts
maciekstosio Jul 2, 2024
a4a707a
fix: add installing dependencies
maciekstosio Jul 2, 2024
b214415
chore: run prettier on new scripts and fix scripts name
maciekstosio Jul 2, 2024
5d250e2
fix: take react-native from root node modules
maciekstosio Jul 2, 2024
bbace06
chore: test
maciekstosio Jul 2, 2024
51f3397
chore: revert test
maciekstosio Jul 2, 2024
bfbc266
feat: run sync archs on prebuild
maciekstosio Jul 8, 2024
cd5e7d0
Update .github/workflows/check-paper-integrity.yml
maciekstosio Jul 8, 2024
54bcd79
Update .github/workflows/check-paper-integrity.yml
maciekstosio Jul 8, 2024
8e4f7a0
chore: fix task name, update name and run github workflow only on cha…
maciekstosio Jul 8, 2024
2b31454
chore: test pipeline
maciekstosio Jul 8, 2024
adb798d
chore: test pipeline 2
maciekstosio Jul 8, 2024
4106011
chore: roll back changes for test
maciekstosio Jul 8, 2024
6a24cee
chore: fix line end
maciekstosio Jul 8, 2024
bdf4f93
chore: fix end of file with empty line
maciekstosio Jul 8, 2024
1b2a000
chore: add changes from comments
maciekstosio Jul 8, 2024
3e8dc1e
feat: extract package name prefix to the variable
maciekstosio Jul 9, 2024
cfaa6da
Merge branch 'main' into @maciekstosio/Change-gradle-copy-task-to-JS-
maciekstosio Jul 9, 2024
18d3e80
fix: fix prefix
maciekstosio Jul 10, 2024
7f96746
fix: run yarn in root in android-build-test
maciekstosio Jul 10, 2024
f1ff4b6
fix: caching and steps naming
maciekstosio Jul 10, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .github/workflows/check-archs-consistency.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Test consistency between Paper & Fabric
on:
pull_request:
branches:
- main
paths:
- src/fabric/**
- android/src/paper/java/com/facebook/react/viewmanagers/**
jobs:
check:
runs-on: ubuntu-latest
concurrency:
group: check-archs-consistency-${{ github.ref }}
cancel-in-progress: true
steps:
- name: checkout
uses: actions/checkout@v2
- name: Use Node.js 18
uses: actions/setup-node@v2
Comment on lines +17 to +19
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use v4 script versions.

Suggested change
uses: actions/checkout@v2
- name: Use Node.js 18
uses: actions/setup-node@v2
uses: actions/checkout@v4
- name: Use Node.js 18
uses: actions/setup-node@v4

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:(

with:
node-version: 18
cache: 'yarn'
- name: Install node dependencies
run: yarn
- name: Check Android Paper & Fabric generated interfaces consistency
run: yarn check-archs-consistency
10 changes: 10 additions & 0 deletions Example/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,13 @@ dependencies {
}

apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
apply plugin: 'com.github.node-gradle.node'

task syncArchs(type: NodeTask) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get it why it's still here. Don't we do everything on the JS side now?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's in the app so it shouldn't interfere with the lib. I understood that @kkafar wanted to have it run automatically while developing. It needs to be added per example/test app, so I can just not add it in other packages.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah & I want this in screens.

group = 'Build'
description = 'Run sync beetwen Paper and Fabric arch'
yarn_install
script = file('../../../scripts/codegen-sync-archs.js')
}

tasks['preBuild'].dependsOn(syncArchs)
2 changes: 2 additions & 0 deletions Example/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ buildscript {
repositories {
google()
mavenCentral()
gradlePluginPortal() // Added to run node ./scripts/codegen-sync-archs.js using syncArchs task
}
dependencies {
classpath("com.android.tools.build:gradle")
classpath("com.facebook.react:react-native-gradle-plugin")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
classpath("com.github.node-gradle:gradle-node-plugin:7.0.2") // Added to run node ./scripts/codegen-sync-archs.js using syncArchs task
}
}

Expand Down
2 changes: 0 additions & 2 deletions Example/android/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,3 @@ hermesEnabled=true
# This is necessary, because the code checking for multiple instances
# detects package versions from other example applications in the repository.
disableMultipleInstancesCheck=true

isScreensExampleApp=true
2 changes: 0 additions & 2 deletions FabricExample/android/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,3 @@ newArchEnabled=true
# Use this property to enable or disable the Hermes JS engine.
# If set to false, you will be using JSC instead.
hermesEnabled=true

isScreensExampleApp=true
1 change: 0 additions & 1 deletion TVOSExample/android/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,3 @@ newArchEnabled=false
# If set to false, you will be using JSC instead.
hermesEnabled=true

isScreensExampleApp=true
76 changes: 0 additions & 76 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -196,79 +196,3 @@ dependencies {
}
}
}

def isScreensExampleApp() {
return project.hasProperty('isScreensExampleApp') && project.property('isScreensExampleApp') == "true"
}

def getAbsoluteCodegenArtifactsPaperDestination() {
if (!project.hasProperty('codegenArtifactsPaperDestination')) {
throw new Exception('[RNScreens] Please fill codegenArtifactsPaperDestination variable in android/gradle.properties correct path to paper paper destination')
}

return "${project.rootDir}/../../${project.property('codegenArtifactsPaperDestination')}"
}

def getAbsoluteCodegenArtifactsSource() {
if (!project.hasProperty('codegenArtifactsSource')) {
throw new Exception('[RNScreens] Please fill codegenArtifactsSource variable in android/gradle.properties correct path to codegenerated artifacts')
}

return "${project.rootDir}/../../${project.property('codegenArtifactsSource')}"
}


tasks.register("copyCodegenArtifacts") {
group 'After build tasks'
description 'Tasks which copy codegen artifacts to paper architecture'

if (!isScreensExampleApp() || !isNewArchitectureEnabled()) {
return
}

dependsOn tasks.generateCodegenArtifactsFromSchema

doLast {

def absoluteCodegenArtifactsPaperDestination = getAbsoluteCodegenArtifactsPaperDestination()
def absoluteCodegenArtifactsSource = getAbsoluteCodegenArtifactsSource()

def existingFiles = fileTree(absoluteCodegenArtifactsPaperDestination).matching {
include '**/*.java'
}

def generatedFiles = fileTree(absoluteCodegenArtifactsSource).matching {
include '**/*.java'
}

def existingFilesMap = [:]

existingFiles.forEach { existingFile ->
existingFilesMap[existingFile.name] = 1
}

generatedFiles.forEach { generatedFile ->
if (!existingFilesMap.containsKey(generatedFile.name)) {
logger.warn("[RNScreens] ${generatedFile.name} not found in paper dir, if it's used in Android you need to copy it manually and implement yourself before using auto-copy feature")
}
}

if (existingFiles.size() == 0) {
logger.warn("[RNScreens] Paper destination with codegen interfaces is empty. This might be okay if you don't have any interfaces/delegates used in Android, if that's not the case please check if codegenArtifactsPaperDestination in android/gradle.properties is correct")
}

if (existingFiles.size() > generatedFiles.size()) {
throw new Exception("[RNScreens] Number od generated artifacts should be greather then or equal to paper interfaces. Please check if codegenArtifactsSource in android/gradle.properties is correct")
}

copy {
from absoluteCodegenArtifactsSource
include existingFiles.collect { it.name }
into absoluteCodegenArtifactsPaperDestination
}
}
}

if (isScreensExampleApp() && isNewArchitectureEnabled()) {
tasks.generateCodegenArtifactsFromSchema.finalizedBy('copyCodegenArtifacts')
}
7 changes: 0 additions & 7 deletions android/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,3 @@ android.useAndroidX=true
android.enableJetifier=true

kotlin.code.style=official

# Path to codegen output directory with this library view manager's interfaces & delegates. Used by `copyCodegenArtifacts` task that helps to synchronise newly generated files with their Paper conterparts.
codegenArtifactsSource=android/build/generated/source/codegen/java/com/facebook/react/viewmanagers

# Path to directory with view manager's interfaces & delegates used while running on Paper architecture. This property is used as output path for `copyCodegenArtifacts` task.
# Used for task (copyCodegenArtifacts) that automates copying those interfaces/delegates when codegen is run
codegenArtifactsPaperDestination=android/src/paper/java/com/facebook/react/viewmanagers/
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
"lint-android": "./android/gradlew -p android spotlessCheck -q",
"lint": "yarn lint-js && yarn lint-android",
"release": "yarn prepare && npm login && release-it",
"prepare": "bob build && husky install"
"prepare": "bob build && husky install",
"check-archs-consistency": "node ./scripts/codegen-check-consistency.js",
"sync-archs": "node ./scripts/codegen-sync-archs.js"
},
"main": "lib/commonjs/index",
"module": "lib/module/index",
Expand Down Expand Up @@ -127,7 +129,8 @@
"cpp/**/*.{h,cpp}": "yarn format-cpp",
"android/src/main/cpp/.{cpp, h}": "yarn format-android-cpp",
"android/**/*.kt": "yarn format-android",
"ios/**/*.{h,m,mm,cpp}": "yarn format-ios"
"ios/**/*.{h,m,mm,cpp}": "yarn format-ios",
"src/fabric/*.ts": "yarn sync-archs"
},
"react-native-builder-bob": {
"source": "src",
Expand Down
3 changes: 3 additions & 0 deletions scripts/codegen-check-consistency.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const { checkCodegenIntegrity } = require('./codegen-utils');

checkCodegenIntegrity();
3 changes: 3 additions & 0 deletions scripts/codegen-sync-archs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const { generateCodegenJavaOldArch } = require('./codegen-utils');

generateCodegenJavaOldArch();
124 changes: 124 additions & 0 deletions scripts/codegen-utils.js
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job with this one!

Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
const packageJSON = require('../package.json');

const ERROR_PREFIX = 'RNScreens'
const ROOT_DIR = path.resolve(__dirname, '..');
const ANDROID_DIR = path.resolve(ROOT_DIR, 'android');
const GENERATED_DIR = path.resolve(ANDROID_DIR, 'build/generated');
const OLD_ARCH_DIR = path.resolve(ANDROID_DIR, 'src/paper');
const SPECS_DIR = path.resolve(ROOT_DIR, packageJSON.codegenConfig.jsSrcsDir);
const PACKAGE_NAME = packageJSON.codegenConfig.android.javaPackageName;
const RN_DIR = path.resolve(ROOT_DIR, 'node_modules/react-native');
const RN_CODEGEN_DIR = path.resolve(
ROOT_DIR,
'node_modules/@react-native/codegen'
);

const SOURCE_FOLDERS = 'java/com/facebook/react/viewmanagers';
const CODEGEN_FILES_DIR = `${GENERATED_DIR}/source/codegen/${SOURCE_FOLDERS}`;
const OLD_ARCH_FILES_DIR = `${OLD_ARCH_DIR}/${SOURCE_FOLDERS}`;

function exec(command) {
console.log(`[${PACKAGE_NAME}]> ` + command);
execSync(command);
}

function fixOldArchJavaForRN72Compat(dir) {
// see https://github.com/rnmapbox/maps/issues/3193
const files = fs.readdirSync(dir);
files.forEach(file => {
const filePath = path.join(dir, file);
const fileExtension = path.extname(file);
if (fileExtension === '.java') {
let fileContent = fs.readFileSync(filePath, 'utf-8');
let newFileContent = fileContent.replace(
/extends ReactContextBaseJavaModule implements TurboModule/g,
'extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule'
);
if (fileContent !== newFileContent) {
// also insert an import line with `import com.facebook.react.bridge.ReactModuleWithSpec;`
newFileContent = newFileContent.replace(
/import com.facebook.react.bridge.ReactMethod;/,
'import com.facebook.react.bridge.ReactMethod;\nimport com.facebook.react.bridge.ReactModuleWithSpec;'
);

console.log(' => fixOldArchJava applied to:', filePath);
fs.writeFileSync(filePath, newFileContent, 'utf-8');
}
} else if (fs.lstatSync(filePath).isDirectory()) {
fixOldArchJavaForRN72Compat(filePath);
}
});
}

async function generateCodegen() {
exec(`rm -rf ${GENERATED_DIR}`);
exec(`mkdir -p ${GENERATED_DIR}/source/codegen/`);

exec(
`node ${RN_CODEGEN_DIR}/lib/cli/combine/combine-js-to-schema-cli.js --platform android ${GENERATED_DIR}/source/codegen/schema.json ${SPECS_DIR}`
);
exec(
`node ${RN_DIR}/scripts/generate-specs-cli.js --platform android --schemaPath ${GENERATED_DIR}/source/codegen/schema.json --outputDir ${GENERATED_DIR}/source/codegen --javaPackageName ${PACKAGE_NAME}`
);

fixOldArchJavaForRN72Compat(`${GENERATED_DIR}/source/codegen/java/`);
}

async function generateCodegenJavaOldArch() {
await generateCodegen();

const generatedFiles = fs.readdirSync(CODEGEN_FILES_DIR);
const oldArchFiles = fs.readdirSync(OLD_ARCH_FILES_DIR);
maciekstosio marked this conversation as resolved.
Show resolved Hide resolved
const existingFilesSet = new Set(oldArchFiles.map(fileName => fileName));

generatedFiles.forEach(generatedFile => {
if (!existingFilesSet.has(generatedFile)) {
console.warn(
`[${ERROR_PREFIX}] ${generatedFile} not found in paper dir, if it's used on Android you need to copy it manually and implement yourself before using auto-copy feature.`
);
}
});

if (oldArchFiles.length === 0) {
console.warn(
`[${ERROR_PREFIX}] Paper destination with codegen interfaces is empty. This might be okay if you don't have any interfaces/delegates used on Android, otherwise please check if OLD_ARCH_DIR and SOURCE_FOLDERS are set properly.`
);
}

oldArchFiles.forEach(oldArchFile => {
if (!fs.existsSync(`${CODEGEN_FILES_DIR}/${oldArchFile}`)) {
console.warn(
`[${ERROR_PREFIX}] ${existingFile.name} file does not exist in codegen artifacts source destination. Please check if you still need this interface/delagete.`
);
}
});

oldArchFiles.forEach(file => {
exec(`cp -rf ${CODEGEN_FILES_DIR}/${file} ${OLD_ARCH_FILES_DIR}/${file}`);
});
}

function compareFileAtTwoPaths(filename, firstPath, secondPath) {
const fileA = fs.readFileSync(`${firstPath}/${filename}`, 'utf-8');
const fileB = fs.readFileSync(`${secondPath}/${filename}`, 'utf-8');

maciekstosio marked this conversation as resolved.
Show resolved Hide resolved
if (fileA !== fileB) {
throw new Error(
`[${ERROR_PREFIX}] File ${filename} is different at ${firstPath} and ${secondPath}. Make sure you commited codegen autogenerated files.`
);
}
}

async function checkCodegenIntegrity() {
await generateCodegen();

const oldArchFiles = fs.readdirSync(OLD_ARCH_FILES_DIR);
oldArchFiles.forEach(file => {
compareFileAtTwoPaths(file, CODEGEN_FILES_DIR, OLD_ARCH_FILES_DIR);
});
}

module.exports = { generateCodegenJavaOldArch, checkCodegenIntegrity };
Loading