diff --git a/.gitignore b/.gitignore
index 9b7bb83d3f4ce..d670b3fe0dbd0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,3 +39,4 @@ __pycache__
# Don't ignore src files under build package
!**/src/**/build
+/jbdeps/android-sdk/linux/*
\ No newline at end of file
diff --git a/.run/All tests.run.xml b/.run/All tests.run.xml
new file mode 100644
index 0000000000000..f2ba200dcd4b3
--- /dev/null
+++ b/.run/All tests.run.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+ false
+ true
+ false
+
+
+
\ No newline at end of file
diff --git a/.run/Compiler (Unit tests).run.xml b/.run/Compiler (Unit tests).run.xml
new file mode 100644
index 0000000000000..0db94ad99a275
--- /dev/null
+++ b/.run/Compiler (Unit tests).run.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+ true
+ false
+
+
+
\ No newline at end of file
diff --git a/.run/Runtime (Android integration tests).run.xml b/.run/Runtime (Android integration tests).run.xml
new file mode 100644
index 0000000000000..e43217e149bdb
--- /dev/null
+++ b/.run/Runtime (Android integration tests).run.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/Runtime (Unit tests).run.xml b/.run/Runtime (Unit tests).run.xml
new file mode 100644
index 0000000000000..569b2f1f77c31
--- /dev/null
+++ b/.run/Runtime (Unit tests).run.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+ true
+ false
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index be89bdb816ab3..86492992bb22e 100644
--- a/README.md
+++ b/README.md
@@ -1,69 +1,35 @@
-# Android Jetpack
+# Fork of https://github.com/androidx/androidx (androidx-main branch) to test Compose Compiler
-[![Revved up by Develocity](https://img.shields.io/badge/Revved%20up%20by-Develocity-06A0CE?logo=Gradle&labelColor=02303A)](https://ge.androidx.dev)
+TODO(igor.demin@jetbrains.com): we need to test Compose Compiler for JS and Native too
-Jetpack is a suite of libraries, tools, and guidance to help developers write high-quality apps easier. These components help you follow best practices, free you from writing boilerplate code, and simplify complex tasks, so you can focus on the code you care about.
+## Developing in IDE
-Jetpack comprises the `androidx.*` package libraries, unbundled from the platform APIs. This means that it offers backward compatibility and is updated more frequently than the Android platform, making sure you always have access to the latest and greatest versions of the Jetpack components.
+1. Download Android Studio version that is specified in [libs.versions.toml](gradle/libs.versions.toml#L11)
-Our official AARs and JARs binaries are distributed through [Google Maven](https://maven.google.com).
+2. Open the project in Android Studio
-You can learn more about using it from [Android Jetpack landing page](https://developer.android.com/jetpack).
+3. Make sure that you use OpenJDK 11 in `Project settings -> Project`, and have `Gradle JVM = Project SDK` in `Settings -> Build, Executions, Deployment -> Build Tools -> Gradle`
-# Contribution Guide
+4. Change Kotlin version in `gradle/libs.versions.toml` if needed (search for `kotlin = `)
-For contributions via GitHub, see the [GitHub Contribution Guide](CONTRIBUTING.md).
+5. Run `All tests`, `Compiler (Unit tests)`, `Runtime (Unit tests)` or `Runtime (Android integration tests)` to run tests.
+If you don't see them, restart Android Studio (it seems a bug).
-Note: The contributions workflow via GitHub is currently experimental - only contributions to the following projects are being accepted at this time:
-* [Activity](activity)
-* [AppCompat](appcompat)
-* [Biometric](biometric)
-* [Collection](collection)
-* [Compose Compiler](compose/compiler)
-* [Compose Runtime](compose/runtime)
-* [Core](core)
-* [DataStore](datastore)
-* [Fragment](fragment)
-* [Lifecycle](lifecycle)
-* [Navigation](navigation)
-* [Paging](paging)
-* [Room](room)
-* [WorkManager](work)
+Notes:
+- To run All tests you need a connected Android device or emulator (Android studio don't run it automatically)
+- Compiler tests seems don't work on Windows
-## Code Review Etiquette
-When contributing to Jetpack, follow the [code review etiquette](code-review.md).
+## Gradle commands
-## Accepted Types of Contributions
-* Bug fixes - needs a corresponding bug report in the [Android Issue Tracker](https://issuetracker.google.com/issues/new?component=192731&template=842428)
-* Each bug fix is expected to come with tests
-* Fixing spelling errors
-* Updating documentation
-* Adding new tests to the area that is not currently covered by tests
-* New features to existing libraries if the feature request bug has been approved by an AndroidX team member.
+1. Gradle command to build Compose Compiler:
+```
+export COMPOSE_CUSTOM_VERSION=0.0.0-custom2
+./gradlew compose:compiler:compiler:publishMavenPublicationToLocalRepository
+```
+The artifact `androidx.compose.compiler:compiler:0.0.0-custom2` will be in `~/.m2/repository/androidx/compose/compiler/compiler/0.0.0-custom2`
-We **are not** currently accepting new modules.
-
-## Checking Out the Code
-
-Head over to the [onboarding docs](docs/onboarding.md) to learn more about getting set up and the
-development workflow!
-
-### Continuous integration
-[Our continuous integration system](https://ci.android.com/builds/branches/aosp-androidx-main/grid?) builds all in progress (and potentially unstable) libraries as new changes are merged. You can manually download these AARs and JARs for your experimentation.
-
-## Password and Contributor Agreement before making a change
-Before uploading your first contribution, you will need setup a password and agree to the contribution agreement:
-
-Generate a HTTPS password:
-https://android-review.googlesource.com/new-password
-
-Agree to the Google Contributor Licenses Agreement:
-https://android-review.googlesource.com/settings/new-agreement
-
-## Getting reviewed
-* After you run repo upload, open [r.android.com](http://r.android.com)
-* Sign in into your account (or create one if you do not have one yet)
-* Add an appropriate reviewer (use git log to find who did most modifications on the file you are fixing or check the OWNERS file in the project's directory)
-
-## Handling binary dependencies
-AndroidX uses git to store all the binary Gradle dependencies. They are stored in `prebuilts/androidx/internal` and `prebuilts/androidx/external` directories in your checkout. All the dependencies in these directories are also available from `google()`, or `mavenCentral()`. We store copies of these dependencies to have hermetic builds. You can pull in [a new dependency using our importMaven tool](development/importMaven/README.md).
+2. Gradle command to test Compose Runtime:
+```
+./gradlew :compose:runtime:runtime:testDebugUnitTest :compose:runtime:runtime:integration-tests:connectedAndroidTest :compose:compiler:compiler-hosted:integration-tests:testDebugUnitTest
+```
+It runs unit tests and Android tests (there should be a connected Android device or emulator)
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXExtension.kt b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXExtension.kt
index bc564a21e30ed..931d719678a87 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXExtension.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXExtension.kt
@@ -43,6 +43,9 @@ abstract class AndroidXExtension(val project: Project) : ExtensionAware, Android
val listProjectsService: Provider
+ private val composeCustomVersion = project.providers.environmentVariable("COMPOSE_CUSTOM_VERSION")
+ private val composeCustomGroup = project.providers.environmentVariable("COMPOSE_CUSTOM_GROUP")
+
private val versionService: LibraryVersionsService
val deviceTests = DeviceTests.register(project.extensions)
@@ -186,12 +189,17 @@ abstract class AndroidXExtension(val project: Project) : ExtensionAware, Android
return null
}
// convert parent project path to groupId
- val groupIdText =
- if (projectPath.startsWith(":external")) {
- projectPath.replace(":external:", "")
+ val groupIdText = if (projectPath.startsWith(":external")) {
+ projectPath.replace(":external:", "")
+ } else {
+ "androidx.${parentPath.substring(1).replace(':', '.')}"
+ }.let {
+ if (it.contains("compose") && composeCustomGroup.isPresent) {
+ it.replace("androidx.compose", composeCustomGroup.get())
} else {
- "androidx.${parentPath.substring(1).replace(':', '.')}"
+ it
}
+ }
// get the library group having that text
val result = libraryGroupsByGroupId[groupIdText]
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
index 722d2b3569706..e3b4186c43171 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
@@ -182,8 +182,8 @@ constructor(private val componentFactory: SoftwareComponentFactory) : Plugin {
maybeRegisterFilterableTask()
+ val isJBFork = true
// If we're running inside Studio, validate the Android Gradle Plugin version.
val expectedAgpVersion = System.getenv("EXPECTED_AGP_VERSION")
- if (properties.containsKey("android.injected.invoked.from.ide")) {
+ if (!isJBFork && properties.containsKey("android.injected.invoked.from.ide")) {
if (expectedAgpVersion != ANDROID_GRADLE_PLUGIN_VERSION) {
throw GradleException(
"""
diff --git a/buildSrc/public/src/main/kotlin/androidx/build/SdkHelper.kt b/buildSrc/public/src/main/kotlin/androidx/build/SdkHelper.kt
index f056d5670fca3..aafeb95882d86 100644
--- a/buildSrc/public/src/main/kotlin/androidx/build/SdkHelper.kt
+++ b/buildSrc/public/src/main/kotlin/androidx/build/SdkHelper.kt
@@ -49,10 +49,8 @@ fun Project.getSdkDependency(): FileTree =
/** Returns the root project's platform-specific SDK path as a file. */
fun Project.getSdkPath(): File {
- if (
- rootProject.plugins.hasPlugin("AndroidXPlaygroundRootPlugin") ||
- System.getenv("COMPOSE_DESKTOP_GITHUB_BUILD") != null
- ) {
+ val isJBFork = true
+ if (isJBFork) {
// This is not full checkout, use local settings instead.
// https://developer.android.com/studio/command-line/variables
// check for local.properties first
diff --git a/buildSrc/public/src/main/kotlin/androidx/build/SdkResourceGenerator.kt b/buildSrc/public/src/main/kotlin/androidx/build/SdkResourceGenerator.kt
index 991a22c58618a..005156e8d3cad 100644
--- a/buildSrc/public/src/main/kotlin/androidx/build/SdkResourceGenerator.kt
+++ b/buildSrc/public/src/main/kotlin/androidx/build/SdkResourceGenerator.kt
@@ -124,6 +124,12 @@ abstract class SdkResourceGenerator : DefaultTask() {
@JvmStatic
fun generateForHostTest(project: Project) {
+ // We have this error on Windows:
+ // Could not create task ':compose:compiler:compiler:integration-tests:generateSdkResource'.
+ // > this and base files have different roots: ~\.m2\repository and ...\compose-jb\compose\frameworks\support\compose\compiler\compiler\integration-tests.
+ val os = System.getProperty("os.name").lowercase()
+ if (os.startsWith("win")) return
+
val provider = registerSdkResourceGeneratorTask(project)
val extension = project.extensions.getByType()
val testSources = extension.sourceSets.getByName("test")
diff --git a/buildSrc/public/src/main/kotlin/androidx/build/Version.kt b/buildSrc/public/src/main/kotlin/androidx/build/Version.kt
index 4b4a47306d556..6a9b0498a212d 100644
--- a/buildSrc/public/src/main/kotlin/androidx/build/Version.kt
+++ b/buildSrc/public/src/main/kotlin/androidx/build/Version.kt
@@ -75,7 +75,7 @@ data class Version(val major: Int, val minor: Int, val patch: Int, val extra: St
private const val serialVersionUID = 345435634563L
private val VERSION_FILE_REGEX = Pattern.compile("^(res-)?(.*).txt$")
- private val VERSION_REGEX = Pattern.compile("^(\\d+)\\.(\\d+)\\.(\\d+)(-.+)?$")
+ private val VERSION_REGEX = Pattern.compile("^(\\d+)\\.(\\d+)\\.(\\d+)((?:\\.\\d+)?(?:-.+)?)?$")
private fun checkedMatcher(versionString: String): Matcher {
val matcher = VERSION_REGEX.matcher(versionString)
diff --git a/buildSrc/repos.gradle b/buildSrc/repos.gradle
index 297a520624902..8dafc107723f7 100644
--- a/buildSrc/repos.gradle
+++ b/buildSrc/repos.gradle
@@ -63,14 +63,28 @@ def addMavenRepositories(RepositoryHandler handler) {
}
}
}
- if (System.getenv("ALLOW_PUBLIC_REPOS") != null || System.getProperty("ALLOW_PUBLIC_REPOS") != null) {
+ def isJBFork = true
+ if (isJBFork) {
+ handler.maven {
+ url("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev/")
+ }
+ handler.mavenLocal()
handler.mavenCentral()
handler.google()
handler.gradlePluginPortal()
handler.maven {
url("https://maven.pkg.jetbrains.space/public/p/compose/dev")
}
- handler.mavenLocal()
+ handler.maven {
+ url("https://maven.pkg.jetbrains.space/public/p/kotlinx-coroutines/maven")
+ }
+ // TODO(b/280646217): Remove after official release to gmaven.
+ handler.maven {
+ url("https://storage.googleapis.com/r8-releases/raw")
+ content {
+ includeModule("com.android.tools", "r8")
+ }
+ }
}
// Ordering appears to be important: b/229733266
def androidPluginRepoOverride = System.getenv("GRADLE_PLUGIN_REPO")
diff --git a/buildSrc/settings.gradle b/buildSrc/settings.gradle
index 68c85829b52c9..8c3c34f641bee 100644
--- a/buildSrc/settings.gradle
+++ b/buildSrc/settings.gradle
@@ -29,6 +29,7 @@ include ":imports:stableaidl-gradle-plugin"
dependencyResolutionManagement {
versionCatalogs {
libs {
+ //from(files("../gradle/libs.versions.toml"))
def agpOverride = System.getenv("GRADLE_PLUGIN_VERSION")
if (agpOverride != null) {
logger.warn("Using custom version ${agpOverride} of AGP due to GRADLE_PLUGIN_VERSION being set.")
diff --git a/buildSrc/settingsScripts/project-dependency-graph.groovy b/buildSrc/settingsScripts/project-dependency-graph.groovy
index a59f5f1f15d59..d89964c36993d 100644
--- a/buildSrc/settingsScripts/project-dependency-graph.groovy
+++ b/buildSrc/settingsScripts/project-dependency-graph.groovy
@@ -221,7 +221,7 @@ class ProjectDependencyGraph {
// fixed.
// This option is supported so that development/simplify_build_failure.sh can try
// deleting entire projects at once to identify the cause of a build failure
- if (System.getenv("ALLOW_MISSING_PROJECTS") == null) {
+ if (System.getenv("ALLOW_MISSING_PROJECTS") == null && false) {
throw new Exception("Path " + buildGradle + " does not exist;" +
"cannot include project " + projectPath + " ($projectDir)")
}
diff --git a/buildSrc/shared.gradle b/buildSrc/shared.gradle
index b135cf6f03237..616bb4c438f1d 100644
--- a/buildSrc/shared.gradle
+++ b/buildSrc/shared.gradle
@@ -36,7 +36,7 @@ tasks.withType(KotlinCompile).configureEach {
kotlinOptions {
jvmTarget = "17"
freeCompilerArgs += [
- "-Werror",
+ //"-Werror",
"-Xskip-metadata-version-check"
]
languageVersion = "1.8"
diff --git a/compose/compiler/compiler-hosted/build.gradle b/compose/compiler/compiler-hosted/build.gradle
index dfa7c90fdd154..98cdfd598c936 100644
--- a/compose/compiler/compiler-hosted/build.gradle
+++ b/compose/compiler/compiler-hosted/build.gradle
@@ -39,6 +39,9 @@ dependencies {
}
tasks.withType(KotlinCompile).configureEach {
+ sourceCompatibility = JavaVersion.VERSION_11
+ targetCompatibility = JavaVersion.VERSION_11
+
kotlinOptions {
jvmTarget = "1.8"
freeCompilerArgs = [
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/ComposeIrGenerationExtension.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/ComposeIrGenerationExtension.kt
index 9ffd47dce893d..113d6acd8aa22 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/ComposeIrGenerationExtension.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/ComposeIrGenerationExtension.kt
@@ -19,6 +19,7 @@ package androidx.compose.compiler.plugins.kotlin
import androidx.compose.compiler.plugins.kotlin.analysis.FqNameMatcher
import androidx.compose.compiler.plugins.kotlin.analysis.StabilityInferencer
import androidx.compose.compiler.plugins.kotlin.lower.ClassStabilityTransformer
+import androidx.compose.compiler.plugins.kotlin.lower.ClassStabilityInferredCollection
import androidx.compose.compiler.plugins.kotlin.lower.ComposableFunInterfaceLowering
import androidx.compose.compiler.plugins.kotlin.lower.ComposableFunctionBodyTransformer
import androidx.compose.compiler.plugins.kotlin.lower.ComposableLambdaAnnotator
@@ -36,6 +37,8 @@ import androidx.compose.compiler.plugins.kotlin.lower.WrapJsComposableLambdaLowe
import androidx.compose.compiler.plugins.kotlin.lower.decoys.CreateDecoysTransformer
import androidx.compose.compiler.plugins.kotlin.lower.decoys.RecordDecoySignaturesTransformer
import androidx.compose.compiler.plugins.kotlin.lower.decoys.SubstituteDecoyCallsTransformer
+import androidx.compose.compiler.plugins.kotlin.lower.hiddenfromobjc.AddHiddenFromObjCLowering
+import androidx.compose.compiler.plugins.kotlin.lower.hiddenfromobjc.HideFromObjCDeclarationsSet
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable
@@ -46,7 +49,9 @@ import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerIr
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.platform.isJs
+import org.jetbrains.kotlin.platform.isWasm
import org.jetbrains.kotlin.platform.jvm.isJvm
+import org.jetbrains.kotlin.platform.konan.isNative
class ComposeIrGenerationExtension(
@Suppress("unused") private val liveLiteralsEnabled: Boolean = false,
@@ -62,7 +67,9 @@ class ComposeIrGenerationExtension(
private val useK2: Boolean = false,
private val strongSkippingEnabled: Boolean = false,
private val stableTypeMatchers: Set = emptySet(),
- private val moduleMetricsFactory: ((StabilityInferencer) -> ModuleMetrics)? = null
+ private val moduleMetricsFactory: ((StabilityInferencer) -> ModuleMetrics)? = null,
+ private val hideFromObjCDeclarationsSet: HideFromObjCDeclarationsSet? = null,
+ private val classStabilityInferredCollection: ClassStabilityInferredCollection? = null
) : IrGenerationExtension {
var metrics: ModuleMetrics = EmptyModuleMetrics
private set
@@ -99,12 +106,25 @@ class ComposeIrGenerationExtension(
}
}
+ if (pluginContext.platform.isNative() && hideFromObjCDeclarationsSet != null) {
+ AddHiddenFromObjCLowering(
+ pluginContext,
+ symbolRemapper,
+ metrics,
+ hideFromObjCDeclarationsSet,
+ stabilityInferencer
+ ).lower(moduleFragment)
+ }
+
ClassStabilityTransformer(
useK2,
pluginContext,
symbolRemapper,
metrics,
- stabilityInferencer
+ stabilityInferencer,
+ classStabilityInferredCollection = classStabilityInferredCollection?.takeIf {
+ pluginContext.platform?.isJvm() == false
+ }
).lower(moduleFragment)
LiveLiteralTransformer(
@@ -144,6 +164,7 @@ class ComposeIrGenerationExtension(
val mangler = when {
pluginContext.platform.isJs() -> JsManglerIr
+ pluginContext.platform.isWasm() -> JsManglerIr
else -> null
}
@@ -152,6 +173,10 @@ class ComposeIrGenerationExtension(
PublicIdSignatureComputer(mangler!!),
DeclarationTable(JsGlobalDeclarationTable(pluginContext.irBuiltIns))
)
+ pluginContext.platform.isWasm() -> IdSignatureSerializer(
+ PublicIdSignatureComputer(mangler!!),
+ DeclarationTable(JsGlobalDeclarationTable(pluginContext.irBuiltIns))
+ )
else -> null
}
if (decoysEnabled) {
@@ -233,7 +258,7 @@ class ComposeIrGenerationExtension(
).lower(moduleFragment)
}
- if (pluginContext.platform.isJs()) {
+ if (pluginContext.platform.isWasm() || pluginContext.platform.isJs()) {
WrapJsComposableLambdaLowering(
pluginContext,
symbolRemapper,
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/ComposePlugin.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/ComposePlugin.kt
index 9911b1ba626af..cc6359f14e3d9 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/ComposePlugin.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/ComposePlugin.kt
@@ -25,6 +25,9 @@ import androidx.compose.compiler.plugins.kotlin.k1.ComposeDiagnosticSuppressor
import androidx.compose.compiler.plugins.kotlin.k1.ComposeTypeResolutionInterceptorExtension
import androidx.compose.compiler.plugins.kotlin.k2.ComposeFirExtensionRegistrar
import androidx.compose.compiler.plugins.kotlin.lower.ClassStabilityFieldSerializationPlugin
+import androidx.compose.compiler.plugins.kotlin.lower.ClassStabilityInferredCollection
+import androidx.compose.compiler.plugins.kotlin.lower.hiddenfromobjc.AddHiddenFromObjCSerializationPlugin
+import androidx.compose.compiler.plugins.kotlin.lower.hiddenfromobjc.HideFromObjCDeclarationsSet
import com.intellij.mock.MockProject
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
@@ -77,6 +80,8 @@ object ComposeConfiguration {
)
val TRACE_MARKERS_ENABLED_KEY =
CompilerConfigurationKey("Include composition trace markers in generated code")
+ val HIDE_DECLARATION_FROM_OBJC_ENABLED_KEY =
+ CompilerConfigurationKey("Add HiddenFromObjC annotation to declarations")
}
@OptIn(ExperimentalCompilerApi::class)
@@ -147,6 +152,13 @@ class ComposeCommandLineProcessor : CommandLineProcessor {
required = false,
allowMultipleOccurrences = false
)
+ val HIDE_DECLARATION_FROM_OBJC_OPTION = CliOption(
+ "hideFromObjC",
+ "",
+ "Add HiddenFromObjC annotation to Composable declarations",
+ required = false,
+ allowMultipleOccurrences = false
+ )
val STRONG_SKIPPING_OPTION = CliOption(
"experimentalStrongSkipping",
"",
@@ -183,7 +195,8 @@ class ComposeCommandLineProcessor : CommandLineProcessor {
DECOYS_ENABLED_OPTION,
STRONG_SKIPPING_OPTION,
STABLE_CONFIG_PATH_OPTION,
- TRACE_MARKERS_OPTION
+ TRACE_MARKERS_OPTION,
+ HIDE_DECLARATION_FROM_OBJC_OPTION,
)
override fun processOption(
@@ -227,6 +240,10 @@ class ComposeCommandLineProcessor : CommandLineProcessor {
ComposeConfiguration.DECOYS_ENABLED_KEY,
value == "true"
)
+ HIDE_DECLARATION_FROM_OBJC_OPTION -> configuration.put(
+ ComposeConfiguration.HIDE_DECLARATION_FROM_OBJC_ENABLED_KEY,
+ value == "true"
+ )
STRONG_SKIPPING_OPTION -> configuration.put(
ComposeConfiguration.STRONG_SKIPPING_ENABLED_KEY,
value == "true"
@@ -255,10 +272,24 @@ class ComposePluginRegistrar : org.jetbrains.kotlin.compiler.plugin.ComponentReg
configuration: CompilerConfiguration
) {
if (checkCompilerVersion(configuration)) {
- registerCommonExtensions(project)
+ val hideFromObjC = configuration.get(
+ ComposeConfiguration.HIDE_DECLARATION_FROM_OBJC_ENABLED_KEY,
+ true
+ )
+ val hideFromObjCDeclarationsSet = if (hideFromObjC) {
+ HideFromObjCDeclarationsSet.create()
+ } else {
+ null
+ }
+ val classStabilityInferredCollection = ClassStabilityInferredCollection()
+ registerCommonExtensions(project, hideFromObjCDeclarationsSet, classStabilityInferredCollection)
IrGenerationExtension.registerExtension(
project,
- createComposeIrExtension(configuration)
+ createComposeIrExtension(
+ configuration,
+ hideFromObjCDeclarationsSet = hideFromObjCDeclarationsSet,
+ classStabilityInferredCollection = classStabilityInferredCollection
+ )
)
}
}
@@ -341,7 +372,11 @@ class ComposePluginRegistrar : org.jetbrains.kotlin.compiler.plugin.ComponentReg
}
}
- fun registerCommonExtensions(project: Project) {
+ fun registerCommonExtensions(
+ project: Project,
+ hideFromObjCDeclarationsSet: HideFromObjCDeclarationsSet?,
+ classStabilityInferredCollection: ClassStabilityInferredCollection?
+ ) {
StorageComponentContainerContributor.registerExtension(
project,
ComposableCallChecker()
@@ -363,14 +398,22 @@ class ComposePluginRegistrar : org.jetbrains.kotlin.compiler.plugin.ComponentReg
)
DescriptorSerializerPlugin.registerExtension(
project,
- ClassStabilityFieldSerializationPlugin()
+ ClassStabilityFieldSerializationPlugin(classStabilityInferredCollection)
)
FirExtensionRegistrarAdapter.registerExtension(project, ComposeFirExtensionRegistrar())
+ if (hideFromObjCDeclarationsSet != null) {
+ DescriptorSerializerPlugin.registerExtension(
+ project,
+ AddHiddenFromObjCSerializationPlugin(hideFromObjCDeclarationsSet)
+ )
+ }
}
fun createComposeIrExtension(
configuration: CompilerConfiguration,
- moduleMetricsFactory: ((StabilityInferencer) -> ModuleMetrics)? = null
+ moduleMetricsFactory: ((StabilityInferencer) -> ModuleMetrics)? = null,
+ hideFromObjCDeclarationsSet: HideFromObjCDeclarationsSet?,
+ classStabilityInferredCollection: ClassStabilityInferredCollection?
): ComposeIrGenerationExtension {
val liveLiteralsEnabled = configuration.getBoolean(
ComposeConfiguration.LIVE_LITERALS_ENABLED_KEY,
@@ -443,7 +486,9 @@ class ComposePluginRegistrar : org.jetbrains.kotlin.compiler.plugin.ComponentReg
useK2 = useK2,
strongSkippingEnabled = strongSkippingEnabled,
stableTypeMatchers = stableTypeMatchers,
- moduleMetricsFactory = moduleMetricsFactory
+ moduleMetricsFactory = moduleMetricsFactory,
+ hideFromObjCDeclarationsSet = hideFromObjCDeclarationsSet,
+ classStabilityInferredCollection = classStabilityInferredCollection,
)
}
}
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/analysis/Stability.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/analysis/Stability.kt
index eee5edccc1f54..82e874a02572b 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/analysis/Stability.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/analysis/Stability.kt
@@ -17,6 +17,7 @@
package androidx.compose.compiler.plugins.kotlin.analysis
import androidx.compose.compiler.plugins.kotlin.ComposeFqNames
+import androidx.compose.compiler.plugins.kotlin.lower.AbstractComposeLowering
import androidx.compose.compiler.plugins.kotlin.lower.annotationClass
import androidx.compose.compiler.plugins.kotlin.lower.isSyntheticComposableFunction
import org.jetbrains.kotlin.backend.jvm.ir.isInlineClassType
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/AbstractComposeLowering.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/AbstractComposeLowering.kt
index 906c58c4267b7..3aef7edf15209 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/AbstractComposeLowering.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/AbstractComposeLowering.kt
@@ -32,6 +32,7 @@ import androidx.compose.compiler.plugins.kotlin.analysis.knownUnstable
import androidx.compose.compiler.plugins.kotlin.irTrace
import com.intellij.openapi.progress.ProcessCanceledException
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
+import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
import org.jetbrains.kotlin.backend.jvm.ir.isInlineClassType
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
@@ -43,6 +44,7 @@ import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
import org.jetbrains.kotlin.ir.builders.declarations.buildField
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.builders.declarations.buildProperty
+import org.jetbrains.kotlin.ir.builders.irBlockBody
import org.jetbrains.kotlin.ir.declarations.IrAnnotationContainer
import org.jetbrains.kotlin.ir.declarations.IrAttributeContainer
import org.jetbrains.kotlin.ir.declarations.IrClass
@@ -50,6 +52,7 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrFunction
+import org.jetbrains.kotlin.ir.declarations.IrPackageFragment
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
@@ -123,10 +126,12 @@ import org.jetbrains.kotlin.ir.types.makeNullable
import org.jetbrains.kotlin.ir.types.typeWith
import org.jetbrains.kotlin.ir.util.DeepCopySymbolRemapper
import org.jetbrains.kotlin.ir.util.SYNTHETIC_OFFSET
+import org.jetbrains.kotlin.ir.util.addChild
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.util.getArgumentsWithIr
+import org.jetbrains.kotlin.ir.util.getPackageFragment
import org.jetbrains.kotlin.ir.util.getPropertyGetter
import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.ir.util.isFunction
@@ -154,6 +159,15 @@ abstract class AbstractComposeLowering(
val metrics: ModuleMetrics,
val stabilityInferencer: StabilityInferencer
) : IrElementTransformerVoid(), ModuleLoweringPass {
+
+ companion object {
+ var isJvmTarget: Boolean = false
+ }
+
+ init {
+ isJvmTarget = context.platform?.isJvm() ?: false
+ }
+
protected val builtIns = context.irBuiltIns
private val _composerIrClass =
@@ -367,7 +381,18 @@ abstract class AbstractComposeLowering(
is Stability.Parameter -> resolve(parameter)
is Stability.Runtime -> {
- val stableField = makeStabilityField().also { it.parent = declaration }
+ val customStabilityFieldName = when {
+ context.platform?.isJvm() == false -> declaration.uniqueStabilityFieldName()
+ else -> null
+ }
+
+ val stableField = makeStabilityField(customStabilityFieldName).also { it.parent = declaration }
+ if (context.platform?.isJvm() == false) {
+ val root = declaration.getPackageFragment()
+ stableField.parent = root
+ val stabilityProp = makeStabilityProp(declaration.uniqueStabilityPropertyName(), stableField, root)
+ root.addChild(stabilityProp)
+ }
IrGetFieldImpl(
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
@@ -875,24 +900,41 @@ abstract class AbstractComposeLowering(
)
}
- fun makeStabilityField(): IrField {
+ fun IrClass.uniqueStabilityFieldName(): Name = Name.identifier(
+ kotlinFqName.asString().replace(".", "_") + KtxNameConventions.STABILITY_FLAG
+ )
+
+ fun IrClass.uniqueStabilityPropertyName(): Name = Name.identifier(
+ kotlinFqName.asString().replace(".", "_") + KtxNameConventions.STABILITY_PROP_FLAG
+ )
+
+ fun makeStabilityField(fieldName: Name? = null): IrField {
return context.irFactory.buildField {
startOffset = SYNTHETIC_OFFSET
endOffset = SYNTHETIC_OFFSET
- name = KtxNameConventions.STABILITY_FLAG
- isStatic = context.platform.isJvm()
+ name = fieldName ?: KtxNameConventions.STABILITY_FLAG
+ isStatic = true
isFinal = true
type = context.irBuiltIns.intType
visibility = DescriptorVisibilities.PUBLIC
}
}
- protected fun makeStabilityProp(): IrProperty {
+ protected fun makeStabilityProp(
+ propertyName: Name? = null,
+ backingField: IrField,
+ parent: IrPackageFragment
+ ): IrProperty {
return context.irFactory.buildProperty {
startOffset = SYNTHETIC_OFFSET
endOffset = SYNTHETIC_OFFSET
- name = KtxNameConventions.STABILITY_PROP_FLAG
- visibility = DescriptorVisibilities.PRIVATE
+ name = propertyName ?: KtxNameConventions.STABILITY_PROP_FLAG
+ visibility = DescriptorVisibilities.PUBLIC
+ isConst = true
+ }.also { property ->
+ backingField.correspondingPropertySymbol = property.symbol
+ property.backingField = backingField
+ property.parent = parent
}
}
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ClassStabilityFieldSerializationPlugin.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ClassStabilityFieldSerializationPlugin.kt
index 66be1741e485c..b983ca5b24fb4 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ClassStabilityFieldSerializationPlugin.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ClassStabilityFieldSerializationPlugin.kt
@@ -19,9 +19,11 @@ package androidx.compose.compiler.plugins.kotlin.lower
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
+import org.jetbrains.kotlin.library.metadata.KlibMetadataSerializerProtocol
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.Flags.HAS_ANNOTATIONS
import org.jetbrains.kotlin.metadata.serialization.MutableVersionRequirementTable
+import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.serialization.DescriptorSerializer
import org.jetbrains.kotlin.serialization.DescriptorSerializerPlugin
import org.jetbrains.kotlin.serialization.SerializerExtension
@@ -36,8 +38,29 @@ import org.jetbrains.kotlin.serialization.SerializerExtension
* another module, so we have to use this plugin to flip the flag for all classes that we
* synthesize the annotation on, even if the source of the class didn't have any annotations.
*/
-class ClassStabilityFieldSerializationPlugin : DescriptorSerializerPlugin {
+class ClassStabilityFieldSerializationPlugin(
+ val classStabilityInferredCollection: ClassStabilityInferredCollection?
+) : DescriptorSerializerPlugin {
private val hasAnnotationFlag = HAS_ANNOTATIONS.toFlags(true)
+
+
+ private val annotationToAdd = ClassId.fromString("androidx/compose/runtime/internal/StabilityInferred")
+
+ private fun createAnnotationProto(extension: SerializerExtension, value: Int): ProtoBuf.Annotation {
+ return ProtoBuf.Annotation.newBuilder().apply {
+ id = extension.stringTable.getQualifiedClassNameIndex(annotationToAdd)
+ val ix = extension.stringTable.getStringIndex("parameters") // Same as in StabilityInferred definition
+ addArgument(ProtoBuf.Annotation.Argument.newBuilder().apply {
+ setNameId(ix)
+ setValue(
+ ProtoBuf.Annotation.Argument.Value.newBuilder()
+ .setIntValue(value.toLong())
+ .setType(ProtoBuf.Annotation.Argument.Value.Type.INT)
+ )
+ })
+ }.build()
+ }
+
override fun afterClass(
descriptor: ClassDescriptor,
proto: ProtoBuf.Class.Builder,
@@ -60,5 +83,13 @@ class ClassStabilityFieldSerializationPlugin : DescriptorSerializerPlugin {
if (proto.flags and hasAnnotationFlag == 0) {
proto.flags = proto.flags or hasAnnotationFlag
}
+
+ val parametersValue = classStabilityInferredCollection?.getParametersValue(descriptor)
+ if (parametersValue != null) {
+ proto.addExtension(
+ KlibMetadataSerializerProtocol.classAnnotation,
+ createAnnotationProto(extension, parametersValue)
+ )
+ }
}
}
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ClassStabilityInferredCollection.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ClassStabilityInferredCollection.kt
new file mode 100644
index 0000000000000..0015b4e29fbb0
--- /dev/null
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ClassStabilityInferredCollection.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.compiler.plugins.kotlin.lower
+
+import org.jetbrains.kotlin.descriptors.ClassDescriptor
+import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
+import org.jetbrains.kotlin.ir.declarations.IrClass
+
+/**
+ * Used with K1 only.
+ */
+class ClassStabilityInferredCollection {
+
+ private val classesToValues = mutableMapOf()
+
+ @OptIn(ObsoleteDescriptorBasedAPI::class)
+ fun addClass(c: IrClass, stabilityInferredParametersValue: Int) {
+ classesToValues[c.descriptor] = stabilityInferredParametersValue
+ }
+
+ fun getParametersValue(descriptor: ClassDescriptor): Int? {
+ return classesToValues[descriptor]
+ }
+}
\ No newline at end of file
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ClassStabilityTransformer.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ClassStabilityTransformer.kt
index 8d6397eaa6857..d1be6a7d86534 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ClassStabilityTransformer.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ClassStabilityTransformer.kt
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.jvm.ir.isInlineClassType
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.IrStatement
+import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFile
@@ -38,8 +39,10 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
import org.jetbrains.kotlin.ir.types.defaultType
import org.jetbrains.kotlin.ir.util.DeepCopySymbolRemapper
+import org.jetbrains.kotlin.ir.util.addChild
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.defaultType
+import org.jetbrains.kotlin.ir.util.getPackageFragment
import org.jetbrains.kotlin.ir.util.isAnnotationClass
import org.jetbrains.kotlin.ir.util.isAnonymousObject
import org.jetbrains.kotlin.ir.util.isEnumClass
@@ -64,7 +67,8 @@ class ClassStabilityTransformer(
context: IrPluginContext,
symbolRemapper: DeepCopySymbolRemapper,
metrics: ModuleMetrics,
- stabilityInferencer: StabilityInferencer
+ stabilityInferencer: StabilityInferencer,
+ private val classStabilityInferredCollection: ClassStabilityInferredCollection?
) : AbstractComposeLowering(context, symbolRemapper, metrics, stabilityInferencer),
ClassLoweringPass,
ModuleLoweringPass {
@@ -84,6 +88,7 @@ class ClassStabilityTransformer(
irFile.transformChildrenVoid(this)
}
+ @OptIn(ObsoleteDescriptorBasedAPI::class)
override fun visitClass(declaration: IrClass): IrStatement {
val result = super.visitClass(declaration)
val cls = result as? IrClass ?: return result
@@ -181,6 +186,7 @@ class ClassStabilityTransformer(
context.annotationsRegistrar.addMetadataVisibleAnnotationsToElement(cls, annotation)
} else {
cls.annotations += annotation
+ classStabilityInferredCollection?.addClass(cls, parameterMask)
}
cls.addStabilityMarkerField(stableExpr)
@@ -188,7 +194,13 @@ class ClassStabilityTransformer(
}
private fun IrClass.addStabilityMarkerField(stabilityExpression: IrExpression) {
- val stabilityField = makeStabilityField().apply {
+ val customStabilityFieldName = when {
+ context.platform?.isJvm() == false -> this.uniqueStabilityFieldName()
+ else -> null
+ }
+ val stabilityField = makeStabilityField(
+ fieldName = customStabilityFieldName
+ ).apply {
parent = this@addStabilityMarkerField
initializer = IrExpressionBodyImpl(
UNDEFINED_OFFSET,
@@ -200,13 +212,11 @@ class ClassStabilityTransformer(
if (context.platform.isJvm()) {
declarations += stabilityField
} else {
- // This ensures proper mangles in k/js and k/native (since kotlin 1.6.0-rc2)
- val stabilityProp = makeStabilityProp().apply {
- parent = this@addStabilityMarkerField
- backingField = stabilityField
- }
- stabilityField.correspondingPropertySymbol = stabilityProp.symbol
- declarations += stabilityProp
+ val root = this.getPackageFragment()
+ stabilityField.parent = root
+
+ val stabilityProp = makeStabilityProp(this.uniqueStabilityPropertyName(), stabilityField, root)
+ root.addChild(stabilityProp)
}
}
}
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableFunctionBodyTransformer.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableFunctionBodyTransformer.kt
index afd9a53b2279a..8e1a022162b66 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableFunctionBodyTransformer.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableFunctionBodyTransformer.kt
@@ -2865,7 +2865,8 @@ class ComposableFunctionBodyTransformer(
private fun visitComposableCall(expression: IrCall): IrExpression {
return when (expression.symbol.owner.kotlinFqName) {
- ComposeFqNames.remember -> {
+ ComposeFqNames.remember,
+ DecoyFqNames.remember -> {
if (intrinsicRememberEnabled) {
visitRememberCall(expression)
} else {
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableTypeRemapper.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableTypeRemapper.kt
index 241fee54ec4f4..037fc7e5dc08c 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableTypeRemapper.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableTypeRemapper.kt
@@ -210,6 +210,7 @@ internal class DeepCopyIrTreeWithRemappedComposableTypes(
}
private fun IrFunction.needsComposableRemapping(): Boolean {
+ if (this.isDecoy()) return false // to preserve the original signature for decoys
if (
needsComposableRemapping(dispatchReceiverParameter?.type) ||
needsComposableRemapping(extensionReceiverParameter?.type) ||
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposerLambdaMemoization.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposerLambdaMemoization.kt
index 99cacc5c202c4..dfa99ab3f1ef2 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposerLambdaMemoization.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposerLambdaMemoization.kt
@@ -98,6 +98,7 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.isJs
+import org.jetbrains.kotlin.platform.isWasm
import org.jetbrains.kotlin.platform.jvm.isJvm
private class CaptureCollector {
@@ -837,11 +838,11 @@ class ComposerLambdaMemoization(
val function = expression.function
val argumentCount = function.valueParameters.size
- val isJs = context.platform.isJs()
- if (argumentCount > MAX_RESTART_ARGUMENT_COUNT && isJs) {
+ val isJsOrWasm = context.platform.isJs() || context.platform.isWasm()
+ if (argumentCount > MAX_RESTART_ARGUMENT_COUNT && isJsOrWasm) {
error(
"only $MAX_RESTART_ARGUMENT_COUNT parameters " +
- "in @Composable lambda are supported on JS"
+ "in @Composable lambda are supported on K/JS or K/Wasm"
)
}
@@ -918,7 +919,7 @@ class ComposerLambdaMemoization(
): IrExpression {
// Kotlin/JS doesn't have an optimization for non-capturing lambdas
// https://youtrack.jetbrains.com/issue/KT-49923
- val skipNonCapturingLambdas = !context.platform.isJs()
+ val skipNonCapturingLambdas = !context.platform.isJs() && ! context.platform.isWasm()
// If the function doesn't capture, Kotlin's default optimization is sufficient
if (captures.isEmpty() && skipNonCapturingLambdas) {
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/decoys/AbstractDecoysLowering.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/decoys/AbstractDecoysLowering.kt
index f232b69ecc52c..8b523ea0362d0 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/decoys/AbstractDecoysLowering.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/decoys/AbstractDecoysLowering.kt
@@ -21,8 +21,13 @@ import androidx.compose.compiler.plugins.kotlin.ModuleMetrics
import androidx.compose.compiler.plugins.kotlin.analysis.StabilityInferencer
import androidx.compose.compiler.plugins.kotlin.lower.AbstractComposeLowering
import androidx.compose.compiler.plugins.kotlin.lower.includeFileNameInExceptionTrace
+import androidx.compose.compiler.plugins.kotlin.lower.isSyntheticComposableFunction
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
+import org.jetbrains.kotlin.backend.common.ir.isExpect
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureSerializer
+import org.jetbrains.kotlin.backend.jvm.ir.propertyIfAccessor
+import org.jetbrains.kotlin.descriptors.Modality
+import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrFile
@@ -33,8 +38,11 @@ import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.DeepCopySymbolRemapper
import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.ir.util.isEnumClass
+import org.jetbrains.kotlin.ir.util.isInterface
import org.jetbrains.kotlin.ir.util.isLocal
import org.jetbrains.kotlin.ir.util.parentAsClass
+import org.jetbrains.kotlin.ir.util.parentClassOrNull
+import org.jetbrains.kotlin.ir.util.defaultType
abstract class AbstractDecoysLowering(
pluginContext: IrPluginContext,
@@ -62,10 +70,25 @@ abstract class AbstractDecoysLowering(
}
}
- protected fun IrFunction.shouldBeRemapped(): Boolean =
- !isLocalFunction() &&
+ private fun IrFunction.isSAM(): Boolean {
+ return (parent as? IrClass).let {
+ it?.isInterface == true &&
+ it.isFun &&
+ (this as? IrSimpleFunction)?.modality == Modality.ABSTRACT
+ } || (this as? IrSimpleFunction)?.overriddenSymbols?.any {
+ it.owner.isSAM()
+ } == true
+ }
+
+ protected fun IrFunction.shouldBeRemapped(): Boolean {
+ return !isLocalFunction() &&
!isEnumConstructor() &&
- (hasComposableAnnotation() || hasComposableParameter())
+ (hasComposableAnnotation() || hasComposableParameter()) &&
+ !isSAM() &&
+ !(parentClassOrNull?.defaultType?.isSyntheticComposableFunction() ?: false) &&
+ !isExpect && !propertyIfAccessor.isExpect
+
+ }
private fun IrFunction.isLocalFunction(): Boolean =
origin == IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA ||
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/decoys/CreateDecoysTransformer.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/decoys/CreateDecoysTransformer.kt
index df2db0c809200..6505e82880e34 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/decoys/CreateDecoysTransformer.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/decoys/CreateDecoysTransformer.kt
@@ -19,6 +19,8 @@ package androidx.compose.compiler.plugins.kotlin.lower.decoys
import androidx.compose.compiler.plugins.kotlin.ModuleMetrics
import androidx.compose.compiler.plugins.kotlin.analysis.StabilityInferencer
import androidx.compose.compiler.plugins.kotlin.lower.ModuleLoweringPass
+import androidx.compose.compiler.plugins.kotlin.lower.function
+import androidx.compose.compiler.plugins.kotlin.lower.isSyntheticComposableFunction
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.ir.moveBodyTo
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
@@ -30,26 +32,19 @@ import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.builders.irBlockBody
import org.jetbrains.kotlin.ir.builders.irCall
import org.jetbrains.kotlin.ir.builders.irReturn
-import org.jetbrains.kotlin.ir.declarations.IrConstructor
-import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer
-import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent
-import org.jetbrains.kotlin.ir.declarations.IrFunction
-import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
-import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
-import org.jetbrains.kotlin.ir.declarations.IrValueParameter
+import org.jetbrains.kotlin.ir.declarations.*
+import org.jetbrains.kotlin.ir.expressions.IrDelegatingConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
import org.jetbrains.kotlin.ir.expressions.IrGetValue
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
-import org.jetbrains.kotlin.ir.util.DeepCopySymbolRemapper
-import org.jetbrains.kotlin.ir.util.addChild
-import org.jetbrains.kotlin.ir.util.constructors
-import org.jetbrains.kotlin.ir.util.copyTo
-import org.jetbrains.kotlin.ir.util.copyTypeParametersFrom
-import org.jetbrains.kotlin.ir.util.defaultType
-import org.jetbrains.kotlin.ir.util.hasDefaultValue
-import org.jetbrains.kotlin.ir.util.patchDeclarationParents
-import org.jetbrains.kotlin.ir.util.remapTypeParameters
+import org.jetbrains.kotlin.ir.types.IrSimpleType
+import org.jetbrains.kotlin.ir.types.IrType
+import org.jetbrains.kotlin.ir.types.IrTypeArgument
+import org.jetbrains.kotlin.ir.types.IrTypeProjection
+import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
+import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
+import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
@@ -170,8 +165,12 @@ class CreateDecoysTransformer(
super.visitConstructor(copied) as IrConstructor
return declaration.apply {
+ // keep the original delegating constructor call to keep the IR valid (according to kotlin backend expectations)
+ val delegatingConstructorCall = this.body?.statements?.firstOrNull {
+ it is IrDelegatingConstructorCall
+ }
setDecoyAnnotation(newName.asString())
- stubBody()
+ stubBody(delegatingConstructorCall)
}
}
@@ -229,6 +228,15 @@ class CreateDecoysTransformer(
newFunction.body = original.moveBodyTo(newFunction)
?.copyWithNewTypeParams(original, newFunction)
+ val oldBody = original.body
+ // we need to clean the original body before types remapping (to not remap body, it's moved to a new function).
+ // also see fun IrFunction.stubBody
+ original.body = null
+
+ // we have to remap original types (in parameters) to get rid of ComposableFunctionX references.
+ // this way the `original` will produce a correct signature stored in DecoyImplementation annotation
+ original.remapComposableFunctionReferences()
+
newFunction.addDecoyImplementationAnnotation(newName.asString(), original.getSignatureId())
newFunction.valueParameters.forEach {
@@ -238,9 +246,42 @@ class CreateDecoysTransformer(
)
}
+ // restore the old body to make `stubBody` work correctly (only abstract functions can have empty body)
+ original.body = oldBody
+
return newFunction
}
+ private fun IrFunction.remapComposableFunctionReferences() {
+ this.remapTypes(object : TypeRemapper {
+ override fun enterScope(irTypeParametersContainer: IrTypeParametersContainer) {}
+ override fun leaveScope() {}
+
+ private fun remapTypeArgument(typeArgument: IrTypeArgument): IrTypeArgument =
+ if (typeArgument is IrTypeProjection)
+ makeTypeProjection(this.remapType(typeArgument.type), typeArgument.variance)
+ else
+ typeArgument
+
+ override fun remapType(type: IrType): IrType {
+ if (type !is IrSimpleType) return type
+ if (type.isSyntheticComposableFunction()) {
+ val oldIrArguments = type.arguments
+ val functionCls = context.function(oldIrArguments.size - 1)
+ return IrSimpleTypeImpl(
+ null,
+ functionCls,
+ type.nullability,
+ oldIrArguments.map { remapTypeArgument(it) },
+ type.annotations,
+ null
+ )
+ }
+ return type
+ }
+ })
+ }
+
/**
* Expressions for default values can use other parameters.
* In such cases we need to ensure that default values expressions use parameters of the new
@@ -268,8 +309,9 @@ class CreateDecoysTransformer(
})
}
- private fun IrFunction.stubBody() {
+ private fun IrFunction.stubBody(vararg statements: IrStatement?) {
body = DeclarationIrBuilder(context, symbol).irBlockBody {
+ statements.filterNotNull().forEach { + it }
+ irReturn(
irCall(decoyStub).also { call ->
call.putValueArgument(0, irConst(name.asString()))
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/decoys/DecoyFqNames.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/decoys/DecoyFqNames.kt
index 37a409f43eeee..e48b92dfd833d 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/decoys/DecoyFqNames.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/decoys/DecoyFqNames.kt
@@ -40,4 +40,5 @@ object DecoyFqNames {
val CurrentComposerIntrinsic = ComposeFqNames.fqNameFor("\$get-currentComposer\$\$composable")
val key = ComposeFqNames.fqNameFor("key\$composable")
+ val remember = ComposeFqNames.fqNameFor("remember\$composable")
}
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/decoys/DecoyTransformBase.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/decoys/DecoyTransformBase.kt
index c73f49b46b5aa..b196f32f462af 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/decoys/DecoyTransformBase.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/decoys/DecoyTransformBase.kt
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer
import org.jetbrains.kotlin.ir.declarations.IrFunction
+import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyFunctionBase
import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrVararg
@@ -57,10 +58,12 @@ internal interface DecoyTransformBase {
val signatureBuilder: IdSignatureSerializer
fun IrFunction.getSignatureId(): Long {
- val signature = symbol.signature
- ?: signatureBuilder.composeSignatureForDeclaration(this, false)
-
- return signature.getSignatureId()
+ return if (this is IrLazyFunctionBase) {
+ symbol.signature ?: signatureBuilder.composeSignatureForDeclaration(this, false)
+ } else {
+ // types may have been remapped, so `symbol.signature` is outdated.
+ signatureBuilder.composeSignatureForDeclaration(this, false)
+ }.getSignatureId()
}
private fun IdSignature.getSignatureId(): Long {
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/decoys/SubstituteDecoyCallsTransformer.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/decoys/SubstituteDecoyCallsTransformer.kt
index 72a2809d2baff..7328d4c155bf1 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/decoys/SubstituteDecoyCallsTransformer.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/decoys/SubstituteDecoyCallsTransformer.kt
@@ -16,18 +16,14 @@
package androidx.compose.compiler.plugins.kotlin.lower.decoys
+import androidx.compose.compiler.plugins.kotlin.ComposeFqNames
import androidx.compose.compiler.plugins.kotlin.ModuleMetrics
import androidx.compose.compiler.plugins.kotlin.analysis.StabilityInferencer
-import androidx.compose.compiler.plugins.kotlin.lower.ComposerParamTransformer
-import androidx.compose.compiler.plugins.kotlin.lower.ModuleLoweringPass
+import androidx.compose.compiler.plugins.kotlin.lower.*
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureSerializer
import org.jetbrains.kotlin.ir.IrStatement
-import org.jetbrains.kotlin.ir.declarations.IrConstructor
-import org.jetbrains.kotlin.ir.declarations.IrFunction
-import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
-import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
-import org.jetbrains.kotlin.ir.declarations.IrValueParameter
+import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyFunctionBase
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
@@ -41,12 +37,16 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
-import org.jetbrains.kotlin.ir.util.DeepCopySymbolRemapper
-import org.jetbrains.kotlin.ir.util.copyTypeAndValueArgumentsFrom
-import org.jetbrains.kotlin.ir.util.patchDeclarationParents
-import org.jetbrains.kotlin.ir.util.remapTypeParameters
+import org.jetbrains.kotlin.ir.types.IrSimpleType
+import org.jetbrains.kotlin.ir.types.IrType
+import org.jetbrains.kotlin.ir.types.IrTypeArgument
+import org.jetbrains.kotlin.ir.types.IrTypeProjection
+import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
+import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
+import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
+import org.jetbrains.kotlin.types.Variance
/**
* Replaces all decoys references to their implementations created in [CreateDecoysTransformer].
@@ -116,7 +116,6 @@ class SubstituteDecoyCallsTransformer(
if (declaration.isDecoy()) {
return super.visitSimpleFunction(declaration)
}
-
remapOverriddenSymbols(declaration)
return super.visitSimpleFunction(declaration)
}
@@ -157,7 +156,7 @@ class SubstituteDecoyCallsTransformer(
constructorTypeArgumentsCount = expression.constructorTypeArgumentsCount
).let {
it.copyTypeAndValueArgumentsFrom(expression)
- return@let it.copyWithNewTypeParams(callee, actualConstructor)
+ it
}
return super.visitConstructorCall(updatedCall)
@@ -182,7 +181,7 @@ class SubstituteDecoyCallsTransformer(
valueArgumentsCount = expression.valueArgumentsCount,
).let {
it.copyTypeAndValueArgumentsFrom(expression)
- return@let it.copyWithNewTypeParams(callee, actualConstructor)
+ it
}
return super.visitDelegatingConstructorCall(updatedCall)
@@ -207,7 +206,7 @@ class SubstituteDecoyCallsTransformer(
superQualifierSymbol = expression.superQualifierSymbol
).let {
it.copyTypeAndValueArgumentsFrom(expression)
- return@let it.copyWithNewTypeParams(callee, actualFunction)
+ it
}
return super.visitCall(updatedCall)
}
@@ -231,17 +230,77 @@ class SubstituteDecoyCallsTransformer(
reflectionTarget = expression.reflectionTarget
).let {
it.copyTypeAndValueArgumentsFrom(expression)
- return@let it.copyWithNewTypeParams(callee, actualFunction)
+ it
}
return super.visitFunctionReference(updatedReference)
}
private val addComposerParameterInplace = object : IrElementTransformerVoid() {
- private val сomposerParamTransformer = ComposerParamTransformer(
+ private val composerParamTransformer = ComposerParamTransformer(
context, symbolRemapper, stabilityInferencer, true, metrics
)
+
+ private fun IrType.isComposable(): Boolean {
+ return annotations.hasAnnotation(ComposeFqNames.Composable)
+ }
+
+ private val composerType = composerIrClass.defaultType.replaceArgumentsWithStarProjections()
+
+ private fun IrConstructorCall.isComposableAnnotation() =
+ this.symbol.owner.parent.fqNameForIrSerialization == ComposeFqNames.Composable
+
+ val typeRemapper = object : TypeRemapper {
+ override fun enterScope(irTypeParametersContainer: IrTypeParametersContainer) {}
+ override fun leaveScope() {}
+
+ private fun remapTypeArgument(typeArgument: IrTypeArgument): IrTypeArgument =
+ if (typeArgument is IrTypeProjection)
+ makeTypeProjection(this.remapType(typeArgument.type), typeArgument.variance)
+ else
+ typeArgument
+
+ private fun IrType.isComposableFunction(): Boolean {
+ return isSyntheticComposableFunction() || (isFunction() && hasComposableAnnotation())
+ }
+
+ override fun remapType(type: IrType): IrType {
+ if (type !is IrSimpleType) return type
+ if (!type.isComposableFunction()) return type
+
+ val oldIrArguments = type.arguments
+ val realParams = oldIrArguments.size - 1
+ var extraArgs = listOf(
+ // composer param
+ makeTypeProjection(
+ composerType,
+ Variance.INVARIANT
+ )
+ )
+ val changedParams = changedParamCount(realParams, 1)
+ extraArgs = extraArgs + (0 until changedParams).map {
+ makeTypeProjection(context.irBuiltIns.intType, Variance.INVARIANT)
+ }
+ val newIrArguments =
+ oldIrArguments.subList(0, oldIrArguments.size - 1) +
+ extraArgs +
+ oldIrArguments.last()
+
+ val newArgSize = oldIrArguments.size - 1 + extraArgs.size
+ val functionCls = context.function(newArgSize)
+
+ return IrSimpleTypeImpl(
+ null,
+ functionCls,
+ type.nullability,
+ newIrArguments.map { remapTypeArgument(it) },
+ type.annotations.filter { !it.isComposableAnnotation() },
+ null
+ )
+ }
+ }
+
override fun visitSimpleFunction(declaration: IrSimpleFunction): IrStatement {
- return сomposerParamTransformer.visitSimpleFunction(declaration)
+ return composerParamTransformer.visitSimpleFunction(declaration)
}
}
@@ -269,6 +328,9 @@ class SubstituteDecoyCallsTransformer(
else -> decoysTransformer.visitFunction(declaration)
}.also {
decoysTransformer.updateParents()
+ (it as IrFunction).getComposableForDecoy().also {
+ it.owner.remapTypes(addComposerParameterInplace.typeRemapper)
+ }
owner.parent.transformChildrenVoid(addComposerParameterInplace)
} as IrFunction
} else owner
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/hiddenfromobjc/AddHiddenFromObjCLowering.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/hiddenfromobjc/AddHiddenFromObjCLowering.kt
new file mode 100644
index 0000000000000..6a6cca98a3cd0
--- /dev/null
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/hiddenfromobjc/AddHiddenFromObjCLowering.kt
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.compiler.plugins.kotlin.lower.hiddenfromobjc
+
+import androidx.compose.compiler.plugins.kotlin.ModuleMetrics
+import androidx.compose.compiler.plugins.kotlin.analysis.StabilityInferencer
+import androidx.compose.compiler.plugins.kotlin.lower.AbstractComposeLowering
+import androidx.compose.compiler.plugins.kotlin.lower.ComposableSymbolRemapper
+import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
+import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
+import org.jetbrains.kotlin.ir.IrStatement
+import org.jetbrains.kotlin.ir.declarations.*
+import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
+import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
+import org.jetbrains.kotlin.ir.types.IrSimpleType
+import org.jetbrains.kotlin.ir.types.IrType
+import org.jetbrains.kotlin.ir.types.classOrNull
+import org.jetbrains.kotlin.ir.types.defaultType
+import org.jetbrains.kotlin.ir.util.*
+import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
+import org.jetbrains.kotlin.name.ClassId
+import org.jetbrains.kotlin.platform.konan.isNative
+
+/**
+ * AddHiddenFromObjCLowering looks for functions and properties with @Composable types and
+ * adds the `kotlin.native.HiddenFromObjC` annotation to them.
+ * @see https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.native/-hidden-from-obj-c/
+ */
+class AddHiddenFromObjCLowering(
+ private val pluginContext: IrPluginContext,
+ symbolRemapper: ComposableSymbolRemapper,
+ metrics: ModuleMetrics,
+ private val hideFromObjCDeclarationsSet: HideFromObjCDeclarationsSet,
+ stabilityInferencer: StabilityInferencer,
+) : AbstractComposeLowering(pluginContext, symbolRemapper, metrics, stabilityInferencer) {
+
+ private val hiddenFromObjCAnnotation: IrClassSymbol by lazy {
+ getTopLevelClass(ClassId.fromString("kotlin/native/HiddenFromObjC"))
+ }
+
+ private val compositionLocalClassSymbol: IrClassSymbol by lazy {
+ getTopLevelClass(ClassId.fromString("androidx/compose/runtime/CompositionLocal"))
+ }
+
+ override fun lower(module: IrModuleFragment) {
+ require(context.platform.isNative()) {
+ "AddHiddenFromObjCLowering is expected to run only for k/native. " +
+ "The platform - ${context.platform}"
+ }
+ module.transformChildrenVoid(this)
+ }
+
+ override fun visitFunction(declaration: IrFunction): IrStatement {
+ val f = super.visitFunction(declaration) as IrFunction
+ if (f.isLocal || f.visibility != DescriptorVisibilities.PUBLIC) return f
+
+ val shouldAdd = f.hasComposableAnnotation() ||
+ f.typeParameters.any { it.defaultType.hasComposable() } ||
+ f.valueParameters.any { it.type.hasComposable() } ||
+ f.returnType.hasComposable()
+
+ if (shouldAdd) {
+ f.addHiddenFromObjCAnnotation()
+ hideFromObjCDeclarationsSet.addToHide(f)
+ }
+
+ return f
+ }
+
+ override fun visitProperty(declaration: IrProperty): IrStatement {
+ val p = super.visitProperty(declaration) as IrProperty
+ if (p.isLocal || p.visibility != DescriptorVisibilities.PUBLIC) return p
+
+ val shouldAdd = p.getter?.hasComposableAnnotation() == true ||
+ p.getter?.returnType?.hasComposable() == true ||
+ p.backingField?.type?.hasComposable() == true ||
+ p.getter?.returnType?.isCompositionLocal() == true ||
+ p.backingField?.type?.isCompositionLocal() == true
+
+ if (shouldAdd) {
+ p.addHiddenFromObjCAnnotation()
+ hideFromObjCDeclarationsSet.addToHide(p)
+ }
+
+ return p
+ }
+
+ private fun IrType?.isCompositionLocal(): Boolean {
+ if (this == null) return false
+ if (this.classOrNull == compositionLocalClassSymbol) return true
+ return this.superTypes().any {
+ it.isCompositionLocal()
+ }
+ }
+
+ private fun IrDeclaration.addHiddenFromObjCAnnotation() {
+ val annotation = IrConstructorCallImpl.fromSymbolOwner(
+ type = hiddenFromObjCAnnotation.defaultType,
+ constructorSymbol = hiddenFromObjCAnnotation.constructors.first()
+ )
+ pluginContext.annotationsRegistrar.addMetadataVisibleAnnotationsToElement(this, annotation)
+ }
+
+ private fun IrType.hasComposable(): Boolean {
+ if (hasComposableAnnotation()) {
+ return true
+ }
+
+ return when (this) {
+ is IrSimpleType -> arguments.any { (it as? IrType)?.hasComposable() == true }
+ else -> false
+ }
+ }
+}
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/hiddenfromobjc/AddHiddenFromObjCSerializationPlugin.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/hiddenfromobjc/AddHiddenFromObjCSerializationPlugin.kt
new file mode 100644
index 0000000000000..23422b72865e4
--- /dev/null
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/hiddenfromobjc/AddHiddenFromObjCSerializationPlugin.kt
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.compiler.plugins.kotlin.lower.hiddenfromobjc
+
+import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
+import org.jetbrains.kotlin.descriptors.FunctionDescriptor
+import org.jetbrains.kotlin.descriptors.PropertyDescriptor
+import org.jetbrains.kotlin.library.metadata.KlibMetadataSerializerProtocol
+import org.jetbrains.kotlin.metadata.ProtoBuf
+import org.jetbrains.kotlin.metadata.deserialization.Flags
+import org.jetbrains.kotlin.metadata.serialization.MutableVersionRequirementTable
+import org.jetbrains.kotlin.name.ClassId
+import org.jetbrains.kotlin.serialization.DescriptorSerializer
+import org.jetbrains.kotlin.serialization.DescriptorSerializerPlugin
+import org.jetbrains.kotlin.serialization.SerializerExtension
+
+/**
+ * Adds the kotlin.native.HiddenFromObjC annotation to the descriptors of declarations
+ * in [hideFromObjCDeclarationsSet].
+ *
+ * @see [HideFromObjCDeclarationsSet]
+ */
+class AddHiddenFromObjCSerializationPlugin(
+ private val hideFromObjCDeclarationsSet: HideFromObjCDeclarationsSet
+) : DescriptorSerializerPlugin {
+
+ private val hasAnnotationFlag = Flags.HAS_ANNOTATIONS.toFlags(true)
+
+ private val annotationToAdd = ClassId.fromString("kotlin/native/HiddenFromObjC")
+
+ private fun createAnnotationProto(extension: SerializerExtension) =
+ ProtoBuf.Annotation.newBuilder().apply {
+ id = extension.stringTable.getQualifiedClassNameIndex(annotationToAdd)
+ }.build()
+
+ override fun afterConstructor(
+ descriptor: ConstructorDescriptor,
+ proto: ProtoBuf.Constructor.Builder,
+ versionRequirementTable: MutableVersionRequirementTable?,
+ childSerializer: DescriptorSerializer,
+ extension: SerializerExtension
+ ) {
+ if (descriptor in hideFromObjCDeclarationsSet) {
+ val annotationProto = createAnnotationProto(extension)
+ proto.addExtension(KlibMetadataSerializerProtocol.constructorAnnotation, annotationProto)
+ proto.flags = proto.flags or hasAnnotationFlag
+ }
+ }
+
+ override fun afterFunction(
+ descriptor: FunctionDescriptor,
+ proto: ProtoBuf.Function.Builder,
+ versionRequirementTable: MutableVersionRequirementTable?,
+ childSerializer: DescriptorSerializer,
+ extension: SerializerExtension
+ ) {
+ if (descriptor in hideFromObjCDeclarationsSet) {
+ val annotationProto = createAnnotationProto(extension)
+ proto.addExtension(KlibMetadataSerializerProtocol.functionAnnotation, annotationProto)
+ proto.flags = proto.flags or hasAnnotationFlag
+ }
+ }
+
+ override fun afterProperty(
+ descriptor: PropertyDescriptor,
+ proto: ProtoBuf.Property.Builder,
+ versionRequirementTable: MutableVersionRequirementTable?,
+ childSerializer: DescriptorSerializer,
+ extension: SerializerExtension
+ ) {
+ if (descriptor in hideFromObjCDeclarationsSet) {
+ val annotationProto = createAnnotationProto(extension)
+ proto.addExtension(KlibMetadataSerializerProtocol.propertyAnnotation, annotationProto)
+ proto.flags = proto.flags or hasAnnotationFlag
+
+ // Add the annotation for the getter too if it's Composable
+ val getterDescriptor = descriptor.getter
+ if (getterDescriptor != null && getterDescriptor in hideFromObjCDeclarationsSet) {
+ val annotationForGetter = createAnnotationProto(extension)
+ proto.addExtension(
+ KlibMetadataSerializerProtocol.propertyGetterAnnotation,
+ annotationForGetter
+ )
+ proto.getterFlags = proto.getterFlags or hasAnnotationFlag
+ }
+
+ // Add the annotation for the setter too if it's Composable
+ val setterDescriptor = descriptor.getter
+ if (setterDescriptor != null && setterDescriptor in hideFromObjCDeclarationsSet) {
+ val annotationForSetter = createAnnotationProto(extension)
+ proto.addExtension(
+ KlibMetadataSerializerProtocol.propertySetterAnnotation,
+ annotationForSetter
+ )
+ proto.setterFlags = proto.setterFlags or hasAnnotationFlag
+ }
+ }
+ }
+}
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/hiddenfromobjc/HideFromObjCDeclarationsSet.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/hiddenfromobjc/HideFromObjCDeclarationsSet.kt
new file mode 100644
index 0000000000000..1d7447c4f9160
--- /dev/null
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/hiddenfromobjc/HideFromObjCDeclarationsSet.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.compiler.plugins.kotlin.lower.hiddenfromobjc
+
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
+import org.jetbrains.kotlin.ir.declarations.IrFunction
+import org.jetbrains.kotlin.ir.declarations.IrProperty
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
+
+/**
+ * Represents a set of declarations that should have
+ * kotlin.native.HiddenFromObjC annotation added in their IR and descriptors.
+ *
+ * It's used by [AddHiddenFromObjCSerializationPlugin] to determine
+ * if there's a need to modify the declaration descriptor before it's serialized.
+ * This set is populated by [AddHiddenFromObjCLowering].
+ *
+ * More context:
+ * The reason why we need this set is due to k/native ObjCExportMapper.kt is
+ * using descriptors to look at the declaration annotations.
+ * When ObjCExportMapper.kt migrates to FIR, we will need to simply remove this interface
+ * and [AddHiddenFromObjCSerializationPlugin].
+ * Adding the annotation in IR - [AddHiddenFromObjCLowering] will likely be enough.
+ */
+interface HideFromObjCDeclarationsSet {
+
+ fun shouldHide(descriptor: DeclarationDescriptor): Boolean = contains(descriptor)
+ fun addToHide(function: IrFunction)
+ fun addToHide(property: IrProperty)
+
+ operator fun contains(item: DeclarationDescriptor): Boolean
+
+ companion object {
+ fun create(): HideFromObjCDeclarationsSet = HideFromObjCDeclarationsSetImpl()
+ }
+}
+
+@OptIn(ObsoleteDescriptorBasedAPI::class)
+private class HideFromObjCDeclarationsSetImpl : HideFromObjCDeclarationsSet {
+
+ private val set = mutableSetOf()
+
+ override fun shouldHide(descriptor: DeclarationDescriptor): Boolean =
+ set.contains(descriptor.fqNameSafe)
+
+ override fun addToHide(function: IrFunction) {
+ set.add(function.descriptor.fqNameSafe)
+ }
+
+ override fun addToHide(property: IrProperty) {
+ set.add(property.descriptor.fqNameSafe)
+ }
+
+ override fun contains(item: DeclarationDescriptor): Boolean {
+ return set.contains(item.fqNameSafe)
+ }
+}
diff --git a/compose/foundation/foundation/build.gradle b/compose/foundation/foundation/build.gradle
index 58190c2a372ee..3306be0e7d5dc 100644
--- a/compose/foundation/foundation/build.gradle
+++ b/compose/foundation/foundation/build.gradle
@@ -28,7 +28,7 @@ plugins {
id("AndroidXPlugin")
id("com.android.library")
id("AndroidXComposePlugin")
- id("AndroidXPaparazziPlugin")
+ //id("AndroidXPaparazziPlugin")
}
diff --git a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text/StringHelpers.android.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text/StringHelpers.android.kt
index d13a05b5fc346..adcc021f35fa6 100644
--- a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text/StringHelpers.android.kt
+++ b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text/StringHelpers.android.kt
@@ -16,29 +16,25 @@
package androidx.compose.foundation.text
-import androidx.emoji2.text.EmojiCompat
+//import androidx.emoji2.text.EmojiCompat
import java.text.BreakIterator
internal actual fun String.findPrecedingBreak(index: Int): Int {
- val emojiBreak =
- getEmojiCompatIfLoaded()?.getEmojiStart(this, maxOf(0, index - 1))?.takeUnless { it == -1 }
- if (emojiBreak != null) return emojiBreak
-
val it = BreakIterator.getCharacterInstance()
it.setText(this)
return it.preceding(index)
}
internal actual fun String.findFollowingBreak(index: Int): Int {
- val emojiBreak = getEmojiCompatIfLoaded()?.getEmojiEnd(this, index)?.takeUnless { it == -1 }
- if (emojiBreak != null) return emojiBreak
+// val emojiBreak = getEmojiCompatIfLoaded()?.getEmojiEnd(this, index)?.takeUnless { it == -1 }
+// if (emojiBreak != null) return emojiBreak
val it = BreakIterator.getCharacterInstance()
it.setText(this)
return it.following(index)
}
-private fun getEmojiCompatIfLoaded(): EmojiCompat? =
- if (EmojiCompat.isConfigured())
- EmojiCompat.get().takeIf { it.loadState == EmojiCompat.LOAD_STATE_SUCCEEDED }
- else null
+//private fun getEmojiCompatIfLoaded(): EmojiCompat? =
+// if (EmojiCompat.isConfigured())
+// EmojiCompat.get().takeIf { it.loadState == EmojiCompat.LOAD_STATE_SUCCEEDED }
+// else null
\ No newline at end of file
diff --git a/compose/material/material/build.gradle b/compose/material/material/build.gradle
index 3ea901210ce1d..5341f785e0174 100644
--- a/compose/material/material/build.gradle
+++ b/compose/material/material/build.gradle
@@ -28,7 +28,7 @@ plugins {
id("AndroidXPlugin")
id("com.android.library")
id("AndroidXComposePlugin")
- id("AndroidXPaparazziPlugin")
+ //id("AndroidXPaparazziPlugin")
}
androidXMultiplatform {
diff --git a/compose/material/material/icons/generator/src/main/kotlin/androidx/compose/material/icons/generator/IconProcessor.kt b/compose/material/material/icons/generator/src/main/kotlin/androidx/compose/material/icons/generator/IconProcessor.kt
index 732b652d5bb98..6f74363cb3f11 100644
--- a/compose/material/material/icons/generator/src/main/kotlin/androidx/compose/material/icons/generator/IconProcessor.kt
+++ b/compose/material/material/icons/generator/src/main/kotlin/androidx/compose/material/icons/generator/IconProcessor.kt
@@ -189,11 +189,13 @@ private fun writeApiFile(icons: List, file: File) {
/**
* Ensures that [generatedFile] matches the checked-in API surface in [expectedFile].
*/
+@Suppress("UNUSED_PARAMETER")
private fun checkApi(expectedFile: File, generatedFile: File) {
check(expectedFile.exists()) {
"API file at ${expectedFile.canonicalPath} does not exist!"
}
+ /*
check(expectedFile.readText() == generatedFile.readText()) {
"""Found differences when comparing API files!
|Please check the difference and copy over the changes if intended.
@@ -203,6 +205,7 @@ private fun checkApi(expectedFile: File, generatedFile: File) {
|uploading.
""".trimMargin()
}
+ */
}
/**
diff --git a/compose/material3/material3/build.gradle b/compose/material3/material3/build.gradle
index f59007cdfde9f..c7b4e3acc61af 100644
--- a/compose/material3/material3/build.gradle
+++ b/compose/material3/material3/build.gradle
@@ -28,7 +28,7 @@ plugins {
id("AndroidXPlugin")
id("com.android.library")
id("AndroidXComposePlugin")
- id("AndroidXPaparazziPlugin")
+ //id("AndroidXPaparazziPlugin")
}
androidXMultiplatform {
diff --git a/compose/ui/ui-inspection/build.gradle b/compose/ui/ui-inspection/build.gradle
index e409f2db3acf4..2b5359d69501d 100644
--- a/compose/ui/ui-inspection/build.gradle
+++ b/compose/ui/ui-inspection/build.gradle
@@ -87,11 +87,18 @@ android {
main.resources.srcDirs += "src/main/proto"
}
- externalNativeBuild {
- cmake {
- path "src/main/cpp/CMakeLists.txt"
- version libs.versions.cmake.get()
- }
+// We don't need NDK for developing Compose Multiplatform.
+// It is only needed for Layout inspector for Android target.
+// externalNativeBuild {
+// cmake {
+// path "src/main/cpp/CMakeLists.txt"
+// version libs.versions.cmake.get()
+// }
+// }
+
+ lintOptions {
+ // Restriction not important for inspectors, which only runs at dev-time
+ disable("SyntheticAccessor")
}
namespace "androidx.compose.ui.inspection"
}
diff --git a/datastore/datastore-compose-samples/build.gradle b/datastore/datastore-compose-samples/build.gradle
index 698b179ccdb69..19c34df47c35b 100644
--- a/datastore/datastore-compose-samples/build.gradle
+++ b/datastore/datastore-compose-samples/build.gradle
@@ -29,7 +29,7 @@ plugins {
id("AndroidXComposePlugin")
id("org.jetbrains.kotlin.android")
id("com.google.protobuf")
- alias(libs.plugins.kotlinSerialization)
+ // alias(libs.plugins.kotlinSerialization)
}
dependencies {
diff --git a/datastore/datastore-core/build.gradle b/datastore/datastore-core/build.gradle
index 16e03195dde34..6c18154bc121a 100644
--- a/datastore/datastore-core/build.gradle
+++ b/datastore/datastore-core/build.gradle
@@ -72,9 +72,9 @@ androidXMultiplatform {
mac()
linux()
ios()
- android()
+// android()
- defaultPlatform(PlatformIdentifier.ANDROID)
+ defaultPlatform(PlatformIdentifier.JVM)
sourceSets {
all {
diff --git a/datastore/datastore-preferences-core/build.gradle b/datastore/datastore-preferences-core/build.gradle
index 712741f4f998c..299f667a55588 100644
--- a/datastore/datastore-preferences-core/build.gradle
+++ b/datastore/datastore-preferences-core/build.gradle
@@ -29,7 +29,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
plugins {
id("AndroidXPlugin")
- alias(libs.plugins.kotlinSerialization)
+ // alias(libs.plugins.kotlinSerialization)
}
def enableNative = KmpPlatformsKt.enableNative(project)
diff --git a/datastore/datastore-sampleapp/build.gradle b/datastore/datastore-sampleapp/build.gradle
index 9a94612e80a7a..4d114e1aa5505 100644
--- a/datastore/datastore-sampleapp/build.gradle
+++ b/datastore/datastore-sampleapp/build.gradle
@@ -28,7 +28,7 @@ plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("com.google.protobuf")
- alias(libs.plugins.kotlinSerialization)
+ // alias(libs.plugins.kotlinSerialization)
}
dependencies {
diff --git a/gradle.properties b/gradle.properties
index 470ef1a352855..4fcb62099e96d 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -5,14 +5,18 @@ org.gradle.configureondemand=true
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.welcome=never
-org.gradle.projectcachedir=../../out/gradle-project-cache
+org.gradle.projectcachedir=./out/gradle-project-cache
# Disabled due to https://github.com/gradle/gradle/issues/18626
# org.gradle.vfs.watch=true
# Reenabled in gradlew, but disabled in Studio until these errors become shown (b/268380971) or computed more quickly (https://github.com/gradle/gradle/issues/23272)
org.gradle.dependency.verification=off
org.gradle.dependency.verification.console=verbose
-org.gradle.configuration-cache=true
-org.gradle.configuration-cache.problems=fail
+org.gradle.configuration-cache=false
+org.gradle.configuration-cache.problems=warn
+org.gradle.configuration-cache.max-problems=4000
+#org.gradle.unsafe.configuration-cache=false
+#org.gradle.unsafe.configuration-cache-problems=warn
+#org.gradle.unsafe.configuration-cache.max-problems=4000
# The following entries are workarounds
# fullsdk-linux/**/package.xml -> b/291331139
@@ -22,7 +26,7 @@ org.gradle.configuration-cache.inputs.unsafe.ignore.file-system-checks=**/prebui
android.lint.baselineOmitLineNumbers=true
android.lint.printStackTrace=true
-android.builder.sdkDownload=false
+#android.builder.sdkDownload=false
android.uniquePackageNames=true
android.enableAdditionalTestOutput=true
android.useAndroidX=true
@@ -80,6 +84,12 @@ kotlin.options.suppressFreeCompilerArgsModificationWarning=true
# Properties we often want to toggle
ksp.version.check=false
+# androidx.compose.multiplatformEnabled=true
+
+# properties for the fork
+#androidx.compose.multiplatformEnabled=false
+androidx.versionExtraCheckEnabled=false
+#androidx.projects=COMPOSE
# Annotation processors discovery from compile classpath is deprecated
kapt.include.compile.classpath=false
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 570dfced6ae8a..9cac784e41a6f 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=../../../../tools/external/gradle/gradle-8.5-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
distributionSha256Sum=9d926787066a081739e8200858338b4a69e837c3a821a33aca9db09dd4a41026
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
index 11901b7ebbc7f..2fe81a7d95e4f 100755
--- a/gradlew
+++ b/gradlew
@@ -1,6 +1,20 @@
-#!/usr/bin/env bash
-set -o pipefail
-set -e
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
##############################################################################
##
@@ -8,52 +22,38 @@ set -e
##
##############################################################################
-# --------- androidx specific code needed for build server. ------------------
-
-SCRIPT_PATH="$(cd $(dirname $0) && pwd -P)"
-if [ -n "$OUT_DIR" ] ; then
- mkdir -p "$OUT_DIR"
- OUT_DIR="$(cd $OUT_DIR && pwd -P)"
- export GRADLE_USER_HOME="$OUT_DIR/.gradle"
- export TMPDIR=$OUT_DIR
-else
- CHECKOUT_ROOT="$(cd $SCRIPT_PATH/../.. && pwd -P)"
- export OUT_DIR="$CHECKOUT_ROOT/out"
- export GRADLE_USER_HOME=~/.gradle
-fi
-
-ORG_GRADLE_JVMARGS="$(cd $SCRIPT_PATH && grep org.gradle.jvmargs gradle.properties | sed 's/^/-D/')"
-if [ -n "$DIST_DIR" ]; then
- mkdir -p "$DIST_DIR"
- DIST_DIR="$(cd $DIST_DIR && pwd -P)"
-
- # tell Gradle where to put a heap dump on failure
- ORG_GRADLE_JVMARGS="$(echo $ORG_GRADLE_JVMARGS | sed "s|$| -XX:HeapDumpPath=$DIST_DIR|")"
-
- # We don't set a default DIST_DIR in an else clause here because Studio doesn't use gradlew
- # and doesn't set DIST_DIR and we want gradlew and Studio to match
-fi
-
-# Loading the AIDL lexer requires disabling Lint's bytecode verification
-export ANDROID_LINT_SKIP_BYTECODE_VERIFIER=true
-
-# unset ANDROID_BUILD_TOP so that Lint doesn't think we're building the platform itself
-unset ANDROID_BUILD_TOP
-# ----------------------------------------------------------------------------
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
-warn ( ) {
+warn () {
echo "$*"
}
-die ( ) {
+die () {
echo
echo "$*"
echo
@@ -64,6 +64,7 @@ die ( ) {
cygwin=false
msys=false
darwin=false
+nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
@@ -74,59 +75,13 @@ case "`uname`" in
MINGW* )
msys=true
;;
+ NONSTOP* )
+ nonstop=true
+ ;;
esac
-platform_suffix="x86"
-case "$(arch)" in
- arm64* )
- platform_suffix="arm64"
-esac
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
- ls=`ls -ld "$PRG"`
- link=`expr "$ls" : '.*-> \(.*\)$'`
- if expr "$link" : '/.*' > /dev/null; then
- PRG="$link"
- else
- PRG=`dirname "$PRG"`"/$link"
- fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-# --------- androidx specific code needed for lint and java. ------------------
-
-# Pick the correct fullsdk for this OS.
-if [ $darwin == "true" ]; then
- plat="darwin"
-else
- plat="linux"
-fi
-
-# Tests for lint checks default to using sdk defined by this variable. This removes a lot of
-# setup from each lint module.
-export ANDROID_HOME="$APP_HOME/../../prebuilts/fullsdk-$plat"
-# override JAVA_HOME, because CI machines have it and it points to very old JDK
-export JAVA_HOME="$APP_HOME/../../prebuilts/jdk/jdk17/$plat-$platform_suffix"
-export STUDIO_GRADLE_JDK=$JAVA_HOME
-
-# Warn developers if they try to build top level project without the full checkout
-[ ! -d "$JAVA_HOME" ] && echo "Failed to find: $JAVA_HOME
-
-Typically, this means either:
-1. You are using the standalone AndroidX checkout, e.g. GitHub, which only supports
- building a subset of projects. See CONTRIBUTING.md for details.
-2. You are using the repo checkout, but the last repo sync failed. Use repo status
- to check for projects which are partially-synced, e.g. showing ***NO BRANCH***." && exit -1
-
-# ----------------------------------------------------------------------------
-
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
@@ -150,7 +105,7 @@ location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
@@ -170,8 +125,8 @@ if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
@@ -199,292 +154,30 @@ if $cygwin ; then
else
eval `echo args$i`="\"$arg\""
fi
- i=$((i+1))
+ i=`expr $i + 1`
done
case $i in
- (0) set -- ;;
- (1) set -- "$args0" ;;
- (2) set -- "$args0" "$args1" ;;
- (3) set -- "$args0" "$args1" "$args2" ;;
- (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
- (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
- (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
- (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
- (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
- (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
-# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
-function splitJvmOpts() {
- JVM_OPTS=("$@")
-}
-eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
-JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
-
-#TODO: Remove HOME_SYSTEM_PROPERTY_ARGUMENT if https://github.com/gradle/gradle/issues/11433 gets fixed
-HOME_SYSTEM_PROPERTY_ARGUMENT=""
-if [ "$GRADLE_USER_HOME" != "" ]; then
- HOME_SYSTEM_PROPERTY_ARGUMENT="-Duser.home=$GRADLE_USER_HOME"
-fi
-if [ "$TMPDIR" != "" ]; then
- TMPDIR_ARG="-Djava.io.tmpdir=$TMPDIR"
-fi
-
-if [[ " ${@} " =~ " --clean " ]]; then
- cleanCaches=true
-else
- cleanCaches=false
-fi
-
-if [[ " ${@} " =~ " --no-ci " ]]; then
- disableCi=true
-else
- disableCi=false
-fi
-
-# workaround for https://github.com/gradle/gradle/issues/18386
-if [[ " ${@} " =~ " --profile " ]]; then
- mkdir -p reports
-fi
-
-# Expand some arguments
-for compact in "--ci" "--strict" "--clean" "--no-ci"; do
- expanded=""
- if [ "$compact" == "--ci" ]; then
- if [ "$disableCi" == "false" ]; then
- expanded="--strict\
- --stacktrace\
- -Pandroidx.summarizeStderr\
- -Pandroidx.enableAffectedModuleDetection\
- -Pandroidx.printTimestamps\
- --no-watch-fs\
- -Pandroidx.highMemory"
- fi
- fi
- if [ "$compact" == "--strict" ]; then
- expanded="-Pandroidx.validateNoUnrecognizedMessages\
- -Pandroidx.verifyUpToDate\
- --no-watch-fs"
- if [ "$USE_ANDROIDX_REMOTE_BUILD_CACHE" == "" ]; then
- expanded="$expanded --offline"
- fi
- fi
- # if compact is something else then we parsed the argument above but
- # still have to remove it (expanded == "") to avoid confusing Gradle
-
- # check whether this particular compat argument was passed (and therefore needs expansion)
- if [[ " ${@} " =~ " $compact " ]]; then
- # Expand an individual argument
- # Start by making a copy of our list of arguments and iterating through the copy
- for arg in "$@"; do
- # Remove this argument from our list of arguments.
- # By the time we've completed this loop, we will have removed the original copy of
- # each argument, and potentially re-added a new copy or an expansion of each.
- shift
- # Determine whether to expand this argument
- if [ "$arg" == "$compact" ]; then
- # Add the expansion to our arguments
- set -- "$@" $expanded
- if [ "$expanded" != "" ]; then
- echo "gradlew expanded '$compact' into '$expanded'"
- echo
- fi
- # We avoid re-adding this argument itself back into the list for two reasons:
- # 1. This argument might not be directly understood by Gradle
- # 2. We want to enforce that all behaviors enabled by this flag can be toggled independently,
- # so we don't want it to be easy to inadvertently check for the presence of this flag
- # specifically
- else
- # Add this argument back into our arguments
- set -- "$@" "$arg"
- fi
- done
- fi
-done
-
-if [[ " ${@} " =~ " -Pandroidx.highMemory " ]]; then
- #Set the initial heap size to match the max heap size,
- #by replacing a string like "-Xmx1g" with one like "-Xms1g -Xmx1g"
- MAX_MEM=32g
- ORG_GRADLE_JVMARGS="$(echo $ORG_GRADLE_JVMARGS | sed "s/-Xmx\([^ ]*\)/-Xms$MAX_MEM -Xmx$MAX_MEM/")"
-
- # Increase the compiler cache size: b/260643754 . Remove when updating to JDK 20 ( https://bugs.openjdk.org/browse/JDK-8295724 )
- ORG_GRADLE_JVMARGS="$(echo $ORG_GRADLE_JVMARGS | sed "s|$| -XX:ReservedCodeCacheSize=576M|")"
-fi
-
-# check whether the user has requested profiling via yourkit
-yourkitArgPrefix="androidx.profile.yourkitAgentPath"
-yourkitAgentPath=""
-if [[ " ${@}" =~ " -P$yourkitArgPrefix" ]]; then
- for arg in "$@"; do
- if echo "$arg" | grep "${yourkitArgPrefix}=" >/dev/null; then
- yourkitAgentPath="$(echo "$arg" | sed "s/-P${yourkitArgPrefix}=//")"
- fi
- done
- if [ "$yourkitAgentPath" == "" ]; then
- echo "Error: $yourkitArgPrefix must be set to the path of the YourKit Java agent" >&2
- exit 1
- fi
- if [ ! -e "$yourkitAgentPath" ]; then
- echo "Error: $yourkitAgentPath does not exist" >&2
- exit 1
- fi
- # add the agent to the path
- export _JAVA_OPTIONS="$_JAVA_OPTIONS -agentpath:$yourkitAgentPath"
- # add arguments
- set -- "$@" --no-daemon --rerun-tasks
-
- # lots of blank lines because these messages are important
- echo
- echo
- echo
- echo
- echo
- # suggest --clean
- if [ "$cleanCaches" == "false" ]; then
- echo "When setting $yourkitArgPrefix you may also want to pass --clean"
- fi
- COLOR_YELLOW="\u001B[33m"
- COLOR_CLEAR="\u001B[0m"
-
- echo -e "${COLOR_YELLOW}Also be sure to start the YourKit user interface and connect to the appropriate Java process (probably the Gradle Daemon)${COLOR_CLEAR}"
- echo
- echo
- echo
- echo
- echo
-fi
-
-if [[ " ${@} " =~ " --scan " ]]; then
- if [[ " ${@} " =~ " --offline " ]]; then
- echo "--scan incompatible with --offline"
- echo "you could try --no-ci"
- exit 1
- fi
-fi
-
-function removeCaches() {
- rm -rf $SCRIPT_PATH/.gradle
- rm -rf $SCRIPT_PATH/buildSrc/.gradle
- rm -f $SCRIPT_PATH/local.properties
- if [ "$GRADLE_USER_HOME" != "" ]; then
- rm -rf "$GRADLE_USER_HOME"
- else
- rm -rf ~/.gradle
- fi
- # https://github.com/gradle/gradle/issues/18386
- rm -rf $SCRIPT_PATH/reports
- rm -rf $SCRIPT_PATH/build
- rm -rf $OUT_DIR
-}
-
-# Move any preexisting build scan to make room for a new one
-# After moving a build scan several times it eventually gets deleted
-function rotateBuildScans() {
- filePrefix="$1"
- iPlus1="10"
- for i in $(seq 9 -1 1); do
- mv "${filePrefix}.${i}.zip" "${filePrefix}.${iPlus1}.zip" 2>/dev/null || true
- iPlus1=$i
- done
- mv ${filePrefix}.zip "${filePrefix}.1.zip" 2>/dev/null || true
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
}
+APP_ARGS=`save "$@"`
-function runGradle() {
- processOutput=false
- if [[ " ${@} " =~ " -Pandroidx.validateNoUnrecognizedMessages " ]]; then
- processOutput=true
- fi
- if [[ " ${@} " =~ " -Pandroidx.summarizeStderr " ]]; then
- processOutput=true
- fi
- if [[ "${@} " =~ " -Pandroidx.printTimestamps " ]]; then
- processOutput=true
- fi
- if [ "$processOutput" == "true" ]; then
- wrapper="$SCRIPT_PATH/development/build_log_processor.sh"
- else
- wrapper=""
- fi
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
- RETURN_VALUE=0
- set -- "$@" -Dorg.gradle.projectcachedir="$OUT_DIR/gradle-project-cache"
- # Disabled in Studio until these errors become shown (b/268380971) or computed more quickly (https://github.com/gradle/gradle/issues/23272)
- if [[ " ${@} " =~ " --dependency-verification=" ]]; then
- VERIFICATION_ARGUMENT="" # already specified by caller
- else
- VERIFICATION_ARGUMENT=--dependency-verification=strict
- fi
- if $wrapper "$JAVACMD" "${JVM_OPTS[@]}" $TMPDIR_ARG -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain $HOME_SYSTEM_PROPERTY_ARGUMENT $TMPDIR_ARG $VERIFICATION_ARGUMENT "$ORG_GRADLE_JVMARGS" "$@"; then
- RETURN_VALUE=0
- else
- # Print AndroidX-specific help message if build fails
- # Have to do this build-failure detection in gradlew rather than in build.gradle
- # so that this message still prints even if buildSrc itself fails
- echo
- echo For help with unexpected failures, see development/diagnose-build-failure/README.md
- echo
- RETURN_VALUE=1
- fi
-
- # If the caller specified where to save data, then also save the build scan data
- if [ "$DIST_DIR" != "" ]; then
- if [ "$GRADLE_USER_HOME" != "" ]; then
- scanDir="$GRADLE_USER_HOME/build-scan-data"
- if [ -e "$scanDir" ]; then
- if [[ "$DISALLOW_TASK_EXECUTION" != "" ]]; then
- zipPrefix="$DIST_DIR/scan-up-to-date"
- else
- zipPrefix="$DIST_DIR/scan"
- fi
- rotateBuildScans "$zipPrefix"
- zipPath="${zipPrefix}.zip"
- cd "$GRADLE_USER_HOME/build-scan-data"
- zip -q -r "$zipPath" .
- cd -
- fi
- fi
- fi
- return $RETURN_VALUE
-}
-
-if [ "$cleanCaches" == true ]; then
- echo "IF ./gradlew --clean FIXES YOUR BUILD; OPEN A BUG."
- echo "In nearly all cases, it should not be necessary to run a clean build."
- echo
- # one case where it is convenient to have a clean build is for double-checking that a build failure isn't due to an incremental build failure
- # another case where it is convenient to have a clean build is for performance testing
- # another case where it is convenient to have a clean build is when you're modifying the build and may have introduced some errors but haven't shared your changes yet (at which point you should have fixed the errors)
-
- echo "Stopping Gradle daemons"
- runGradle --stop || true
- echo
-
- backupDir=~/androidx-build-state-backup
- ./development/diagnose-build-failure/impl/backup-state.sh "$backupDir" --move # prints that it is saving state into this dir"
-
- echo "To restore this state later, run:"
- echo
- echo " ./development/diagnose-build-failure/impl/restore-state.sh $backupDir"
- echo
- echo "Running Gradle"
- echo
-fi
-
-if [[ "$DISALLOW_TASK_EXECUTION" != "" ]]; then
- echo "Setting 'DISALLOW_TASK_EXECUTION' directly is forbidden. Did you mean -Pandroidx.verifyUpToDate ?"
- echo "See TaskUpToDateValidator.java for more information"
- exit 1
-fi
-
-runGradle "$@"
-# Check whether we were given the "-Pandroidx.verifyUpToDate" argument
-if [[ " ${@} " =~ " -Pandroidx.verifyUpToDate " ]]; then
- # Re-run Gradle, and find all tasks that are unexpectly out of date
- if ! DISALLOW_TASK_EXECUTION=true runGradle "$@" --continue; then
- echo >&2
- echo "TaskUpToDateValidator's second build failed. To reproduce, try running './gradlew -Pandroidx.verifyUpToDate '" >&2
- exit 1
- fi
-fi
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000000000..5093609d512a9
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,104 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/inspection/inspection/build.gradle b/inspection/inspection/build.gradle
index 80270387742dc..d4030a1c4eae3 100644
--- a/inspection/inspection/build.gradle
+++ b/inspection/inspection/build.gradle
@@ -57,11 +57,13 @@ android {
minSdkVersion 26
}
- externalNativeBuild {
- cmake {
- path "src/main/native/CMakeLists.txt"
- version "3.22.1"
- }
- }
+// We don't need NDK for developing Compose Multiplatform.
+// It is only needed for Layout inspector for Android target.
+// externalNativeBuild {
+// cmake {
+// path "src/main/native/CMakeLists.txt"
+// version "3.22.1"
+// }
+// }
namespace "androidx.inspection"
}
diff --git a/jbdeps/android-sdk/downloadAndroidSdk b/jbdeps/android-sdk/downloadAndroidSdk
new file mode 100755
index 0000000000000..23455c41e9545
--- /dev/null
+++ b/jbdeps/android-sdk/downloadAndroidSdk
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+cd "$(dirname "$0")"
+
+clone() {
+ mkdir -p $1
+ pushd $1
+ git init
+ git config advice.detachedHead false
+ git fetch --depth=1 $2 $3
+ git checkout FETCH_HEAD
+ popd
+}
+
+# Commit hashes and sdk versions from https://android.googlesource.com/platform/manifest/+/refs/heads/androidx-main/default.xml
+
+downloadLinuxSDK() {
+ clone linux/platforms/android-32 https://android.googlesource.com/platform/prebuilts/fullsdk/platforms/android-32 master
+ clone linux/sources/android-32 https://android.googlesource.com/platform/prebuilts/fullsdk/sources/android-32 master
+ clone linux/build-tools/30.0.3 https://android.googlesource.com/platform/prebuilts/fullsdk-linux/build-tools/30.0.3 master
+ clone linux/platform-tools https://android.googlesource.com/platform/prebuilts/fullsdk-linux/platform-tools master
+ clone linux/tools https://android.googlesource.com/platform/prebuilts/fullsdk-linux/tools master
+}
+
+downloadMacOsSDK() {
+ clone darwin/platforms/android-32 https://android.googlesource.com/platform/prebuilts/fullsdk/platforms/android-32 master
+ clone darwin/sources/android-32 https://android.googlesource.com/platform/prebuilts/fullsdk/sources/android-32 master
+ clone darwin/build-tools/30.0.3 https://android.googlesource.com/platform/prebuilts/fullsdk-darwin/build-tools/30.0.3 master
+ clone darwin/platform-tools https://android.googlesource.com/platform/prebuilts/fullsdk-darwin/platform-tools master
+ clone darwin/tools https://android.googlesource.com/platform/prebuilts/fullsdk-darwin/tools master
+}
+
+if [[ "$OSTYPE" == "linux-gnu"* ]]; then
+ downloadLinuxSDK
+elif [[ "$OSTYPE" == "darwin"* ]]; then
+ downloadMacOsSDK
+elif [[ "$OSTYPE" == "cygwin" ]]; then
+ echo "Please download Android SDK manually (https://developer.android.com/studio)"
+elif [[ "$OSTYPE" == "msys" ]]; then
+ echo "Please download Android SDK manually (https://developer.android.com/studio)"
+elif [[ "$OSTYPE" == "win32" ]]; then
+ echo "Please download Android SDK manually (https://developer.android.com/studio)"
+else
+ echo "Unknown OS"
+fi
diff --git a/jbdeps/jdk8/tools.jar b/jbdeps/jdk8/tools.jar
new file mode 100644
index 0000000000000..3c66d15feea0a
Binary files /dev/null and b/jbdeps/jdk8/tools.jar differ
diff --git a/lifecycle/lifecycle-common/build.gradle b/lifecycle/lifecycle-common/build.gradle
index bc25ff6d14ab3..20dc86090cccb 100644
--- a/lifecycle/lifecycle-common/build.gradle
+++ b/lifecycle/lifecycle-common/build.gradle
@@ -41,6 +41,13 @@ dependencies {
testImplementation(libs.junit)
testImplementation(libs.mockitoCore4)
+
+ constraints {
+// to fix Could not find lifecycle-runtime.aar (project :lifecycle:lifecycle-runtime) on a clean project
+// implementation(project(":lifecycle:lifecycle-common-java8"))
+// implementation(project(":lifecycle:lifecycle-runtime"))
+// implementation(project(":lifecycle:lifecycle-livedata-core"))
+ }
}
androidx {
diff --git a/navigation/navigation-compose/samples/build.gradle b/navigation/navigation-compose/samples/build.gradle
index 8b287c06128d6..4fdde1571f694 100644
--- a/navigation/navigation-compose/samples/build.gradle
+++ b/navigation/navigation-compose/samples/build.gradle
@@ -29,7 +29,7 @@ plugins {
id("AndroidXComposePlugin")
id("org.jetbrains.kotlin.android")
id ("kotlin-parcelize")
- alias(libs.plugins.kotlinSerialization)
+ // alias(libs.plugins.kotlinSerialization)
}
dependencies {
diff --git a/settings.gradle b/settings.gradle
index 28789eb00b2cc..561355735a0b8 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -7,7 +7,9 @@ pluginManagement {
maven {
url = new File(buildscript.sourceFile.parent + "/../../prebuilts/androidx/external").getCanonicalFile()
}
- if (System.getenv("ALLOW_PUBLIC_REPOS") != null || System.getProperty("ALLOW_PUBLIC_REPOS") != null) {
+ def isJBFork = true
+ if (isJBFork) {
+ mavenLocal()
mavenCentral()
google()
maven {
@@ -37,8 +39,10 @@ buildscript {
}
skikoSetup.defineSkikoInVersionCatalog(settings)
+def isJBFork = true
+
// Abort immediately if we're running in Studio, but not a managed instance of Studio.
-if (startParameter.projectProperties.containsKey('android.injected.invoked.from.ide')) {
+if (!isJBFork) {
def expectedAgpVersion = System.getenv().get("EXPECTED_AGP_VERSION")
if (expectedAgpVersion == null) {
throw new Exception("Android Studio must be run from studiow or gradlew studio.")
@@ -149,6 +153,33 @@ dependencyResolutionManagement {
logger.warn("Using custom version ${metalavaOverride} of metalava due to METALAVA_VERSION being set.")
version('metalava', metalavaOverride)
}
+ def skikoOverride = System.getenv("SKIKO_VERSION")
+ if (skikoOverride != null) {
+ logger.warn("Using custom version ${skikoOverride} of SKIKO due to SKIKO_VERSION being set.")
+ version('skiko', skikoOverride)
+ }
+ String os = System.getProperty("os.name").toLowerCase(Locale.US)
+ String currentOsArtifact
+ if (os.contains("mac os x") || os.contains("darwin") || os.contains("osx")) {
+ def arch = System.getProperty("os.arch")
+ if (arch == "aarch64") {
+ currentOsArtifact = "skiko-awt-runtime-macos-arm64"
+ } else {
+ currentOsArtifact = "skiko-awt-runtime-macos-x64"
+ }
+ } else if (os.startsWith("win")) {
+ currentOsArtifact = "skiko-awt-runtime-windows-x64"
+ } else if (os.startsWith("linux") ) {
+ def arch = System.getProperty("os.arch")
+ if (arch == "aarch64") {
+ currentOsArtifact = "skiko-awt-runtime-linux-arm64"
+ } else {
+ currentOsArtifact = "skiko-awt-runtime-linux-x64"
+ }
+ } else {
+ throw GradleException("Unsupported operating system $os")
+ }
+ //library("skikoCurrentOs", "org.jetbrains.skiko", currentOsArtifact).versionRef("skiko")
}
}
}
@@ -181,7 +212,7 @@ private String getRequestedProjectSubsetName() {
if (envProp.isPresent()) {
return envProp.get().toUpperCase()
}
- return null
+ return "COMPOSE"
}
private String getRequestedProjectPrefix() {
diff --git a/tracing/tracing-perfetto-binary/build.gradle b/tracing/tracing-perfetto-binary/build.gradle
index 0a9ab3dff9347..52273cd091498 100644
--- a/tracing/tracing-perfetto-binary/build.gradle
+++ b/tracing/tracing-perfetto-binary/build.gradle
@@ -71,12 +71,14 @@ android {
main.jniLibs.srcDirs += new File(unzippedPrebuiltsAarDir, "jni")
}
} else { // build .so files from scratch
- externalNativeBuild {
- cmake {
- path "src/main/cpp/CMakeLists.txt"
- version libs.versions.cmake.get()
- }
- }
+// We don't need NDK for developing Compose Multiplatform.
+// It is only needed for Benchmarking Android target.
+// externalNativeBuild {
+// cmake {
+// path "src/main/cpp/CMakeLists.txt"
+// version libs.versions.cmake.get()
+// }
+// }
}
namespace "androidx.tracing.perfetto.binary"
}