Fix auto-download of CMake (#43511)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/43511

Changelog: [Internal]

This is an attempt to fix [#39783](https://github.com/facebook/react-native/issues/39783).

It seems that when `configureBuildForHermes` runs (as part of `yarn android` in `rn-tester`) cmake may not be available and is not installed automatically:
* for 3p, even after installing the latest Android Studio, cmake 3.22.1 is not available by default but needs to be installed manually
* for Meta employees, same story when looking at the `ANDROID_HOME` set by the `setup_fb4a.sh` in the `.zshrc` file:
```
# added by setup_fb4a.sh
export ANDROID_SDK=/opt/android_sdk
export ANDROID_NDK_REPOSITORY=/opt/android_ndk
export ANDROID_HOME=${ANDROID_SDK}
export PATH=${PATH}:${ANDROID_SDK}/emulator:${ANDROID_SDK}/tools:${ANDROID_SDK}/tools/bin:${ANDROID_SDK}/platform-tools
```

This diff introduces an explicit task to install cmake.

### ALTERNATIVE 1

See D54897379.

### ALTERNATIVE 2

Suggested by cortinico:

> Create a mini module called :packages:react-native:ReactAndroid:hermes-engine:cmake-downloader which just triggers an empty cmake build via Android SDK

Reviewed By: cortinico

Differential Revision: D54859484

fbshipit-source-id: f9ecdf78ff408947b1e85e7da4f112c89d3a8c89
This commit is contained in:
Fabrizio Cucci
2024-03-15 10:16:29 -07:00
committed by Facebook GitHub Bot
parent fb42a55bdf
commit f2c335ac96
@@ -20,22 +20,27 @@ group = "com.facebook.react"
version = parent?.properties?.get("publishing_version")?.toString()!!
val cmakeVersion = parent?.properties?.get("cmake_version")?.toString()!!
val cmakePath = "${getSDKPath()}/cmake/$cmakeVersion"
val cmakeBinaryPath = "${cmakePath}/bin/cmake"
/**
* We use the bundled version of CMake in the Android SDK if available, to don't force Android users
* to install CMake externally.
*/
fun findCmakePath(cmakeVersion: String): String {
val cmakeRelativePath = "cmake/${cmakeVersion}/bin/cmake"
if (System.getenv("ANDROID_SDK_ROOT") != null &&
File("${System.getenv("ANDROID_SDK_ROOT")}/${cmakeRelativePath}").exists()) {
return "${System.getenv("ANDROID_SDK_ROOT")}/${cmakeRelativePath}"
fun getSDKPath(): String {
val androidSdkRoot = System.getenv("ANDROID_SDK_ROOT")
val androidHome = System.getenv("ANDROID_HOME")
return when {
!androidSdkRoot.isNullOrBlank() -> androidSdkRoot
!androidHome.isNullOrBlank() -> androidHome
else -> throw IllegalStateException("Neither ANDROID_SDK_ROOT nor ANDROID_HOME is set.")
}
if (System.getenv("ANDROID_HOME") != null &&
File("${System.getenv("ANDROID_HOME")}/${cmakeRelativePath}").exists()) {
return "${System.getenv("ANDROID_HOME")}/${cmakeRelativePath}"
}
fun getSDKManagerPath(): String {
val metaSdkManagerPath = File("${getSDKPath()}/cmdline-tools/latest/bin/sdkmanager")
val ossSdkManagerPath = File("${getSDKPath()}/tools/bin/sdkmanager")
return when {
metaSdkManagerPath.exists() -> metaSdkManagerPath.absolutePath
ossSdkManagerPath.exists() -> ossSdkManagerPath.absolutePath
else -> throw GradleException("Could not find sdkmanager executable.")
}
return "cmake"
}
val reactNativeRootDir = project(":packages:react-native:ReactAndroid").projectDir.parent
@@ -111,14 +116,28 @@ val unzipHermes by
into(hermesDir)
}
// NOTE: ideally, we would like CMake to be installed automatically by the `externalNativeBuild`
// below. To do that, we would need the various `ConfigureCMake*` tasks to run *before*
// `configureBuildForHermes` and `buildHermesC` so that CMake is available for their run. But the
// `ConfigureCMake*` tasks depend upon the `ImportHermesc.cmake` file which is actually generated by
// the two tasks mentioned before, so we install CMake manually to break the circular dependency.
val installCMake by
tasks.registering(Exec::class) {
onlyIf { !File(cmakePath).exists() }
commandLine(
windowsAwareCommandLine(getSDKManagerPath(), "--install", "cmake;${cmakeVersion}"))
}
val configureBuildForHermes by
tasks.registering(Exec::class) {
dependsOn(installCMake)
workingDir(hermesDir)
inputs.dir(hermesDir)
outputs.files(hermesBuildOutputFileTree)
commandLine(
windowsAwareCommandLine(
findCmakePath(cmakeVersion),
cmakeBinaryPath,
if (Os.isFamily(Os.FAMILY_WINDOWS)) "-GNMake Makefiles" else "",
"-S",
".",
@@ -135,7 +154,7 @@ val buildHermesC by
outputs.file(hermesCOutputBinary)
commandLine(
windowsAwareCommandLine(
findCmakePath(cmakeVersion),
cmakeBinaryPath,
"--build",
hermesBuildDir.toString(),
"--target",