diff --git a/src/main/java/net/minecraftforge/mcmaven/cli/MavenTask.java b/src/main/java/net/minecraftforge/mcmaven/cli/MavenTask.java index 379d0fa..9c4d3d5 100644 --- a/src/main/java/net/minecraftforge/mcmaven/cli/MavenTask.java +++ b/src/main/java/net/minecraftforge/mcmaven/cli/MavenTask.java @@ -7,12 +7,14 @@ import java.io.File; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import joptsimple.OptionParser; import joptsimple.OptionSpecBuilder; import net.minecraftforge.mcmaven.impl.Mavenizer; import net.minecraftforge.mcmaven.impl.MinecraftMaven; +import net.minecraftforge.mcmaven.impl.cache.Cache; import net.minecraftforge.mcmaven.impl.mappings.Mappings; import net.minecraftforge.mcmaven.impl.mappings.ParchmentMappings; import net.minecraftforge.mcmaven.impl.util.Artifact; @@ -36,6 +38,11 @@ static OptionParser run(String[] args, boolean getParser) throws Exception { "Directory to store data needed for this program") .withRequiredArg().ofType(File.class).defaultsTo(new File("cache")); + // per-projct cache directory, This is where all the post processed files are cached + var localCacheO = parser.accepts("local-cache", + "Directory to store the project specific cache files, opposed to the global cache") + .withRequiredArg().ofType(File.class).defaultsTo(new File("cache/local")); + // jdk cache directory var jdkCacheO = parser.accepts("jdk-cache", "Directory to store jdks downloaded from the disoco api") @@ -104,9 +111,11 @@ static OptionParser run(String[] args, boolean getParser) throws Exception { var accessTransformerO = parser.accepts("access-transformer", "An AccessTransformer config to apply to the artifacts have been built. This is a work around for Gradle's broken ArtifactTransformer system. https://github.com/MinecraftForge/ForgeGradle/issues/1023") - .availableUnless(stubO) .withRequiredArg().ofType(File.class); - stubO.availableUnless(accessTransformerO); + + var facadeConfigO = parser.accepts("facade-config", + "A Facade Config, which allows injecting interfaces to the built artifacts.") + .withRequiredArg().ofType(File.class); var outputJsonO = parser.accepts("output-json", "File to write extended output data to. Not compatible with bulk operations.") @@ -165,6 +174,9 @@ static OptionParser run(String[] args, boolean getParser) throws Exception { var jdkCache = !options.has(cacheO) || options.has(jdkCacheO) ? options.valueOf(jdkCacheO) : new File(cache, "jdks"); + var localCache = !options.has(cacheO) || options.has(localCacheO) + ? options.valueOf(localCacheO) + : new File(cache, "local"); Artifact artifact = null; for (var entry : artifacts.entrySet()) { @@ -193,14 +205,15 @@ static OptionParser run(String[] args, boolean getParser) throws Exception { var mcmaven = new MinecraftMaven( output, options.has(dependenciesOnlyO), - cache, - jdkCache, + new Cache(cache, localCache, jdkCache, foreignRepositories), mappings, foreignRepositories, options.has(globalAuxiliaryVariantsO), options.has(disableGradleO), options.has(stubO), + new HashSet<>(), new ArrayList<>(options.valuesOf(accessTransformerO)), + new ArrayList<>(options.valuesOf(facadeConfigO)), options.valueOf(outputJsonO) ); mcmaven.run(artifact); diff --git a/src/main/java/net/minecraftforge/mcmaven/impl/MinecraftMaven.java b/src/main/java/net/minecraftforge/mcmaven/impl/MinecraftMaven.java index 7c0b97d..4aac547 100644 --- a/src/main/java/net/minecraftforge/mcmaven/impl/MinecraftMaven.java +++ b/src/main/java/net/minecraftforge/mcmaven/impl/MinecraftMaven.java @@ -19,6 +19,7 @@ import net.minecraftforge.mcmaven.impl.util.Constants; import net.minecraftforge.mcmaven.impl.util.POMBuilder; import net.minecraftforge.mcmaven.impl.util.ProcessUtils; +import net.minecraftforge.mcmaven.impl.util.Task; import net.minecraftforge.mcmaven.impl.util.Util; import net.minecraftforge.srgutils.MinecraftVersion; import net.minecraftforge.util.data.json.JsonData; @@ -71,18 +72,13 @@ public record MinecraftMaven( boolean stubJars, Set mcpConfigVersions, List accessTransformer, + List facadeConfigs, @Nullable File outputJsonFile ) { // Only 1.14.4+ has official mappings, we can support more when we add more mappings private static final MinecraftVersion MIN_OFFICIAL_MAPPINGS = MinecraftVersion.from("1.14.4"); private static final ComparableVersion MIN_SUPPORTED_FORGE = new ComparableVersion("1.14.4"); - public MinecraftMaven(File output, boolean dependenciesOnly, File cacheRoot, File jdkCacheRoot, Mappings mappings, - Map foreignRepositories, boolean globalAuxiliaryVariants, boolean disableGradle, boolean stubJars, - List accessTransformer, @Nullable File outputJsonFile) { - this(output, dependenciesOnly, new Cache(cacheRoot, jdkCacheRoot, foreignRepositories), mappings, foreignRepositories, globalAuxiliaryVariants, disableGradle, stubJars, new HashSet<>(), accessTransformer, outputJsonFile); - } - public MinecraftMaven { LOGGER.info(" Output: " + output.getAbsolutePath()); if (outputJsonFile != null) @@ -99,27 +95,31 @@ public MinecraftMaven(File output, boolean dependenciesOnly, File cacheRoot, Fil LOGGER.info(" GradleVariantHack: " + globalAuxiliaryVariants); LOGGER.info(" Disable Gradle: " + disableGradle); LOGGER.info(" Stub Jars: " + stubJars); - if (!accessTransformer.isEmpty()) { - var first = true; - var itor = accessTransformer.iterator(); - while (itor.hasNext()) { - var file = itor.next(); - if (first) { - LOGGER.getInfo().print(" Access Transformer: "); - first = false; - } else { - LOGGER.getInfo().print(" "); - } - LOGGER.getInfo().print(file.getAbsolutePath()); - if (!file.exists()) { - LOGGER.getInfo().print(" SKIPPING DOESN'T EXIST"); - itor.remove(); - } - LOGGER.getInfo().println(); + if (!accessTransformer.isEmpty()) + filter(" Access Transformer: ", accessTransformer); + if (!facadeConfigs.isEmpty()) + filter(" Facade Config: ", facadeConfigs); + LOGGER.info(); + } + + private static void filter(String header, List files) { + var prefix = header; + var itor = files.iterator(); + while (itor.hasNext()) { + var file = itor.next(); + LOGGER.getInfo().print(prefix); + if (prefix == header) + prefix = " ".repeat(header.length()); + + LOGGER.getInfo().print(file.getAbsolutePath()); + + if (!file.exists()) { + LOGGER.getInfo().print(" SKIPPING DOESN'T EXIST"); + itor.remove(); } LOGGER.getInfo().println(); } - LOGGER.info(); + LOGGER.getInfo().println(); } public void run(Artifact artifact) { @@ -225,13 +225,13 @@ protected void createMinecraft(Artifact artifact, MCPConfigRepo mcprepo, Map artifacts = null; if (hasMcp(mcprepo, ver.id)) artifacts = mcprepo.process(versioned, mappings.withMCVersion(ver.id), outputJson); - else if (mappings.channel().equals("official") && (hasOfficialMappings(mcprepo, ver.id) || !mcprepo.isObfuscated(ver.id))) + else if (mappings.channel().equals("official") && (hasOfficialMappings(mcprepo, ver.id) || !MCPConfigRepo.isObfuscated(ver.id))) artifacts = mcprepo.processWithoutMcp(versioned, mappings.withMCVersion(ver.id), outputJson); else { LOGGER.info("Skipping " + versioned + " no mcp config"); continue; } - finalize(artifact, mappings, artifacts); + finalize(versioned, mappings, artifacts); } } else { var mcVersion = mcpToMcVersion(version); @@ -240,7 +240,7 @@ else if (mappings.channel().equals("official") && (hasOfficialMappings(mcprepo, List artifacts = null; if (hasMcp(mcprepo, version)) artifacts = mcprepo.process(artifact, mappings, outputJson); - else if (mappings.channel().equals("official") && (hasOfficialMappings(mcprepo, mcVersion) || !mcprepo.isObfuscated(mcVersion))) + else if (mappings.channel().equals("official") && (hasOfficialMappings(mcprepo, mcVersion) || !MCPConfigRepo.isObfuscated(mcVersion))) artifacts = mcprepo.processWithoutMcp(artifact, mappings, outputJson); else throw new IllegalStateException("Can not process " + artifact + " as it does not have a MCPConfig ror official mappings"); @@ -300,11 +300,26 @@ protected void finalize(Artifact module, Mappings mappings, List stub(input, pending.artifact())); + } + + private File stub(Task inputTask, Artifact artifact) { var tool = this.cache.maven().download(Constants.STUBIFY); + var target = new File(this.cache.localCache(), artifact.appendClassifier("stub").getLocalPath()); + var input = inputTask.execute(); + var cache = Util.cache(target) .add("tool", tool) - .add("source", source); + .add("input", input); if (Mavenizer.checkCache(target, cache)) - return; + return target; - File jdk; - try { - jdk = this.cache.jdks().get(Constants.STUBIFY_JAVA_VERSION); - } catch (Exception e) { - throw new IllegalStateException("Failed to find JDK for version " + Constants.STUBIFY_JAVA_VERSION, e); - } + var args = List.of("--input", input.getAbsolutePath(), "--output", target.getAbsolutePath()); + execute("stubify", Constants.STUBIFY_JAVA_VERSION, tool, args, target); - var log = new File(source.getAbsolutePath() + ".stubify.log"); - var ret = ProcessUtils.runJar(jdk, source.getParentFile(), log, tool, Collections.emptyList(), - List.of("--input", source.getAbsolutePath(), "--output", target.getAbsolutePath()) - ); - if (ret.exitCode != 0) - throw new IllegalStateException("Failed to stubify jar file (exit code " + ret.exitCode + "), See log: " + log.getAbsolutePath()); + cache.save(); + return target; + } - try { - cache.save(); - HashUtils.updateHash(target); - } catch (Throwable t) { - throw new RuntimeException("Failed to generate artifact: %s".formatted(artifact), t); - } + private Task accessTransform(PendingArtifact pending) { + var input = pending.task(); + return Task.named("access-transform", Task.deps(input), () -> accessTransform(input, pending.artifact())); } - private void writeAccessTransformed(File target, File source, Artifact artifact) { + private File accessTransform(Task inputTask, Artifact artifact) { var tool = this.cache.maven().download(Constants.ACCESS_TRANSFORMER); + var target = new File(this.cache.localCache(), artifact.appendClassifier("ated").getLocalPath()); + var input = inputTask.execute(); + var cache = Util.cache(target) .add("tool", tool) .add(accessTransformer) - .add("source", source); + .add("input", input); if (Mavenizer.checkCache(target, cache)) - return; - - File jdk; - try { - jdk = this.cache.jdks().get(Constants.ACCESS_TRANSFORMER_JAVA_VERSION); - } catch (Exception e) { - throw new IllegalStateException("Failed to find JDK for version " + Constants.ACCESS_TRANSFORMER_JAVA_VERSION, e); - } + return target; - var log = new File(source.getAbsolutePath() + ".accesstransformer.log"); var args = new ArrayList<>(List.of( - "--inJar", source.getAbsolutePath(), + "--inJar", input.getAbsolutePath(), "--outJar", target.getAbsolutePath() )); + for (var file : accessTransformer) { if (!file.exists()) throw new IllegalStateException("Access Transformer config does not exist: " + file.getAbsolutePath()); @@ -464,21 +459,65 @@ private void writeAccessTransformed(File target, File source, Artifact artifact) args.add(file.getAbsolutePath()); } + execute("Access Transform", Constants.ACCESS_TRANSFORMER_JAVA_VERSION, tool, args, target); + cache.save(); + return target; + } + + private Task facade(PendingArtifact pending) { + var input = pending.task(); + return Task.named("facade", Task.deps(input), () -> facade(input, pending.artifact())); + } + + private File facade(Task inputTask, Artifact artifact) { + var tool = this.cache.maven().download(Constants.FACADE); + var target = new File(this.cache.localCache(), artifact.appendClassifier("facade").getLocalPath()); + var input = inputTask.execute(); + + var cache = Util.cache(target) + .add("tool", tool) + .add(facadeConfigs) + .add("input", input); + + if (Mavenizer.checkCache(target, cache)) + return target; + + var args = new ArrayList<>(List.of( + "--input", input.getAbsolutePath(), + "--output", target.getAbsolutePath() + )); + + for (var file : facadeConfigs) { + if (!file.exists()) + throw new IllegalStateException("Facade config does not exist: " + file.getAbsolutePath()); + args.add("--config"); + args.add(file.getAbsolutePath()); + } + + execute("facade ", Constants.FACAD_JAVA_VERSION, tool, args, target); + cache.save(); + return target; + } + + private void execute(String name, int javaVersion, File tool, List args, File target) { + File jdk; + try { + jdk = this.cache.jdks().get(javaVersion); + } catch (Exception e) { + throw new IllegalStateException("Failed to find JDK for version " + javaVersion, e); + } + // Older versions of AT have a bug where it wont create the directories as needed. var parent = target.getParentFile(); if (parent != null && !parent.exists()) parent.mkdirs(); - var ret = ProcessUtils.runJar(jdk, source.getParentFile(), log, tool, Collections.emptyList(), args); + + var log = new File(target.getAbsolutePath() + ".log"); + var ret = ProcessUtils.runJar(jdk, parent, log, tool, Collections.emptyList(), args); if (ret.exitCode != 0) - throw new IllegalStateException("Failed to Access Transform jar file (exit code " + ret.exitCode + "), See log: " + log.getAbsolutePath()); + throw new IllegalStateException("Failed to " + name + " file (exit code " + ret.exitCode + "), See log: " + log.getAbsolutePath()); - try { - cache.save(); - HashUtils.updateHash(target); - } catch (Throwable t) { - throw new RuntimeException("Failed to generate artifact: %s".formatted(artifact), t); - } } private void updateVariants(Artifact artifact) { diff --git a/src/main/java/net/minecraftforge/mcmaven/impl/cache/Cache.java b/src/main/java/net/minecraftforge/mcmaven/impl/cache/Cache.java index 5c9231e..b0b4c70 100644 --- a/src/main/java/net/minecraftforge/mcmaven/impl/cache/Cache.java +++ b/src/main/java/net/minecraftforge/mcmaven/impl/cache/Cache.java @@ -10,7 +10,7 @@ import java.util.Map; /** Represents the cache for this tool. */ -public record Cache(File root, JDKCache jdks, MavenCache maven, MinecraftMavenCache minecraft) { +public record Cache(File root, File localCache, JDKCache jdks, MavenCache maven, MinecraftMavenCache minecraft) { /** * Makes a new cache with the given root and JDK cache directories. * @@ -18,10 +18,15 @@ public record Cache(File root, JDKCache jdks, MavenCache maven, MinecraftMavenCa * @param jdkCache The JDK cache directory. */ public Cache(File root, File jdkCache) { - this(root, jdkCache, Map.of()); + this(root, new File(root, "local"), jdkCache, Map.of()); } - public Cache(File root, File jdkCache, Map foreignRepositories) { - this(root, new JDKCache(jdkCache), new MavenCache(Constants.FORGE_NAME, Constants.FORGE_MAVEN, root, foreignRepositories), new MinecraftMavenCache(root)); + public Cache(File root, File localCache, File jdkCache, Map foreignRepositories) { + this(root, + localCache, + new JDKCache(jdkCache), + new MavenCache(Constants.FORGE_NAME, Constants.FORGE_MAVEN, root, foreignRepositories), + new MinecraftMavenCache(root) + ); } } diff --git a/src/main/java/net/minecraftforge/mcmaven/impl/repo/Repo.java b/src/main/java/net/minecraftforge/mcmaven/impl/repo/Repo.java index b964e54..2c179fb 100644 --- a/src/main/java/net/minecraftforge/mcmaven/impl/repo/Repo.java +++ b/src/main/java/net/minecraftforge/mcmaven/impl/repo/Repo.java @@ -272,6 +272,10 @@ public Task getAsTask() { public PendingArtifact withVariants(Supplier variants) { return new PendingArtifact(message, task, artifact, auxiliary, variantTask(task, variants)); } + + public PendingArtifact withTask(Task task) { + return new PendingArtifact(message, task, artifact, auxiliary, variants); + } } /* diff --git a/src/main/java/net/minecraftforge/mcmaven/impl/util/Artifact.java b/src/main/java/net/minecraftforge/mcmaven/impl/util/Artifact.java index 802932b..5c05472 100644 --- a/src/main/java/net/minecraftforge/mcmaven/impl/util/Artifact.java +++ b/src/main/java/net/minecraftforge/mcmaven/impl/util/Artifact.java @@ -278,6 +278,10 @@ public Artifact withClassifier(String classifier) { return new Artifact(group, name, version, classifier, ext, os, arch); } + public Artifact appendClassifier(String classifier) { + return withClassifier(this.classifier == null ? classifier : this.classifier + '-' + classifier); + } + public Artifact withExtension(String ext) { return new Artifact(group, name, version, classifier, ext, os, arch); } diff --git a/src/main/java/net/minecraftforge/mcmaven/impl/util/Constants.java b/src/main/java/net/minecraftforge/mcmaven/impl/util/Constants.java index 1907fba..4066771 100644 --- a/src/main/java/net/minecraftforge/mcmaven/impl/util/Constants.java +++ b/src/main/java/net/minecraftforge/mcmaven/impl/util/Constants.java @@ -39,4 +39,7 @@ public final class Constants { public static final Artifact STUBIFY = Artifact.from("net.minecraftforge:jar-stubify:1.0.0"); public static final int STUBIFY_JAVA_VERSION = 25; + + public static final Artifact FACADE = Artifact.from("net.minecraftforge:facade:1.0.0"); + public static final int FACAD_JAVA_VERSION = 25; }