Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ import com.facebook.react.utils.DependencyUtils.readVersionAndGroupStrings
import com.facebook.react.utils.JdkConfiguratorUtils.configureJavaToolChains
import com.facebook.react.utils.JsonUtils
import com.facebook.react.utils.NdkConfiguratorUtils.configureReactNativeNdk
import com.facebook.react.utils.NdkConfiguratorUtils.configureStrictCxxApiForLibrary
import com.facebook.react.utils.NdkConfiguratorUtils.configureStubPchGeneration
import com.facebook.react.utils.ProjectUtils.isStrictCxxApiEnabled
import com.facebook.react.utils.ProjectUtils.needsCodegenFromPackageJson
import com.facebook.react.utils.PropertyUtils
import com.facebook.react.utils.findPackageJsonFile
Expand Down Expand Up @@ -136,6 +138,9 @@ class ReactPlugin : Plugin<Project> {
subproject.pluginManager.withPlugin("com.android.library") {
if (!subproject.state.executed) {
configureNamespaceForLibraries(subproject)
if (project.isStrictCxxApiEnabled) {
configureStrictCxxApiForLibrary(subproject)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
package com.facebook.react.utils

import com.android.build.api.variant.ApplicationAndroidComponentsExtension
import com.android.build.api.variant.LibraryAndroidComponentsExtension
import com.android.build.api.variant.Variant
import com.facebook.react.ReactExtension
import com.facebook.react.internal.StubPchBuildService
import com.facebook.react.utils.ProjectUtils.getReactNativeArchitectures
import com.facebook.react.utils.ProjectUtils.isStrictCxxApiEnabled
import java.io.File
import org.gradle.api.Project

Expand Down Expand Up @@ -55,6 +57,9 @@ internal object NdkConfiguratorUtils {
if (cmakeArgs.none { it.startsWith("-DANDROID_STL") }) {
cmakeArgs.add("-DANDROID_STL=c++_shared")
}
if (project.isStrictCxxApiEnabled && cmakeArgs.none { it.startsWith("-DRN_STRICT_API") }) {
cmakeArgs.add("-DRN_STRICT_API=ON")
}

val architectures = project.getReactNativeArchitectures()
// abiFilters are split ABI are not compatible each other, so we set the abiFilters
Expand All @@ -66,6 +71,14 @@ internal object NdkConfiguratorUtils {
}
}

/** Defines RN_STRICT_API for the library's own native code. */
fun configureStrictCxxApiForLibrary(project: Project) {
project.extensions.getByType(LibraryAndroidComponentsExtension::class.java).onVariants { variant
->
variant.externalNativeBuild?.cppFlags?.add("-DRN_STRICT_API")
}
}

/**
* The codegen targets share a precompiled header, which only a real build produces. Android
* Studio's C++ engine needs one at sync time, so during a sync we write stubs for the variant
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import com.facebook.react.utils.PropertyUtils.REACT_NATIVE_ARCHITECTURES
import com.facebook.react.utils.PropertyUtils.SCOPED_EDGE_TO_EDGE_ENABLED
import com.facebook.react.utils.PropertyUtils.SCOPED_HERMES_ENABLED
import com.facebook.react.utils.PropertyUtils.SCOPED_REACT_NATIVE_ARCHITECTURES
import com.facebook.react.utils.PropertyUtils.SCOPED_STRICT_CXX_API_ENABLED
import com.facebook.react.utils.PropertyUtils.SCOPED_USE_THIRD_PARTY_JSC
import com.facebook.react.utils.PropertyUtils.STRICT_CXX_API_ENABLED
import com.facebook.react.utils.PropertyUtils.USE_THIRD_PARTY_JSC
import org.gradle.api.Project
import org.gradle.api.file.DirectoryProperty
Expand Down Expand Up @@ -56,6 +58,13 @@ internal object ProjectUtils {
(project.hasProperty(SCOPED_EDGE_TO_EDGE_ENABLED) &&
project.property(SCOPED_EDGE_TO_EDGE_ENABLED).toString().toBoolean())

internal val Project.isStrictCxxApiEnabled: Boolean
get() =
(project.hasProperty(STRICT_CXX_API_ENABLED) &&
project.property(STRICT_CXX_API_ENABLED).toString().toBoolean()) ||
(project.hasProperty(SCOPED_STRICT_CXX_API_ENABLED) &&
project.property(SCOPED_STRICT_CXX_API_ENABLED).toString().toBoolean())

internal val Project.useThirdPartyJSC: Boolean
get() =
(project.hasProperty(USE_THIRD_PARTY_JSC) &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ object PropertyUtils {
const val EDGE_TO_EDGE_ENABLED = "edgeToEdgeEnabled"
const val SCOPED_EDGE_TO_EDGE_ENABLED = "react.edgeToEdgeEnabled"

/**
* Public property that enforces the C++ stable API for the native code of the app and its
* libraries by defining RN_STRICT_API
*/
const val STRICT_CXX_API_ENABLED = "strictCxxApiEnabled"
const val SCOPED_STRICT_CXX_API_ENABLED = "react.strictCxxApiEnabled"

/** Public property that excludes jsctooling from core */
const val USE_THIRD_PARTY_JSC = "useThirdPartyJSC"
const val SCOPED_USE_THIRD_PARTY_JSC = "react.useThirdPartyJSC"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import com.facebook.react.utils.ProjectUtils.getReactNativeArchitectures
import com.facebook.react.utils.ProjectUtils.isEdgeToEdgeEnabled
import com.facebook.react.utils.ProjectUtils.isHermesEnabled
import com.facebook.react.utils.ProjectUtils.isNewArchEnabled
import com.facebook.react.utils.ProjectUtils.isStrictCxxApiEnabled
import com.facebook.react.utils.ProjectUtils.needsCodegenFromPackageJson
import java.io.File
import org.assertj.core.api.Assertions.assertThat
Expand Down Expand Up @@ -115,6 +116,39 @@ class ProjectUtilsTest {
assertThat(project.isEdgeToEdgeEnabled).isFalse()
}

@Test
fun isStrictCxxApiEnabled_returnsFalseByDefault() {
assertThat(createProject().isStrictCxxApiEnabled).isFalse()
}

@Test
fun isStrictCxxApiEnabled_withEnabledViaProperty_returnsTrue() {
val project = createProject()
project.extensions.extraProperties.set("strictCxxApiEnabled", "true")
assertThat(project.isStrictCxxApiEnabled).isTrue()
}

@Test
fun isStrictCxxApiEnabled_withEnabledViaScopedProperty_returnsTrue() {
val project = createProject()
project.extensions.extraProperties.set("react.strictCxxApiEnabled", "true")
assertThat(project.isStrictCxxApiEnabled).isTrue()
}

@Test
fun isStrictCxxApiEnabled_withDisabledViaProperty_returnsFalse() {
val project = createProject()
project.extensions.extraProperties.set("strictCxxApiEnabled", "false")
assertThat(project.isStrictCxxApiEnabled).isFalse()
}

@Test
fun isStrictCxxApiEnabled_withInvalidViaProperty_returnsFalse() {
val project = createProject()
project.extensions.extraProperties.set("strictCxxApiEnabled", "¯\\_(ツ)_/¯")
assertThat(project.isStrictCxxApiEnabled).isFalse()
}

@Test
fun needsCodegenFromPackageJson_withCodegenConfigInPackageJson_returnsTrue() {
val project = createProject()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ target_link_libraries(${CMAKE_PROJECT_NAME}
add_library(common_flags INTERFACE)
target_compile_options(common_flags INTERFACE ${folly_FLAGS})

if(RN_STRICT_API)
target_compile_definitions(common_flags INTERFACE RN_STRICT_API)
target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE RN_STRICT_API)
endif()

# Defines the `reactnative_pch` target and `target_reuse_reactnative_pch()`, so
# the codegen targets below share a single precompiled header. Has to come after
# `common_flags`, as the precompiled header is built with the same flags as its
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,10 @@

#pragma once

#include <ReactCommon/JavaTurboModule.h>
#include <ReactCommon/TurboModule.h>
#include <React/Bridging.h>
#include <React/ComponentRegistry.h>
#include <React/NativeModuleCore.h>
#include <React/RendererCore.h>
#include <React/View.h>
#include <folly/dynamic.h>
#include <jsi/jsi.h>
#include <react/bridging/Bridging.h>
#include <react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h>
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
#include <react/renderer/components/view/ViewEventEmitter.h>
#include <react/renderer/core/ConcreteComponentDescriptor.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/core/StateData.h>
#include <react/renderer/core/propsConversions.h>
Loading