mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Move .cxx
directory out of android/app
(#166277)
This is a build artifact, so move to `build/app/intermediates/flutter`. See/ fixes https://github.com/flutter/flutter/issues/160372 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md --------- Co-authored-by: Gray Mackall <mackall@google.com>
This commit is contained in:
parent
9ce60b743d
commit
f539bb4471
@ -152,6 +152,27 @@ Future<void> main() async {
|
|||||||
throw TaskResult.failure("Shared library doesn't exist");
|
throw TaskResult.failure("Shared library doesn't exist");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
section('AGP cxx build artifacts');
|
||||||
|
|
||||||
|
final String defaultPath = path.join(project.rootPath, 'android', 'app', '.cxx');
|
||||||
|
|
||||||
|
final String modifiedPath = path.join(
|
||||||
|
project.rootPath,
|
||||||
|
'build',
|
||||||
|
'app',
|
||||||
|
'intermediates',
|
||||||
|
'flutter',
|
||||||
|
'.cxx',
|
||||||
|
);
|
||||||
|
if (Directory(defaultPath).existsSync()) {
|
||||||
|
throw TaskResult.failure('Producing unexpected build artifacts in $defaultPath');
|
||||||
|
}
|
||||||
|
if (!Directory(modifiedPath).existsSync()) {
|
||||||
|
throw TaskResult.failure(
|
||||||
|
'Not producing external native build output directory in $modifiedPath',
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return TaskResult.success(null);
|
return TaskResult.success(null);
|
||||||
|
@ -610,6 +610,23 @@ object FlutterPluginUtils {
|
|||||||
"$flutterSdkRootPath/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt"
|
"$flutterSdkRootPath/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// AGP defaults to outputting build artifacts in `android/app/.cxx`. This directory is a
|
||||||
|
// build artifact, so we move it from that directory to within Flutter's build directory
|
||||||
|
// to avoid polluting source directories with build artifacts.
|
||||||
|
//
|
||||||
|
// AGP explicitely recommends not setting the buildStagingDirectory to be within a build
|
||||||
|
// directory in
|
||||||
|
// https://developer.android.com/reference/tools/gradle-api/8.3/null/com/android/build/api/dsl/Cmake#buildStagingDirectory(kotlin.Any),
|
||||||
|
// but as we are not actually building anything (and are instead only tricking AGP into
|
||||||
|
// downloading the NDK), it is acceptable for the buildStagingDirectory to be removed
|
||||||
|
// and rebuilt when running clean builds.
|
||||||
|
gradleProjectAndroidExtension.externalNativeBuild.cmake.buildStagingDirectory(
|
||||||
|
gradleProject.layout.buildDirectory
|
||||||
|
.dir("${FlutterPluginConstants.INTERMEDIATES_DIR}/flutter/.cxx")
|
||||||
|
.get()
|
||||||
|
.asFile.path
|
||||||
|
)
|
||||||
|
|
||||||
// CMake will print warnings when you try to build an empty project.
|
// CMake will print warnings when you try to build an empty project.
|
||||||
// These arguments silence the warnings - our project is intentionally
|
// These arguments silence the warnings - our project is intentionally
|
||||||
// empty.
|
// empty.
|
||||||
|
@ -22,6 +22,8 @@ import org.gradle.api.Project
|
|||||||
import org.gradle.api.Task
|
import org.gradle.api.Task
|
||||||
import org.gradle.api.UnknownTaskException
|
import org.gradle.api.UnknownTaskException
|
||||||
import org.gradle.api.artifacts.dsl.DependencyHandler
|
import org.gradle.api.artifacts.dsl.DependencyHandler
|
||||||
|
import org.gradle.api.file.Directory
|
||||||
|
import org.gradle.api.file.DirectoryProperty
|
||||||
import org.gradle.api.logging.Logger
|
import org.gradle.api.logging.Logger
|
||||||
import org.gradle.api.tasks.TaskContainer
|
import org.gradle.api.tasks.TaskContainer
|
||||||
import org.gradle.api.tasks.TaskProvider
|
import org.gradle.api.tasks.TaskProvider
|
||||||
@ -845,6 +847,8 @@ class FlutterPluginUtilsTest {
|
|||||||
val project = mockk<Project>()
|
val project = mockk<Project>()
|
||||||
val mockCmakeOptions = mockk<CmakeOptions>()
|
val mockCmakeOptions = mockk<CmakeOptions>()
|
||||||
val mockDefaultConfig = mockk<DefaultConfig>()
|
val mockDefaultConfig = mockk<DefaultConfig>()
|
||||||
|
val mockDirectoryProperty = mockk<DirectoryProperty>()
|
||||||
|
val mockDirectory = mockk<Directory>()
|
||||||
every {
|
every {
|
||||||
project.extensions
|
project.extensions
|
||||||
.findByType(BaseExtension::class.java)!!
|
.findByType(BaseExtension::class.java)!!
|
||||||
@ -852,17 +856,24 @@ class FlutterPluginUtilsTest {
|
|||||||
} returns mockCmakeOptions
|
} returns mockCmakeOptions
|
||||||
every { project.extensions.findByType(BaseExtension::class.java)!!.defaultConfig } returns mockDefaultConfig
|
every { project.extensions.findByType(BaseExtension::class.java)!!.defaultConfig } returns mockDefaultConfig
|
||||||
|
|
||||||
|
val basePath = "/base/path"
|
||||||
|
val fakeBuildPath = "/randomapp/build/app/"
|
||||||
every { mockCmakeOptions.path } returns null
|
every { mockCmakeOptions.path } returns null
|
||||||
every { mockCmakeOptions.path(any()) } returns Unit
|
every { mockCmakeOptions.path(any()) } returns Unit
|
||||||
every { mockDefaultConfig.externalNativeBuild.cmake.arguments(any(), any()) } returns Unit
|
every { mockDefaultConfig.externalNativeBuild.cmake.arguments(any(), any()) } returns Unit
|
||||||
|
every { mockCmakeOptions.buildStagingDirectory(any()) } returns Unit
|
||||||
|
every { project.layout.buildDirectory } returns mockDirectoryProperty
|
||||||
|
every { mockDirectoryProperty.dir(any<String>()) } returns mockDirectoryProperty
|
||||||
|
every { mockDirectoryProperty.get() } returns mockDirectory
|
||||||
|
every { mockDirectory.asFile.path } returns fakeBuildPath
|
||||||
|
|
||||||
val basePath = "/base/path"
|
|
||||||
FlutterPluginUtils.forceNdkDownload(project, basePath)
|
FlutterPluginUtils.forceNdkDownload(project, basePath)
|
||||||
|
|
||||||
verify(exactly = 1) {
|
verify(exactly = 1) {
|
||||||
mockCmakeOptions.path
|
mockCmakeOptions.path
|
||||||
}
|
}
|
||||||
verify(exactly = 1) { mockCmakeOptions.path("$basePath/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt") }
|
verify(exactly = 1) { mockCmakeOptions.path("$basePath/packages/flutter_tools/gradle/src/main/groovy/CMakeLists.txt") }
|
||||||
|
verify(exactly = 1) { mockCmakeOptions.buildStagingDirectory(any()) }
|
||||||
verify(exactly = 1) {
|
verify(exactly = 1) {
|
||||||
mockDefaultConfig.externalNativeBuild.cmake.arguments(
|
mockDefaultConfig.externalNativeBuild.cmake.arguments(
|
||||||
"-Wno-dev",
|
"-Wno-dev",
|
||||||
@ -1276,11 +1287,18 @@ class FlutterPluginUtilsTest {
|
|||||||
every { tasks } returns
|
every { tasks } returns
|
||||||
mockk<TaskContainer> {
|
mockk<TaskContainer> {
|
||||||
val registerTaskNameSlot = slot<String>()
|
val registerTaskNameSlot = slot<String>()
|
||||||
every { register(capture(registerTaskNameSlot), capture(registerTaskSlot)) } answers registerAnswer@{
|
every {
|
||||||
|
register(
|
||||||
|
capture(registerTaskNameSlot),
|
||||||
|
capture(registerTaskSlot)
|
||||||
|
)
|
||||||
|
} answers registerAnswer@{
|
||||||
val mockRegisterTask =
|
val mockRegisterTask =
|
||||||
mockk<Task> {
|
mockk<Task> {
|
||||||
every { name } returns registerTaskNameSlot.captured
|
every { name } returns registerTaskNameSlot.captured
|
||||||
every { description = capture(descriptionSlot) } returns Unit
|
every {
|
||||||
|
description = capture(descriptionSlot)
|
||||||
|
} returns Unit
|
||||||
every { dependsOn(any<ProcessAndroidResources>()) } returns mockk()
|
every { dependsOn(any<ProcessAndroidResources>()) } returns mockk()
|
||||||
val doLastActionSlot = slot<Action<Task>>()
|
val doLastActionSlot = slot<Action<Task>>()
|
||||||
every { doLast(capture(doLastActionSlot)) } answers doLastAnswer@{
|
every { doLast(capture(doLastActionSlot)) } answers doLastAnswer@{
|
||||||
@ -1302,7 +1320,8 @@ class FlutterPluginUtilsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
variants.forEach { variant ->
|
variants.forEach { variant ->
|
||||||
val testOutputs: DomainObjectCollection<BaseVariantOutput> = mockk<DomainObjectCollection<BaseVariantOutput>>()
|
val testOutputs: DomainObjectCollection<BaseVariantOutput> =
|
||||||
|
mockk<DomainObjectCollection<BaseVariantOutput>>()
|
||||||
val baseVariantSlot = slot<Action<BaseVariantOutput>>()
|
val baseVariantSlot = slot<Action<BaseVariantOutput>>()
|
||||||
val baseVariantOutput = mockk<BaseVariantOutput>()
|
val baseVariantOutput = mockk<BaseVariantOutput>()
|
||||||
// Create a real file in a temp directory.
|
// Create a real file in a temp directory.
|
||||||
@ -1313,7 +1332,9 @@ class FlutterPluginUtilsTest {
|
|||||||
manifest.writeText(manifestText)
|
manifest.writeText(manifestText)
|
||||||
val mockProcessResourcesProvider = mockk<TaskProvider<ProcessAndroidResources>>()
|
val mockProcessResourcesProvider = mockk<TaskProvider<ProcessAndroidResources>>()
|
||||||
val mockProcessResources = mockk<ProcessAndroidResources>()
|
val mockProcessResources = mockk<ProcessAndroidResources>()
|
||||||
every { mockProcessResourcesProvider.hint(ProcessAndroidResources::class).get() } returns mockProcessResources
|
every {
|
||||||
|
mockProcessResourcesProvider.hint(ProcessAndroidResources::class).get()
|
||||||
|
} returns mockProcessResources
|
||||||
every { baseVariantOutput.processResourcesProvider } returns mockProcessResourcesProvider
|
every { baseVariantOutput.processResourcesProvider } returns mockProcessResourcesProvider
|
||||||
// Fallback processing.
|
// Fallback processing.
|
||||||
every { mockProcessResources.manifestFile } returns manifest
|
every { mockProcessResources.manifestFile } returns manifest
|
||||||
@ -1336,7 +1357,10 @@ class FlutterPluginUtilsTest {
|
|||||||
assert(descriptionSlot.captured.contains("stores app links settings for the given build variant"))
|
assert(descriptionSlot.captured.contains("stores app links settings for the given build variant"))
|
||||||
assertEquals(variants.size, registerTaskList.size)
|
assertEquals(variants.size, registerTaskList.size)
|
||||||
for (i in 0 until variants.size) {
|
for (i in 0 until variants.size) {
|
||||||
assertEquals("output${FlutterPluginUtils.capitalize(variants[i].name)}AppLinkSettings", registerTaskList[i].name)
|
assertEquals(
|
||||||
|
"output${FlutterPluginUtils.capitalize(variants[i].name)}AppLinkSettings",
|
||||||
|
registerTaskList[i].name
|
||||||
|
)
|
||||||
verify(exactly = 1) { registerTaskList[i].dependsOn(any<ProcessAndroidResources>()) }
|
verify(exactly = 1) { registerTaskList[i].dependsOn(any<ProcessAndroidResources>()) }
|
||||||
}
|
}
|
||||||
// Output assertions are minimal which ensures code is running but is not exhaustive testing.
|
// Output assertions are minimal which ensures code is running but is not exhaustive testing.
|
||||||
|
Loading…
Reference in New Issue
Block a user