From 2bf6056d1610036ebd67988085cf208f0a9af626 Mon Sep 17 00:00:00 2001 From: Stephanie Gawroriski Date: Mon, 8 Apr 2024 20:23:38 +0000 Subject: [PATCH] Detect whether the CMake build tree changes locations, such as when CI/CD uses a different directory for the build. --- .../general/CollateResourceJarsTaskAction.java | 38 +---------- .../plugin/general/cmake/CMakeBuildTask.java | 2 +- .../plugin/general/cmake/CMakeBuildTaskAction.java | 25 +------- .../plugin/general/cmake/CMakeUpToDateWhen.java | 4 ++ .../plugin/general/cmake/CMakeUtils.java | 75 ++++++++++++++++++++++ .../cc/squirreljme/plugin/multivm/VMHelpers.java | 74 +++++++++++++++++++++ 6 files changed, 159 insertions(+), 59 deletions(-) diff --git a/buildSrc/src/main/java/cc/squirreljme/plugin/general/CollateResourceJarsTaskAction.java b/buildSrc/src/main/java/cc/squirreljme/plugin/general/CollateResourceJarsTaskAction.java index 02f0b47353..e7355a78fe 100644 --- a/buildSrc/src/main/java/cc/squirreljme/plugin/general/CollateResourceJarsTaskAction.java +++ b/buildSrc/src/main/java/cc/squirreljme/plugin/general/CollateResourceJarsTaskAction.java @@ -9,6 +9,7 @@ package cc.squirreljme.plugin.general; +import cc.squirreljme.plugin.multivm.VMHelpers; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -95,42 +96,7 @@ public class CollateResourceJarsTaskAction // Delete old directory set first since it will have a bunch of // old files in it and such... - if (Files.isDirectory(outBase)) - { - Set deleteFiles = new LinkedHashSet<>(); - Set deleteDirs = new LinkedHashSet<>(); - - try (Stream walk = Files.walk(outBase)) - { - walk.forEach((__it) -> { - if (Files.isDirectory(__it)) - deleteDirs.add(__it); - else - deleteFiles.add(__it); - }); - } - - for (Set rawByes : Arrays.asList(deleteFiles, deleteDirs)) - { - List byes = new ArrayList<>(rawByes); - Collections.reverse(byes); - - for (Path bye : byes) - { - __task.getLogger().lifecycle( - String.format("Cleaning %s...", bye)); - - try - { - Files.deleteIfExists(bye); - } - catch (IOException e) - { - e.printStackTrace(); - } - } - } - } + VMHelpers.deleteDirTree(__task, outBase); // Make sure it exists Files.createDirectories(outBase); diff --git a/buildSrc/src/main/java/cc/squirreljme/plugin/general/cmake/CMakeBuildTask.java b/buildSrc/src/main/java/cc/squirreljme/plugin/general/cmake/CMakeBuildTask.java index f32a7cda4e..dd03ac5c2b 100644 --- a/buildSrc/src/main/java/cc/squirreljme/plugin/general/cmake/CMakeBuildTask.java +++ b/buildSrc/src/main/java/cc/squirreljme/plugin/general/cmake/CMakeBuildTask.java @@ -93,7 +93,7 @@ public class CMakeBuildTask try { // Configure CMake first before we continue with anything - action.configure(this); + CMakeUtils.configure(this); } catch (IOException __e) { diff --git a/buildSrc/src/main/java/cc/squirreljme/plugin/general/cmake/CMakeBuildTaskAction.java b/buildSrc/src/main/java/cc/squirreljme/plugin/general/cmake/CMakeBuildTaskAction.java index b46b1f400e..a6a9d6b94c 100644 --- a/buildSrc/src/main/java/cc/squirreljme/plugin/general/cmake/CMakeBuildTaskAction.java +++ b/buildSrc/src/main/java/cc/squirreljme/plugin/general/cmake/CMakeBuildTaskAction.java @@ -24,24 +24,6 @@ import org.gradle.api.Task; public class CMakeBuildTaskAction implements Action { - public void configure(Task __task) - throws IOException - { - CMakeBuildTask from = (CMakeBuildTask)__task; - - Path cmakeBuild = from.cmakeBuild; - Path cmakeSource = from.cmakeSource; - - // Make sure the output build directory exists - Files.createDirectories(cmakeBuild); - - // Configure CMake first before we continue with anything - CMakeUtils.cmakeExecute(__task.getLogger(), - "configure", __task.getProject().getBuildDir().toPath(), - "-S", cmakeSource.toAbsolutePath().toString(), - "-B", cmakeBuild.toAbsolutePath().toString()); - } - /** * {@inheritDoc} * @since 2024/03/15 @@ -61,10 +43,9 @@ public class CMakeBuildTaskAction // Then perform the actual build, for each rule for (String cmakeRule : from.cmakeRules) { - // Does the cache seem invalid? Then configure first - if (!Files.isDirectory(cmakeBuild) || - !Files.exists(cmakeBuild.resolve("CMakeCache.txt"))) - this.configure(__task); + // Do we need to configure? + if (CMakeUtils.configureNeeded(from)) + CMakeUtils.configure(from); // Run normal CMake build CMakeUtils.cmakeExecute(__task.getLogger(), diff --git a/buildSrc/src/main/java/cc/squirreljme/plugin/general/cmake/CMakeUpToDateWhen.java b/buildSrc/src/main/java/cc/squirreljme/plugin/general/cmake/CMakeUpToDateWhen.java index a06a079118..edcd2b92ae 100644 --- a/buildSrc/src/main/java/cc/squirreljme/plugin/general/cmake/CMakeUpToDateWhen.java +++ b/buildSrc/src/main/java/cc/squirreljme/plugin/general/cmake/CMakeUpToDateWhen.java @@ -32,6 +32,10 @@ public class CMakeUpToDateWhen { CMakeBuildTask cmakeTask = (CMakeBuildTask)__task; + // Configuration is needed? + if (CMakeUtils.configureNeeded(cmakeTask)) + return false; + // Cache directory does not exist? if (!Files.isDirectory(cmakeTask.cmakeBuild)) return false; diff --git a/buildSrc/src/main/java/cc/squirreljme/plugin/general/cmake/CMakeUtils.java b/buildSrc/src/main/java/cc/squirreljme/plugin/general/cmake/CMakeUtils.java index 306dc5fd26..42ba2c6891 100644 --- a/buildSrc/src/main/java/cc/squirreljme/plugin/general/cmake/CMakeUtils.java +++ b/buildSrc/src/main/java/cc/squirreljme/plugin/general/cmake/CMakeUtils.java @@ -9,6 +9,7 @@ package cc.squirreljme.plugin.general.cmake; +import cc.squirreljme.plugin.multivm.VMHelpers; import cc.squirreljme.plugin.util.ForwardInputToOutput; import cc.squirreljme.plugin.util.ForwardStream; import cc.squirreljme.plugin.util.PathUtils; @@ -30,6 +31,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.concurrent.TimeUnit; +import org.gradle.api.Task; import org.gradle.api.logging.LogLevel; import org.gradle.api.logging.Logger; import org.gradle.internal.os.OperatingSystem; @@ -318,6 +320,79 @@ public final class CMakeUtils } /** + * Configures the CMake task. + * + * @param __task The task to configure. + * @throws IOException If it could not be configured. + * @since 2024/04/08 + */ + public static void configure(CMakeBuildTask __task) + throws IOException + { + Path cmakeBuild = __task.cmakeBuild; + Path cmakeSource = __task.cmakeSource; + + // Old directory must be deleted as it might be very stale + VMHelpers.deleteDirTree(__task, cmakeBuild); + + // Make sure the output build directory exists + Files.createDirectories(cmakeBuild); + + // Configure CMake first before we continue with anything + CMakeUtils.cmakeExecute(__task.getLogger(), + "configure", __task.getProject().getBuildDir().toPath(), + "-S", cmakeSource.toAbsolutePath().toString(), + "-B", cmakeBuild.toAbsolutePath().toString()); + } + /** + * Is configuration needed? + * + * @param __task The task to check. + * @return If reconfiguration is needed or not. + * @since 2024/04/08 + */ + public static boolean configureNeeded(CMakeBuildTask __task) + { + Path cmakeBuild = __task.cmakeBuild; + + // Missing directories or no cache at all? + if (!Files.isDirectory(cmakeBuild) || + !Files.exists(cmakeBuild.resolve("CMakeCache.txt"))) + return true; + + // Load in the CMake cache to check it + try + { + // Load CMake cache + Map cmakeCache = CMakeUtils.loadCache(cmakeBuild); + + // Check the configuration directory + String rawConfigDir = cmakeCache.get( + "CMAKE_CACHEFILE_DIR:INTERNAL"); + + // No configuration directory is known?? + if (rawConfigDir == null) + return true; + + // Did the directory of the cache change? This can happen + // under CI/CD where the build directory is different and + // there is old data that is restored + Path configDir = Paths.get(rawConfigDir).toAbsolutePath(); + if (!Files.isSameFile(configDir, cmakeBuild) || + !cmakeBuild.equals(configDir)) + return true; + } + catch (IOException __ignored) + { + // If this happens, just assume it needs to be done + return true; + } + + // Not needed + return false; + } + + /** * Dumps log to the output. * * @param __logger The logger to output to. diff --git a/buildSrc/src/main/java/cc/squirreljme/plugin/multivm/VMHelpers.java b/buildSrc/src/main/java/cc/squirreljme/plugin/multivm/VMHelpers.java index ecc34d2689..ebd83464c8 100644 --- a/buildSrc/src/main/java/cc/squirreljme/plugin/multivm/VMHelpers.java +++ b/buildSrc/src/main/java/cc/squirreljme/plugin/multivm/VMHelpers.java @@ -48,6 +48,7 @@ import java.util.jar.Attributes; import java.util.jar.Manifest; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Stream; import org.gradle.api.Project; import org.gradle.api.Task; import org.gradle.api.artifacts.Configuration; @@ -480,6 +481,79 @@ public final class VMHelpers } /** + * Deletes the given directory tree. + * + * @param __task The task deleting for. + * @param __path The path to delete. + * @throws NullPointerException On null arguments. + * @since 2024/04/08 + */ + public static void deleteDirTree(Task __task, Path __path) + throws NullPointerException + { + if (__task == null || __path == null) + throw new NullPointerException("NARG"); + + // Ignore if not a directory + Path base = __path.toAbsolutePath().normalize(); + if (!Files.isDirectory(__path)) + return; + + // Collect files to delete + Set deleteFiles = new LinkedHashSet<>(); + Set deleteDirs = new LinkedHashSet<>(); + + // Perform the walk to collect files + try (Stream walk = Files.walk(__path)) + { + walk.forEach((__it) -> { + Path normal = __it.toAbsolutePath().normalize(); + + if (Files.isDirectory(normal)) + deleteDirs.add(normal); + else + deleteFiles.add(normal); + }); + } + catch (IOException __e) + { + __e.printStackTrace(); + } + + // Run through and delete files then directories + for (Set rawByes : Arrays.asList(deleteFiles, deleteDirs)) + { + List byes = new ArrayList<>(rawByes); + Collections.reverse(byes); + + for (Path bye : byes) + { + // Note + __task.getLogger().lifecycle( + String.format("Cleaning %s...", bye)); + + // Skip out of tree files + if (!bye.startsWith(base)) + { + __task.getLogger().lifecycle( + String.format("%s is out of tree, skipping...", bye)); + continue; + } + + // Perform deletion + try + { + Files.deleteIfExists(bye); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + } + } + + /** * Attempts to find the emulator library so that can be loaded directly * instead of being extracted by each test process, if possible. * -- 2.11.4.GIT