From b12a4c057dd41994543786820e3c2223c4ab44c0 Mon Sep 17 00:00:00 2001 From: Gareth Date: Wed, 29 Apr 2026 21:28:09 +0100 Subject: [PATCH 1/3] Attempt to cache the gradle config for faster boots --- build.gradle.kts | 36 +++++++++++++++++++++++------------- gradle.properties | 6 ++++-- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 86bc8d1..4d262e3 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,7 +6,7 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { id("java") alias(libs.plugins.kotlinJvm) - id("org.jetbrains.intellij.platform") version "2.14.0" // https://github.com/JetBrains/gradle-intellij-plugin/releases + id("org.jetbrains.intellij.platform") version "2.15.0" // https://github.com/JetBrains/gradle-intellij-plugin/releases id("me.filippov.gradle.jvm.wrapper") version "0.16.0" } @@ -148,15 +148,18 @@ tasks.runIde { // part of a plugin, but there are dangers about keeping plugins in sync autoReload = false + val exampleModSolution = layout.projectDirectory.file("example-mod/AshAndDust.sln").asFile.absolutePath + argumentProviders += CommandLineArgumentProvider { - listOf("${rootDir}/example-mod/AshAndDust.sln") + listOf(exampleModSolution) } } tasks.prepareSandbox { dependsOn(compileDotNet) - val outputFolder = "${rootDir}/src/dotnet/${DotnetPluginId}/bin/${DotnetPluginId}.Rider/${BuildConfiguration}" + val outputFolder = layout.projectDirectory.dir("/src/dotnet/${DotnetPluginId}/bin/${DotnetPluginId}.Rider/${BuildConfiguration}") + val dllFiles = listOf( "$outputFolder/${DotnetPluginId}.dll", "$outputFolder/${DotnetPluginId}.pdb", @@ -168,20 +171,27 @@ tasks.prepareSandbox { "$outputFolder/AsmResolver.PE.dll", "$outputFolder/AsmResolver.PE.File.dll", "$outputFolder/ICSharpCode.Decompiler.dll" - ) + ).map { outputFolder.file(it) } - dllFiles.forEach({ f -> - val file = file(f) - from(file, { into("${rootProject.name}/dotnet") }) - }) + dllFiles.forEach { provider -> + from(provider) { + into("${rootProject.name}/dotnet") + } + } - from("${rootDir}/src/dotnet/${DotnetPluginId}/ProjectTemplates", { into("${rootProject.name}/ProjectTemplates") }) + from( + layout.projectDirectory.dir("src/dotnet/$DotnetPluginId/ProjectTemplates") + ) { + into("${rootProject.name}/ProjectTemplates") + } doLast { - dllFiles.forEach({ f -> - val file = file(f) - if (!file.exists()) throw RuntimeException("File ${file} does not exist") - }) + dllFiles.forEach { f -> + val file = f.asFile + if (!file.exists()) { + throw RuntimeException("File $file does not exist") + } + } // The Rider SDK archive omits certain DLLs that are present in a full Rider installation. // Copy the missing Unity plugin DotFiles DLL from the local Rider installation so the sandbox can load it. diff --git a/gradle.properties b/gradle.properties index 11c15a0..2d2be6c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ DotnetPluginId=ReSharperPlugin.RimworldDev DotnetSolution=ReSharperPlugin.RimworldDev.sln RiderPluginId=com.jetbrains.rider.plugins.rimworlddev -PluginVersion=2025.1.10 +PluginVersion=2025.1.11 BuildConfiguration=Release @@ -28,4 +28,6 @@ gradleJvmWrapperVersion=0.15.0 riderBaseVersion=2025.1 # Required to download Rider artifacts from Maven (and not "binary" releases from CDN). -org.jetbrains.intellij.platform.buildFeature.useBinaryReleases=false \ No newline at end of file +org.jetbrains.intellij.platform.buildFeature.useBinaryReleases=false + +org.gradle.configuration-cache=true \ No newline at end of file From 54e2bb447f60fe7d8dc66c80711142f715d5f8d6 Mon Sep 17 00:00:00 2001 From: Gareth Date: Wed, 29 Apr 2026 21:45:16 +0100 Subject: [PATCH 2/3] Move dll copying over to another task to preserve windows build speed --- build.gradle.kts | 84 +++++++++++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 37 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 4d262e3..137a6b3 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -155,43 +155,9 @@ tasks.runIde { } } -tasks.prepareSandbox { - dependsOn(compileDotNet) - - val outputFolder = layout.projectDirectory.dir("/src/dotnet/${DotnetPluginId}/bin/${DotnetPluginId}.Rider/${BuildConfiguration}") - - val dllFiles = listOf( - "$outputFolder/${DotnetPluginId}.dll", - "$outputFolder/${DotnetPluginId}.pdb", - - // Not 100% sure why, but we manually need to include these dependencies for Remodder to work - "$outputFolder/0Harmony.dll", - "$outputFolder/AsmResolver.dll", - "$outputFolder/AsmResolver.DotNet.dll", - "$outputFolder/AsmResolver.PE.dll", - "$outputFolder/AsmResolver.PE.File.dll", - "$outputFolder/ICSharpCode.Decompiler.dll" - ).map { outputFolder.file(it) } - - dllFiles.forEach { provider -> - from(provider) { - into("${rootProject.name}/dotnet") - } - } - - from( - layout.projectDirectory.dir("src/dotnet/$DotnetPluginId/ProjectTemplates") - ) { - into("${rootProject.name}/ProjectTemplates") - } - - doLast { - dllFiles.forEach { f -> - val file = f.asFile - if (!file.exists()) { - throw RuntimeException("File $file does not exist") - } - } +if (!isWindows) { + tasks.register("copyRiderDlls") { + notCompatibleWithConfigurationCache("Uses local Rider install") // The Rider SDK archive omits certain DLLs that are present in a full Rider installation. // Copy the missing Unity plugin DotFiles DLL from the local Rider installation so the sandbox can load it. @@ -231,6 +197,50 @@ tasks.prepareSandbox { } } } + + tasks.named("prepareSandbox") { + dependsOn("copyRiderDlls") + } +} + +tasks.prepareSandbox { + dependsOn(compileDotNet) + + val outputFolder = layout.projectDirectory.dir("/src/dotnet/${DotnetPluginId}/bin/${DotnetPluginId}.Rider/${BuildConfiguration}") + + val dllFiles = listOf( + "$outputFolder/${DotnetPluginId}.dll", + "$outputFolder/${DotnetPluginId}.pdb", + + // Not 100% sure why, but we manually need to include these dependencies for Remodder to work + "$outputFolder/0Harmony.dll", + "$outputFolder/AsmResolver.dll", + "$outputFolder/AsmResolver.DotNet.dll", + "$outputFolder/AsmResolver.PE.dll", + "$outputFolder/AsmResolver.PE.File.dll", + "$outputFolder/ICSharpCode.Decompiler.dll" + ).map { outputFolder.file(it) } + + dllFiles.forEach { provider -> + from(provider) { + into("${rootProject.name}/dotnet") + } + } + + from( + layout.projectDirectory.dir("src/dotnet/$DotnetPluginId/ProjectTemplates") + ) { + into("${rootProject.name}/ProjectTemplates") + } + + doLast { + dllFiles.forEach { f -> + val file = f.asFile + if (!file.exists()) { + throw RuntimeException("File $file does not exist") + } + } + } } val testDotNet by tasks.registering(Exec::class) { From 96839f613b558e7d25a4a7e77ae2f2d41e6aae39 Mon Sep 17 00:00:00 2001 From: Dexter Lowe Date: Thu, 30 Apr 2026 18:11:50 +0100 Subject: [PATCH 3/3] Pre-resolve copy dlls reqs to support gradle caching (#93) * Pre-resolve copy dlls reqs to support gradle caching * Missed a few references needing caches --- build.gradle.kts | 90 +++++++++++++++++++++++++----------------------- 1 file changed, 47 insertions(+), 43 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 137a6b3..346e201 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -105,11 +105,15 @@ val buildResharperPlugin by tasks.registering(Exec::class) { } tasks.buildPlugin { + // Capture providers/files at configuration time so the doLast doesn't touch Project APIs + // (project.copy(), project.buildDir, project.rootDir) — required for the configuration cache. + val pluginZip = layout.buildDirectory.file("distributions/${rootProject.name}-${version}.zip") + val outputDir = layout.projectDirectory.dir("output").asFile + doLast { - copy { - from("${buildDir}/distributions/${rootProject.name}-${version}.zip") - into("${rootDir}/output") - } + val zipFile = pluginZip.get().asFile + outputDir.mkdirs() + zipFile.copyTo(outputDir.resolve(zipFile.name), overwrite = true) } } @@ -155,58 +159,58 @@ tasks.runIde { } } +// The Rider SDK archive omits certain DLLs that are present in a full Rider installation. +// Copy the missing Unity plugin DotFiles DLLs from the local Rider installation so the sandbox can load them. +// +// This is a side-effect on the extracted SDK (intellijPlatform.platformPath) — *not* a declared task output — because +// other tasks (patchPluginXml, buildPlugin, etc.) read from that same directory. Declaring it as an OutputDirectory +// would make Gradle complain about implicit dependencies. Hooking it as a `doLast` on prepareSandbox keeps it as a +// transparent mutation of the SDK that runs before any consumer. +// +// All Project-API access (file(), intellijPlatform.platformPath, system properties) is hoisted to configuration time +// and captured into locals so the action stays compatible with the configuration cache. if (!isWindows) { - tasks.register("copyRiderDlls") { - notCompatibleWithConfigurationCache("Uses local Rider install") - - // The Rider SDK archive omits certain DLLs that are present in a full Rider installation. - // Copy the missing Unity plugin DotFiles DLL from the local Rider installation so the sandbox can load it. - if (!isWindows) { - val riderInstallCandidates = if (Os.isFamily(Os.FAMILY_MAC)) { - listOf(file("/Applications/Rider.app/Contents")) - } else { - // Linux: check JetBrains Toolbox and common standalone install paths - val toolboxBase = file("${System.getProperty("user.home")}/.local/share/JetBrains/Toolbox/apps/Rider") - val toolboxInstalls = if (toolboxBase.exists()) { - toolboxBase.walkTopDown() - .filter { it.name == "plugins" && it.parentFile?.name?.startsWith("2") == true } - .map { it.parentFile } - .toList() - } else emptyList() - toolboxInstalls + listOf(file("/opt/rider"), file("/usr/share/rider")) - } + val riderInstallCandidates: List = if (Os.isFamily(Os.FAMILY_MAC)) { + listOf(File("/Applications/Rider.app/Contents")) + } else { + // Linux: check JetBrains Toolbox and common standalone install paths + val userHome = providers.systemProperty("user.home").get() + val toolboxBase = File("$userHome/.local/share/JetBrains/Toolbox/apps/Rider") + val toolboxInstalls = if (toolboxBase.exists()) { + toolboxBase.walkTopDown() + .filter { it.name == "plugins" && it.parentFile?.name?.startsWith("2") == true } + .map { it.parentFile } + .toList() + } else emptyList() + toolboxInstalls + listOf(File("/opt/rider"), File("/usr/share/rider")) + } - val missingDotFileDlls = listOf( - "JetBrains.ReSharper.Plugins.Unity.Rider.Debugger.PausePoint.Helper.dll", - "JetBrains.ReSharper.Plugins.Unity.Rider.Debugger.Presentation.Texture.dll", - ) + val missingDotFileDlls = listOf( + "JetBrains.ReSharper.Plugins.Unity.Rider.Debugger.PausePoint.Helper.dll", + "JetBrains.ReSharper.Plugins.Unity.Rider.Debugger.Presentation.Texture.dll", + ) - val destDir = intellijPlatform.platformPath.resolve("plugins/rider-unity/DotFiles").toFile() - destDir.mkdirs() + val resolvedRiderDllSources: List = missingDotFileDlls.mapNotNull { dllName -> + val rel = "plugins/rider-unity/DotFiles/$dllName" + riderInstallCandidates.map { File(it, rel) }.firstOrNull { it.exists() } + } - for (dllName in missingDotFileDlls) { - val dllRelPath = "plugins/rider-unity/DotFiles/$dllName" - val srcDll = riderInstallCandidates - .map { file("${it}/${dllRelPath}") } - .firstOrNull { it.exists() } + val riderDllDestDir = intellijPlatform.platformPath.resolve("plugins/rider-unity/DotFiles").toFile() - if (srcDll != null) { - // Copy into the extracted SDK location (platformPath) — that's where Rider loads plugins from at runtime - srcDll.copyTo(file("${destDir}/${srcDll.name}"), overwrite = true) - } + tasks.prepareSandbox { + doLast { + riderDllDestDir.mkdirs() + resolvedRiderDllSources.forEach { src -> + src.copyTo(File(riderDllDestDir, src.name), overwrite = true) } } } - - tasks.named("prepareSandbox") { - dependsOn("copyRiderDlls") - } } tasks.prepareSandbox { dependsOn(compileDotNet) - val outputFolder = layout.projectDirectory.dir("/src/dotnet/${DotnetPluginId}/bin/${DotnetPluginId}.Rider/${BuildConfiguration}") + val outputFolder = layout.projectDirectory.dir("src/dotnet/${DotnetPluginId}/bin/${DotnetPluginId}.Rider/${BuildConfiguration}") val dllFiles = listOf( "$outputFolder/${DotnetPluginId}.dll",