diff --git a/CHANGES.md b/CHANGES.md
index 795493778..e4e2d32ef 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,6 +1,8 @@
# Goomph releases
## [Unreleased]
+### Added
+- New plugin `com.diffplug.configuration-cache-for-platform-specific-build` which makes the `OS.getNative()` and `SwtPlatform.xxx` methods work without breaking the Gradle configuration cache. ([#153](https://github.com/diffplug/goomph/pull/153))
## [3.31.0] - 2021-07-23
### Added
diff --git a/README.md b/README.md
index dfe964755..f31f5f988 100644
--- a/README.md
+++ b/README.md
@@ -108,6 +108,10 @@ Below is an index of Goomph's capabilities, along with links to the javadoc wher
* Used to power the infrastructure above.
+#### Other
+
+* [`com.diffplug.configuration-cache-for-platform-specific-build`](https://javadoc.io/doc/com.diffplug.gradle/goomph/3.31.0/com/diffplug/gradle/swt/PlatformSpecificBuildPlugin.html) allows you to use `OS.getNative()` and `OS.getRunning()` in your gradle build without breaking the configuration cache.
+
## Acknowledgements
diff --git a/build.gradle b/build.gradle
index c3db30e06..28fec94e3 100644
--- a/build.gradle
+++ b/build.gradle
@@ -24,7 +24,7 @@ spotless {
}
String VER_DURIAN = '1.2.0'
-String VER_DURIAN_SWT = '3.4.0'
+String VER_DURIAN_SWT = '3.5.0'
String VER_BNDLIB = '5.3.0'
String OLDEST_SUPPORTED_GRADLE = '5.1'
String VER_P2_BOOTSTRAP = '4.13.0'
@@ -42,8 +42,8 @@ dependencies {
// OSGi
implementation "biz.aQute.bnd:biz.aQute.bndlib:${VER_BNDLIB}"
// testing
- testImplementation "junit:junit:4.13"
- testImplementation "org.assertj:assertj-core:3.14.0"
+ testImplementation "junit:junit:4.13.2"
+ testImplementation "org.assertj:assertj-core:3.20.2"
}
configurations.compileClasspath {
diff --git a/gradle.properties b/gradle.properties
index e7e17ecfc..fae670e4b 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -14,6 +14,7 @@ plugin_list=\
eclipseResourceFilters \
equinoxLaunch \
oomphIde \
+ platformSpecificBuild \
p2AsMaven \
osgiBndManifest \
swtNativeDeps
@@ -63,6 +64,12 @@ plugin_oomphIde_name=Goomph oomphIde
plugin_oomphIde_desc=Downloads and sets up any Eclipse-based IDE.
plugin_oomphIde_tags=eclipse ide p2AsMaven
+plugin_platformSpecificBuild_id=com.diffplug.configuration-cache-for-platform-specific-build
+plugin_platformSpecificBuild_impl=com.diffplug.gradle.swt.PlatformSpecificBuildPlugin
+plugin_platformSpecificBuild_name=Goomph configuration-cache friendly platform specific build
+plugin_platformSpecificBuild_desc=Allows `OS.getNative()` and `OS.getRunning()` to work with configuration cache
+plugin_platformSpecificBuild_tags=configuration-cache platform-specific
+
plugin_p2AsMaven_id=com.diffplug.p2.asmaven
plugin_p2AsMaven_impl=com.diffplug.gradle.p2.AsMavenPlugin
plugin_p2AsMaven_name=Goomph p2AsMaven
diff --git a/src/main/java/com/diffplug/gradle/swt/PlatformSpecificBuildPlugin.java b/src/main/java/com/diffplug/gradle/swt/PlatformSpecificBuildPlugin.java
new file mode 100644
index 000000000..1cb17be71
--- /dev/null
+++ b/src/main/java/com/diffplug/gradle/swt/PlatformSpecificBuildPlugin.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 DiffPlug
+ *
+ * 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.
+ */
+package com.diffplug.gradle.swt;
+
+
+import com.diffplug.common.swt.os.OS;
+import org.gradle.api.Plugin;
+import org.gradle.api.initialization.Settings;
+
+/**
+ * In order to detect the underlying operating system and architecture, it is necessary to
+ * to read various system properties and environment variables, which breaks the Gradle configuration cache.
+ * But, if you apply `com.diffplug.configuration-cache-for-platform-specific-build` in your `settings.gradle`,
+ * then you can call {@link OS#getRunning()} and {@link OS#getNative()} and behind the scenes it will use
+ *
+ * the appropriate APIs which don't break the configuration cache.
+ */
+public class PlatformSpecificBuildPlugin implements Plugin {
+ @Override
+ public void apply(Settings settings) {
+ OS.detectPlatform(
+ systemProp -> settings.getProviders().systemProperty(systemProp).forUseAtConfigurationTime().get(),
+ envVar -> settings.getProviders().environmentVariable(envVar).forUseAtConfigurationTime().get());
+ }
+}
diff --git a/src/test/java/com/diffplug/gradle/swt/PlatformSpecificBuildPluginTest.java b/src/test/java/com/diffplug/gradle/swt/PlatformSpecificBuildPluginTest.java
new file mode 100644
index 000000000..1c69e83f6
--- /dev/null
+++ b/src/test/java/com/diffplug/gradle/swt/PlatformSpecificBuildPluginTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2021 DiffPlug
+ *
+ * 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.
+ */
+package com.diffplug.gradle.swt;
+
+
+import com.diffplug.gradle.GradleIntegrationTest;
+import java.io.IOException;
+import org.gradle.testkit.runner.GradleRunner;
+import org.junit.Ignore;
+import org.junit.Test;
+
+public class PlatformSpecificBuildPluginTest extends GradleIntegrationTest {
+ protected GradleRunner gradleRunner() {
+ return super.gradleRunner().withGradleVersion("7.2");
+ }
+
+ private GradleRunner breakConfigCache() throws IOException {
+ write("gradle.properties", "org.gradle.unsafe.configuration-cache=true");
+ write("build.gradle",
+ "plugins {",
+ " id 'java'",
+ " id 'com.diffplug.eclipse.mavencentral'",
+ "}",
+ "repositories { mavenCentral() }",
+ "eclipseMavenCentral {",
+ " release '4.20.0', {",
+ " implementation 'org.eclipse.swt'",
+ " implementation 'org.eclipse.jface'",
+ " implementation \"org.eclipse.swt.${com.diffplug.common.swt.os.SwtPlatform.getRunning()}\"",
+ " useNativesForRunningPlatform()",
+ " }",
+ "}");
+ write("src/main/java/pkg/Demo.java",
+ "package pkg;",
+ "public class Demo {}");
+ return gradleRunner().withArguments("jar");
+ }
+
+ @Test
+ @Ignore // fails in real project, but not unit test, not sure why
+ public void configurationCacheBroken() throws IOException {
+ breakConfigCache().buildAndFail();
+ }
+
+ @Test
+ public void configurationCacheWorks() throws IOException {
+ write("settings.gradle",
+ "plugins {",
+ " id 'com.diffplug.configuration-cache-for-platform-specific-build'",
+ "}");
+ breakConfigCache().build();
+ }
+}