-
Notifications
You must be signed in to change notification settings - Fork 5
build!: upgrade Android Gradle Plugin to 9.3.1, compileSdk to 36 and use Java 17 #35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -15,7 +15,7 @@ buildscript { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| google() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dependencies { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| classpath 'com.android.tools.build:gradle:7.4.2' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| classpath 'com.android.tools.build:gradle:9.3.1' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -109,9 +109,9 @@ ext { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| keyAliasToUse = "notset" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| keyPassToUse = "notset" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| compileSdk = 33 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| compileSdk = 36 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| minSdk = 24 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| targetSdk = 33 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| targetSdk = 36 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Load values from properties passed to the project, such as via gradle.properties in the user's home .gradle dir | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (project.hasProperty("signingKeystore")) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -132,15 +132,16 @@ ext { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| android { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| namespace 'com.miloshpetrov.sol2.android' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| compileSdkVersion(project.ext.compileSdk) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Make it clear we're compiling for Java 8 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| compileOptions { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Backport some Java 8 APIs like java.time for gestalt | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| coreLibraryDesugaringEnabled true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sourceCompatibility JavaVersion.VERSION_1_8 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| targetCompatibility JavaVersion.VERSION_1_8 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sourceCompatibility JavaVersion.VERSION_17 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| targetCompatibility JavaVersion.VERSION_17 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
138
to
+144
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win Update the stale comment. The comment states Java 8. The code sets Java 17. 📝 Proposed comment fix- // Make it clear we're compiling for Java 8
+ // Make it clear we're compiling for Java 17
compileOptions {
// Backport some Java 8 APIs like java.time for gestalt
coreLibraryDesugaringEnabled true📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sourceSets { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -244,85 +245,72 @@ def deleteDir(File dir) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dir.delete() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tasks.register('modulesJar') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rootProject.destinationSolModules().each { module -> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| modulesJar.dependsOn ":modules:$module.name" + ":jar" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| abstract class PropertyBasedSync extends Sync { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @OutputDirectory | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| abstract DirectoryProperty getOutputDirectory() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tasks.register('exportModules') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| inputs.dir("$rootDir/engine/src/main/resources/") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (module in rootProject.destinationSolModules()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def moduleClassesDir = "${rootProject.projectDir}/modules/${module.name}/build/classes" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def assetsDir = "${rootProject.projectDir}/modules/${module.name}/assets" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (file(moduleClassesDir).exists()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| inputs.dir(moduleClassesDir) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| inputs.dir(assetsDir) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| File getDestinationDir() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return outputDirectory.get().asFile | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| outputs.dir("$projectDir/assets/modules") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dependsOn modulesJar | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| doLast { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dexModules() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Clear the modules directory to ensure that it is up-to date | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def assetsModulesDir = new File("$projectDir/assets", "modules") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| deleteDir(assetsModulesDir) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assetsModulesDir.mkdir() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| void setDestinationDir(File destination) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| outputDirectory.set(destination) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Delete the engine module symlink, since you cannot create a new symlink when one already exists. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def engineModuleDir = new File("$projectDir/assets", "engine") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| deleteDir(engineModuleDir) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| abstract class PropertyBasedGenericTask extends DefaultTask { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @OutputDirectory | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| abstract DirectoryProperty getOutputDirectory() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| boolean canCreateSymlinks | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| androidComponents { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| boolean canCreateSymlinks = false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def tempDir = layout.buildDirectory.dir('tmp').get() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tempDir.asFile.mkdir() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def testSymlink = tempDir.file('test_symlink').asFile | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Files.createSymbolicLink(testSymlink.toPath(), Paths.get("$rootDir/engine/build/resources/main/org/destinationsol")) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| testSymlink.delete() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| canCreateSymlinks = true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (Exception ignore) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Copy the files instead | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| canCreateSymlinks = false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+269
to
+281
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win Make the symlink probe robust. Three problems can force the copy fallback on systems that support symlinks:
The probe also performs file I/O during configuration. That work runs on every build and breaks configuration-cache reuse guarantees. 🛠️ Proposed probe fix try {
def tempDir = layout.buildDirectory.dir('tmp').get()
- tempDir.asFile.mkdir()
+ tempDir.asFile.mkdirs()
def testSymlink = tempDir.file('test_symlink').asFile
- Files.createSymbolicLink(testSymlink.toPath(), Paths.get("$rootDir/engine/build/resources/main/org/destinationsol"))
- testSymlink.delete()
+ Files.deleteIfExists(testSymlink.toPath())
+ Files.createSymbolicLink(testSymlink.toPath(), tempDir.asFile.toPath())
+ Files.deleteIfExists(testSymlink.toPath())
canCreateSymlinks = true
} catch (Exception ignore) {🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Files.createSymbolicLink(Paths.get("$projectDir/assets/engine"), Paths.get("$rootDir/engine/build/resources/main/org/destinationsol")) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| canCreateSymlinks = true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (Exception ignore) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Copy the files instead | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| canCreateSymlinks = false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def exportEngineModuleByCopy = tasks.register('exportModuleEngineByCopy', PropertyBasedSync) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dependsOn ":engine:processResources" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from "$rootDir/engine/build/resources/main/org/destinationsol" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| include "assets/**" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| include "module.json" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| includeEmptyDirs = false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| eachFile { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| relativePath = relativePath.prepend("engine") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (canCreateSymlinks) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rootProject.destinationSolModules().each { module -> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| file("$projectDir/assets/modules/${module.name}").mkdir() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| file("$projectDir/assets/modules/${module.name}/build/classes").mkdirs() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ["assets", "overrides", "deltas", "module.json", "build/dexes"].each { path -> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def sourcePath = "$rootDir/modules/${module.name}/$path" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (file(sourcePath).exists()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Files.createSymbolicLink(Paths.get("$projectDir/assets/modules/${module.name}/$path"), Paths.get(sourcePath)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| copy { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from "$rootDir/engine/build/resources/main/org/destinationsol" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| into "$projectDir/assets/engine" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| include "assets/**" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| include "module.json" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| include "reflections.cache" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| copy { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| into "$projectDir/assets/modules" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from("$rootDir/modules") { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rootProject.destinationSolModules().each { module -> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| include "${module.name}/module.json" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| include "${module.name}/assets/**" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| include "${module.name}/overrides/**" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| include "${module.name}/deltas/**" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| include "${module.name}/build/dexes/*.jar" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def exportEngineModuleBySymlink = tasks.register('exportModuleEngineBySymlink', PropertyBasedGenericTask) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dependsOn ":engine:processResources" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| doLast { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| outputDirectory.dir('engine').get().asFile.mkdir() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ["assets", "overrides", "deltas", "module.json"].each { symlinkPath -> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def sourcePath = "$rootDir/engine/build/resources/main/org/destinationsol/$symlinkPath" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (file(sourcePath).exists()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def destinationPath = outputDirectory.dir('engine').get().dir(symlinkPath).asFile.toPath() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (Files.exists(destinationPath)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Files.delete(destinationPath) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Files.createSymbolicLink(destinationPath, Paths.get(sourcePath)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+295
to
306
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win Handle existing entries without following symlinks. Both export paths use 📍 Affects 1 file
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def dexModules() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onVariants(selector().all(), { variant -> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| variant.sources.assets.addGeneratedSourceDirectory(canCreateSymlinks ? exportEngineModuleBySymlink : exportEngineModuleByCopy, canCreateSymlinks ? PropertyBasedGenericTask::getOutputDirectory : PropertyBasedSync::getOutputDirectory) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+310
to
+312
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win 🧩 Analysis chain🌐 Web query:
💡 Result: The Android Gradle Plugin (AGP) does not have a specific configuration option in Citations:
🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- build.gradle relevant sections ---'
sed -n '240,440p' build.gradle
printf '%s\n' '--- Gradle and AGP declarations ---'
rg -n "distributionUrl|com.android|android-gradle|addGeneratedSourceDirectory|canCreateSymlinks|PropertyBased(GenericTask|Sync)|exportEngineModule" \
. --glob 'gradle-wrapper.properties' --glob 'settings.gradle*' --glob 'build.gradle*' --glob 'gradle.properties'
printf '%s\n' '--- task and output references ---'
rg -n "class (PropertyBasedGenericTask|PropertyBasedSync)|fileTree\\(|moduleClassesDir|outputs\\.(dir|file)|destinationDirectory|preserve|Files\\.(exists|createSymbolicLink|readSymbolicLink)" build.gradleRepository: MovingBlocks/DestSolAndroid Length of output: 12440 🏁 Script executed: #!/bin/bash
set -eu
sed -n '240,440p' build.gradle
printf '\n--- declarations and references ---\n'
rg -n "distributionUrl|com.android|android-gradle|addGeneratedSourceDirectory|canCreateSymlinks|PropertyBased(GenericTask|Sync)|exportEngineModule|fileTree\\(|moduleClassesDir|outputs\\.(dir|file)|destinationDirectory|preserve|Files\\.(exists|createSymbolicLink|readSymbolicLink)" \
. --glob 'gradle-wrapper.properties' --glob 'settings.gradle*' --glob 'build.gradle*' --glob 'gradle.properties' build.gradleRepository: MovingBlocks/DestSolAndroid Length of output: 15761 🌐 Web query:
💡 Result: In Gradle, when symbolic links are used as task inputs, the behavior depends on the operating system's capabilities [1][2]. For operating systems that support symbolic links, Gradle adds the content of the link's destination as the task input, rather than the link itself [1][3]. If the operating system does not support symbolic links, the actual symbolic link file is treated as the input [1][4]. Because Gradle captures the destination content for inputs on supported systems, symbolic links are not stored directly in the build cache, and this can impact cache reusability—particularly when building across different operating systems like Windows and Linux, where symlink support varies [1][2]. Additionally, note the following regarding symlinks in Gradle: - File system watching, an optimization for build speed, does not support symbolic links for project files and directories [5]. - For standard file operations, such as deleting files via the project DSL, symlinks are generally not followed by default unless explicitly configured [6][7]. - Changes to the availability of a symlink—such as modifying a broken symlink to point to a valid file—are detected by Gradle's up-to-date checking mechanism [8][9]. For consistent behavior in build caching across different environments, it is recommended that symbolic links not be checked into version control [1][4]. Citations:
🌐 Web query:
💡 Result: The MergeSourceSetFolders task is an internal Android Gradle Plugin (AGP) component responsible for aggregating assets from various source sets (such as main, build types, and product flavors) and dependencies into a single directory for the final application package [1][2][3]. While Gradle itself is generally capable of handling symlinks in file trees, the MergeSourceSetFolders task and the underlying asset merging logic in AGP may not always behave consistently when encountering symlinked asset directories. Specifically: 1. Task Nature: MergeSourceSetFolders is an incremental task that scans input source folders to compute the final list of assets [1][2]. It treats these inputs as file sets [1]. 2. Symlink Compatibility: The behavior regarding symlinks depends on how the underlying Java/Kotlin file system APIs (used within the asset merger) resolve the paths and whether the task's incremental build caching mechanism explicitly supports them [1][2]. In many cases, if a directory is symlinked, the asset merger may resolve it to its canonical path or fail to track changes correctly if the symlink target changes but the symlink itself remains constant. 3. Recommendations: If you need to include assets that reside outside the standard source set structure, it is generally safer and more reliable to use Gradle's source set configuration to explicitly include those directories rather than relying on filesystem-level symlinks. You can add external folders to your assets in your build.gradle file: android { sourceSets { main { assets.srcDirs += files('/path/to/your/external/assets') } } } This approach ensures the build system is fully aware of the asset locations, maintaining proper incremental build support and avoiding issues with how MergeSourceSetFolders processes filesystem metadata [1][2]. Citations:
Track symlink targets and test asset packaging. 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def path = androidSdkPath() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def dexCommand = System.getProperty("os.name").toLowerCase().contains("windows") ? "d8.bat" : "d8" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def buildToolsVersions = new File(path, "build-tools").listFiles(new FileFilter() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -340,51 +328,110 @@ def dexModules() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (buildToolsVersions.length == 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw new TaskExecutionException(exportModules, new FileNotFoundException("An Android SDK build tools version >= $compileSdk could not be found.")) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def dex = "${buildToolsVersions[0]}/$dexCommand" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (module in rootProject.destinationSolModules()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def moduleClassesDir = file("${rootProject.projectDir}/modules/${module.name}/build/classes/") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def moduleClassesFiles = fileTree(moduleClassesDir).filter { it.isFile() && it.name.endsWith('.class')}.files | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def classesRootPath = moduleClassesDir.toPath() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def moduleClasses = [] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (file in moduleClassesFiles) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| moduleClasses.add(classesRootPath.relativize(file.toPath())) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (moduleClasses.size() == 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // The dexed code jars are only produced for code-bearing modules. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| continue; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rootProject.destinationSolModules().each { module -> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def moduleBuildDir = file("${rootProject.projectDir}/modules/${module.name}/build") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def moduleClassesDir = file("$moduleBuildDir/classes/") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def moduleDexesDir = "${rootProject.projectDir}/modules/${module.name}/build/dexes/" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mkdir(moduleDexesDir) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def jarOutputPath = "$moduleDexesDir/${module.name}.jar" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exec { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| workingDir moduleClassesDir | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| commandLine (["$dex"] + moduleClasses + ['--classpath', "$rootDir/engine/build/classes", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| '--lib', "$path/platforms/android-$compileSdk/android.jar", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| '--min-api', "$minSdk", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| '--output', "$jarOutputPath"]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def codePresent = !fileTree("${rootProject.projectDir}/modules/${module.name}/src/").isEmpty() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TaskProvider<Task> thisModuleDexes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TaskProvider<Task> thisDexedModuleJar | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (codePresent) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| thisModuleDexes = tasks.register("moduleDexes$module.name", Exec) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dependsOn ":modules:$module.name:classes" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| outputs.dir("$moduleDexesDir") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def dex = "${buildToolsVersions[0]}/$dexCommand" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def moduleClassesFiles = fileTree(moduleClassesDir).filter { it.isFile() && it.name.endsWith('.class') }.files | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def classesRootPath = moduleClassesDir.toPath() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def moduleClasses = [] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (file in moduleClassesFiles) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| moduleClasses.add(classesRootPath.relativize(file.toPath())) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| workingDir moduleClassesDir | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| commandLine(["$dex"] + moduleClasses + ['--classpath', "$rootDir/engine/build/classes", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| '--lib', "$path/platforms/android-$compileSdk/android.jar", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| '--min-api', "$minSdk", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| '--output', "$moduleDexesDir"] as List<String>) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+340
to
+356
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🔴 Critical | 🏗️ Heavy lift The dex command line is built during configuration, so it misses the compiled classes.
The task also declares no inputs. Gradle cannot detect changed sources, so it reports up to date after the first run. Build the argument list at execution time and declare the classes directory as an input. 🐛 Proposed fix thisModuleDexes = tasks.register("moduleDexes$module.name", Exec) {
dependsOn ":modules:$module.name:classes"
+ inputs.dir(moduleClassesDir).withPropertyName('moduleClasses').skipWhenEmpty()
outputs.dir("$moduleDexesDir")
def dex = "${buildToolsVersions[0]}/$dexCommand"
- def moduleClassesFiles = fileTree(moduleClassesDir).filter { it.isFile() && it.name.endsWith('.class') }.files
def classesRootPath = moduleClassesDir.toPath()
- def moduleClasses = []
- for (file in moduleClassesFiles) {
- moduleClasses.add(classesRootPath.relativize(file.toPath()))
- }
-
workingDir moduleClassesDir
- commandLine(["$dex"] + moduleClasses + ['--classpath', "$rootDir/engine/build/classes",
- '--lib', "$path/platforms/android-$compileSdk/android.jar",
- '--min-api', "$minSdk",
- '--output', "$moduleDexesDir"] as List<String>)
+ executable "$dex"
+ argumentProviders.add({ ->
+ def moduleClasses = fileTree(moduleClassesDir)
+ .filter { it.isFile() && it.name.endsWith('.class') }
+ .files
+ .collect { classesRootPath.relativize(it.toPath()).toString() }
+ moduleClasses + ['--classpath', "$rootDir/engine/build/classes",
+ '--lib', "$path/platforms/android-$compileSdk/android.jar",
+ '--min-api', "$minSdk",
+ '--output', "$moduleDexesDir"]
+ } as CommandLineArgumentProvider)
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| thisDexedModuleJar = tasks.register("dexedModuleJar$module.name", Zip) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def outputDir = layout.buildDirectory.dir("moduleAssetRoots/$module.name/assets/modules/$module.name/build/dexes/") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| outputs.dir(outputDir) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dependsOn thisModuleDexes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from("${rootProject.projectDir}/modules/${module.name}/build/dexes/") { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| include "**/*.dex" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from("$moduleBuildDir/classes/") { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exclude 'assets/**' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exclude 'dexes/**' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exclude '**/*.class' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| destinationDirectory = outputDir | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| archiveFileName = "${module.name}.jar" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def exportModulesByCopy = tasks.register("exportModule${module.name}ByCopy", PropertyBasedSync) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (codePresent) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dependsOn thisDexedModuleJar | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from("$rootDir/") { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| include "modules/$module.name/module.json" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| include "modules/$module.name/assets/**" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| include "modules/$module.name/overrides/**" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| include "modules/$module.name/deltas/**" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from(layout.buildDirectory.dir("moduleAssetRoots/$module.name/assets/")) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| include "modules/$module.name/build/dexes/${module.name}.jar" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| into("modules/$module.name/") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| preserve { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| include "build/dexes/**" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+374
to
391
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🔴 Critical | 🏗️ Heavy lift
The path layout is also wrong.
🐛 Proposed layout fix from(layout.buildDirectory.dir("moduleAssetRoots/$module.name/assets/")) {
include "modules/$module.name/build/dexes/${module.name}.jar"
}
- into("modules/$module.name/")
preserve {
- include "build/dexes/**"
+ include "modules/$module.name/build/dexes/**"
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| FileSystem jarFileSystem | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jarFileSystem = FileSystems.newFileSystem(URI.create("jar:" + new File(jarOutputPath).toURI()), new HashMap<String, Object>()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fileTree(moduleClassesDir).filter { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| it.isFile() && !it.name.endsWith(".class") && !it.path.startsWith("assets/") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }.each { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def destinationPath = jarFileSystem.getPath("/${moduleClassesDir.relativePath(it)}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Files.createDirectories(destinationPath.parent) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Files.copy(it.toPath(), destinationPath) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def exportModulesBySymlink = tasks.register("exportModule${module.name}BySymlink", PropertyBasedGenericTask) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (codePresent) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dependsOn thisDexedModuleJar | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (Exception e) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| e.printStackTrace() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } finally { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (jarFileSystem != null) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jarFileSystem.close() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| doLast { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def moduleRoot = outputDirectory.file("modules/${module.name}").get().asFile | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| moduleRoot.mkdirs() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ["assets", "overrides", "deltas", "module.json"].each { symlinkPath -> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def sourcePath = "$rootDir/modules/${module.name}/$symlinkPath" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (file(sourcePath).exists()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def destinationPath = moduleRoot.toPath().resolve(symlinkPath) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (Files.exists(destinationPath)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (Files.readSymbolicLink(destinationPath) == Paths.get(sourcePath)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Files.delete(destinationPath) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Files.createSymbolicLink(destinationPath, Paths.get(sourcePath)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (codePresent) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def codeJarPath = moduleRoot.toPath().resolve("build/dexes/${module.name}.jar") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def codeJarSourcePath = layout.buildDirectory.dir("moduleAssetRoots/$module.name/assets/modules/$module.name/build/dexes/").get().file("${module.name}.jar").asFile.toPath() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (Files.exists(codeJarPath)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (Files.readSymbolicLink(codeJarPath) == codeJarSourcePath) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Files.delete(codeJarPath) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| codeJarPath.toFile().parentFile.mkdirs() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Files.createSymbolicLink(codeJarPath, codeJarSourcePath) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onVariants(selector().all(), { variant -> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| variant.sources.assets.addGeneratedSourceDirectory(canCreateSymlinks ? exportModulesBySymlink : exportModulesByCopy, canCreateSymlinks ? PropertyBasedGenericTask::getOutputDirectory : PropertyBasedSync::getOutputDirectory) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| preBuild.dependsOn(exportModules) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def androidSdkPath() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def path | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def localProperties = project.file("../local.properties") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
Repository: MovingBlocks/DestSolAndroid
Length of output: 545
🏁 Script executed:
Repository: MovingBlocks/DestSolAndroid
Length of output: 3386
🌐 Web query:
Android Gradle Plugin 9.3.1 release notes legacy DSL compileSdkVersion lintOptions packagingOptions RenderScript Gradle requirement💡 Result:
Android Gradle Plugin (AGP) 9.3.1 is a version within the 9.3 stable release cycle [1]. Key information regarding your query is synthesized below: Gradle Requirement: AGP 9.3 requires a minimum Gradle version of 9.5.0 [2][3]. Legacy DSL and Deprecations: AGP 9.0 and later versions have removed several legacy DSL blocks that were previously deprecated [4][5][6]. - lintOptions: This block has been replaced by the lint block [7][6]. - packagingOptions: This block has been replaced by the packaging block [7][6]. - compileSdkVersion: This function is deprecated and will be removed in AGP 10.0; it is replaced by the compileSdk block [7]. RenderScript: Support for RenderScript was removed in earlier versions of AGP (it was deprecated and subsequently removed) [5]. In modern AGP versions, RenderScript compilation is not supported as a built-in feature. If you still require RenderScript, you must handle it outside of the standard AGP build pipeline or use alternative image processing libraries. For projects that previously used it, the android.defaults.buildfeatures.renderscript property and the buildFeatures.renderScript block were used to control its enablement [5], but these are no longer relevant in current AGP versions. For further details, consult the Android Gradle Plugin release notes [2] and the official API reference documentation [8].
Citations:
🏁 Script executed:
Repository: MovingBlocks/DestSolAndroid
Length of output: 22109
🌐 Web query:
site:developer.android.com/build/releases/agp-9-0-0-release-notes lintOptions packagingOptions RenderScript compileSdkVersion💡 Result:
RenderScript is deprecated in Android and support has been removed in recent versions of the Android Gradle Plugin (AGP). To enable RenderScript compilation in projects that still require it, you must explicitly set the build feature in your module-level build.gradle file [1]: android { buildFeatures { renderScript = true } } Regarding lintOptions and packagingOptions, these are configuration blocks used within the android block of your module-level build.gradle file to manage lint analysis and the packaging of the APK or AAB. The lintOptions block (often referred to as lint in newer AGP versions) allows you to configure how the lint tool analyzes your project, such as ignoring specific warnings or treating warnings as errors. The packagingOptions block (often referred to as packaging in newer AGP versions) is used to configure how files are packaged into the final artifact, specifically for handling duplicate files or excluding files that are not needed. The compileSdkVersion specifies the Android SDK version used to compile your app. Using a high compileSdkVersion is recommended to access the latest APIs, though it is independent of the deprecated status of specific libraries like RenderScript. [1]
Citations:
Migrate the removed AGP 9 DSL.
lintOptions,packagingOptions, andrenderscript.srcDirsare not supported by AGP 9. Replace them with the current DSL or remove them. MigratecompileSdkVersion(...)tocompileSdk. This repository declares no Gradle wrapper or Gradle version, so add or document the required Gradle 9.5.0+ toolchain.🤖 Prompt for AI Agents