diff --git a/src/main/java/org/moe/gradle/MoeExtension.java b/src/main/java/org/moe/gradle/MoeExtension.java index c0040e2..e9f2112 100644 --- a/src/main/java/org/moe/gradle/MoeExtension.java +++ b/src/main/java/org/moe/gradle/MoeExtension.java @@ -145,12 +145,9 @@ public void setProguardLevel(@NotNull String proguardLevel) { } @Nullable + @org.jetbrains.annotations.Nullable public File getPlatformJar() { return plugin.getSDK().getPlatformJar(platform); } - @Nullable - public File getPlatformDex() { - return plugin.getSDK().getPlatformDex(platform); - } } diff --git a/src/main/java/org/moe/gradle/MoePlugin.java b/src/main/java/org/moe/gradle/MoePlugin.java index 7671bc8..8b04e43 100644 --- a/src/main/java/org/moe/gradle/MoePlugin.java +++ b/src/main/java/org/moe/gradle/MoePlugin.java @@ -28,6 +28,7 @@ import org.moe.gradle.anns.Nullable; import org.moe.gradle.remote.Server; import org.moe.gradle.tasks.AbstractBaseTask; +import org.moe.gradle.tasks.Desugar; import org.moe.gradle.tasks.Dex; import org.moe.gradle.tasks.Dex2Oat; import org.moe.gradle.tasks.ClassValidate; @@ -137,6 +138,8 @@ public void apply(Project project) { // Install rules addRule(ProGuard.class, "Creates a ProGuarded jar.", asList(SOURCE_SET, MODE), MoePlugin.this); + addRule(Desugar.class, "Creates a desugared jar.", + asList(SOURCE_SET, MODE), MoePlugin.this); addRule(ClassValidate.class, "Validate classes.", asList(SOURCE_SET, MODE), MoePlugin.this); addRule(Dex.class, "Creates a Dexed jar.", diff --git a/src/main/java/org/moe/gradle/MoeSDK.java b/src/main/java/org/moe/gradle/MoeSDK.java index d2fa03b..7ce312b 100644 --- a/src/main/java/org/moe/gradle/MoeSDK.java +++ b/src/main/java/org/moe/gradle/MoeSDK.java @@ -349,17 +349,14 @@ private void validateSDK(@NotNull Path path, boolean isLocalSDK) { try { validate(DIR, path, ""); - validate(FIL, path, "sdk/moe-core.dex"); validate(FIL, path, "sdk/moe-core.jar"); validate(FIL, path, "sdk/moe-core-javadoc.jar"); validate(FIL, path, "sdk/moe-core-sources.jar"); - validate(FIL, path, "sdk/moe-ios-junit.dex"); validate(FIL, path, "sdk/moe-ios-junit.jar"); validate(FIL, path, "sdk/moe-ios-junit-javadoc.jar"); validate(FIL, path, "sdk/moe-ios-junit-sources.jar"); - validate(FIL, path, "sdk/moe-ios-dex.jar"); validate(FIL, path, "sdk/moe-ios.jar"); validate(FIL, path, "sdk/moe-ios-javadoc.jar"); validate(FIL, path, "sdk/moe-ios-sources.jar"); @@ -413,15 +410,12 @@ private void validate(int type, @NotNull Path path, @NotNull String sub) throws private @Nullable File MOE_SDK_CORE_JAR; private @Nullable File MOE_SDK_CORE_SOURCES_JAR; private @Nullable File MOE_SDK_CORE_JAVADOC_JAR; - private @Nullable File MOE_SDK_CORE_DEX; private @Nullable File MOE_SDK_IOS_JAVADOC_JAR; private @Nullable File MOE_SDK_IOS_JUNIT_JAR; private @Nullable File MOE_SDK_IOS_JUNIT_SOURCES_JAR; private @Nullable File MOE_SDK_IOS_JUNIT_JAVADOC_JAR; - private @Nullable File MOE_SDK_IOS_JUNIT_DEX; private @Nullable File MOE_SDK_IOS_JAR; private @Nullable File MOE_SDK_IOS_SOURCES_JAR; - private @Nullable File MOE_SDK_IOS_DEX; private @Nullable File MOE_SDK_DEX2OAT_EXEC; private @Nullable File MOE_SDK_DX_JAR; private @Nullable File MOE_SDK_IOS_DEVICE_JAR; @@ -440,15 +434,12 @@ private void bakeSDKPaths(@NotNull Path path) { MOE_SDK_SDK_DIR = path.resolve("sdk").toFile(); MOE_SDK_TOOLS_DIR = path.resolve("tools").toFile(); MOE_SDK_CORE_JAR = path.resolve("sdk/moe-core.jar").toFile(); - MOE_SDK_CORE_DEX = path.resolve("sdk/moe-core.dex").toFile(); MOE_SDK_CORE_SOURCES_JAR = path.resolve("sdk/moe-core-sources.jar").toFile(); MOE_SDK_CORE_JAVADOC_JAR = path.resolve("sdk/moe-core-javadoc.jar").toFile(); - MOE_SDK_IOS_DEX = path.resolve("sdk/moe-ios-dex.jar").toFile(); MOE_SDK_IOS_JAR = path.resolve("sdk/moe-ios.jar").toFile(); MOE_SDK_IOS_SOURCES_JAR = path.resolve("sdk/moe-ios-sources.jar").toFile(); MOE_SDK_IOS_JAVADOC_JAR = path.resolve("sdk/moe-ios-javadoc.jar").toFile(); MOE_SDK_IOS_JUNIT_JAR = path.resolve("sdk/moe-ios-junit.jar").toFile(); - MOE_SDK_IOS_JUNIT_DEX = path.resolve("sdk/moe-ios-junit.dex").toFile(); MOE_SDK_IOS_JUNIT_SOURCES_JAR = path.resolve("sdk/moe-ios-junit-sources.jar").toFile(); MOE_SDK_IOS_JUNIT_JAVADOC_JAR = path.resolve("sdk/moe-ios-junit-javadoc.jar").toFile(); MOE_SDK_DEX2OAT_EXEC = path.resolve("tools/dex2oat").toFile(); @@ -498,11 +489,6 @@ public File getCoreSourcesJar() { return safeVariable(MOE_SDK_CORE_SOURCES_JAR, "MOE_SDK_CORE_SOURCES_JAR"); } - @NotNull - public File getCoreDex() { - return safeVariable(MOE_SDK_CORE_DEX, "MOE_SDK_CORE_DEX"); - } - @NotNull @IgnoreUnused public File getiOSJavadocJar() { @@ -532,22 +518,11 @@ public File getiOSJUnitSourcesJar() { return safeVariable(MOE_SDK_IOS_JUNIT_SOURCES_JAR, "MOE_SDK_IOS_JUNIT_SOURCES_JAR"); } - @NotNull - @IgnoreUnused - public File getiOSJUnitDex() { - return safeVariable(MOE_SDK_IOS_JUNIT_DEX, "MOE_SDK_IOS_JUNIT_DEX"); - } - @NotNull private File getiOSJar() { return safeVariable(MOE_SDK_IOS_JAR, "MOE_SDK_IOS_JAR"); } - @NotNull - private File getiOSDex() { - return safeVariable(MOE_SDK_IOS_DEX, "MOE_SDK_IOS_DEX"); - } - @NotNull public File getDex2OatExec() { return safeVariable(MOE_SDK_DEX2OAT_EXEC, "MOE_SDK_DEX2OAT_EXEC"); @@ -619,14 +594,6 @@ public File getPlatformJar(final @NotNull MoePlatform platform) { throw new GradleException("platform jar is unsupported for " + platform.displayName); } - @NotNull - public File getPlatformDex(final @NotNull MoePlatform platform) { - if (platform == MoePlatform.IOS) { - return getiOSDex(); - } - throw new GradleException("platform dex is unsupported for " + platform.displayName); - } - @NotNull private static T safeVariable(@Nullable T variable, @NotNull String name) { return Require.nonNull(variable, "Unable to access MOE SDK variable '" + name + "'"); diff --git a/src/main/java/org/moe/gradle/tasks/AbstractBaseTask.java b/src/main/java/org/moe/gradle/tasks/AbstractBaseTask.java index 7cd0cf7..2c5db3b 100644 --- a/src/main/java/org/moe/gradle/tasks/AbstractBaseTask.java +++ b/src/main/java/org/moe/gradle/tasks/AbstractBaseTask.java @@ -148,6 +148,7 @@ public Object doCall() { @SuppressWarnings("unchecked") @NotNull + @org.jetbrains.annotations.NotNull public T getOrConvention(@Nullable T value, @NotNull String name) { Require.nonNull(name); @@ -165,6 +166,7 @@ public T getOrConvention(@Nullable T value, @NotNull String name) { @SuppressWarnings("unchecked") @Nullable + @org.jetbrains.annotations.Nullable public T nullableGetOrConvention(@Nullable T value, @NotNull String name) { Require.nonNull(name); diff --git a/src/main/java/org/moe/gradle/tasks/Dex2Oat.java b/src/main/java/org/moe/gradle/tasks/Dex2Oat.java index c3cfb20..4310962 100644 --- a/src/main/java/org/moe/gradle/tasks/Dex2Oat.java +++ b/src/main/java/org/moe/gradle/tasks/Dex2Oat.java @@ -25,13 +25,11 @@ import org.gradle.api.tasks.OutputFile; import org.gradle.api.tasks.SourceSet; import org.moe.common.utils.NativeUtil; -import org.moe.gradle.MoeExtension; import org.moe.gradle.MoePlugin; import org.moe.gradle.MoeSDK; import org.moe.gradle.anns.IgnoreUnused; import org.moe.gradle.anns.NotNull; import org.moe.gradle.anns.Nullable; -import org.moe.gradle.options.ProGuardOptions; import org.moe.gradle.remote.Server; import org.moe.gradle.remote.file.FileList; import org.moe.gradle.utils.Arch; @@ -328,7 +326,6 @@ protected final void setupMoeTask(@NotNull SourceSet sourceSet, @NotNull Mode mo setSupportsRemoteBuild(true); - final MoeExtension ext = getMoeExtension(); final MoeSDK sdk = getMoeSDK(); // Construct default output path @@ -363,23 +360,6 @@ protected final void setupMoeTask(@NotNull SourceSet sourceSet, @NotNull Mode mo addConvention(CONVENTION_INPUT_FILES, () -> { final Set files = new HashSet<>(); files.add(dexTask.getDestJar()); - - switch (ext.proguard.getLevelRaw()) { - case ProGuardOptions.LEVEL_APP: - files.add(sdk.getCoreDex()); - if (ext.getPlatformDex() != null) { - files.add(ext.getPlatformDex()); - } - break; - case ProGuardOptions.LEVEL_PLATFORM: - files.add(sdk.getCoreDex()); - break; - case ProGuardOptions.LEVEL_ALL: - break; - default: - throw new IllegalStateException(); - } - return files; }); addConvention(CONVENTION_COMPILER_BACKEND, () -> BACKEND_QUICK); diff --git a/src/main/java/org/moe/gradle/tasks/ProGuard.java b/src/main/java/org/moe/gradle/tasks/ProGuard.java index e1c6cd1..7e8c0f2 100644 --- a/src/main/java/org/moe/gradle/tasks/ProGuard.java +++ b/src/main/java/org/moe/gradle/tasks/ProGuard.java @@ -372,7 +372,7 @@ private void composeConfigurationFile() { FileUtils.write(getComposedCfgFile(), conf.toString()); } - private static void startSection(@NotNull final StringBuilder b, @NotNull final String comment) { + static void startSection(@NotNull final StringBuilder b, @NotNull final String comment) { int l = comment.length(); b.append("\n##"); for (int i = 0; i < l; ++i) diff --git a/src/main/java/org/moe/gradle/tasks/ResourcePackager.java b/src/main/java/org/moe/gradle/tasks/ResourcePackager.java index d49fd4c..801ca09 100644 --- a/src/main/java/org/moe/gradle/tasks/ResourcePackager.java +++ b/src/main/java/org/moe/gradle/tasks/ResourcePackager.java @@ -107,7 +107,9 @@ private static Jar create(@NotNull MoePlugin plugin, @NotNull SourceSet sourceSe switch (ext.proguard.getLevelRaw()) { case ProGuardOptions.LEVEL_APP: resourcePackagerTask.from(_project.zipTree(sdk.getCoreJar())); - resourcePackagerTask.from(_project.zipTree(ext.getPlatformJar())); + if (ext.getPlatformJar() != null){ + resourcePackagerTask.from(_project.zipTree(ext.getPlatformJar())); + } break; case ProGuardOptions.LEVEL_PLATFORM: resourcePackagerTask.from(_project.zipTree(sdk.getCoreJar())); diff --git a/src/main/java/org/moe/gradle/tasks/XcodeBuild.java b/src/main/java/org/moe/gradle/tasks/XcodeBuild.java index 0bdbcac..2aad959 100644 --- a/src/main/java/org/moe/gradle/tasks/XcodeBuild.java +++ b/src/main/java/org/moe/gradle/tasks/XcodeBuild.java @@ -431,7 +431,12 @@ protected void run() { excludes.add(classValidateTask.getOutputDir()); excludes.add(classValidateTask.getLogFile()); - final ProGuard proGuardTask = classValidateTask.getProGuardTaskDep(); + final Desugar desugarTask = classValidateTask.getDesugarTaskDep(); + excludes.add(desugarTask.getOutJar()); + excludes.add(desugarTask.getComposedCfgFile()); + excludes.add(desugarTask.getLogFile()); + + final ProGuard proGuardTask = desugarTask.getProGuardTaskDep(); excludes.add(proGuardTask.getOutJar()); excludes.add(proGuardTask.getComposedCfgFile()); excludes.add(proGuardTask.getLogFile()); diff --git a/src/main/kotlin/org/moe/gradle/tasks/ClassValidate.kt b/src/main/kotlin/org/moe/gradle/tasks/ClassValidate.kt index 4e6aaef..2d3a524 100644 --- a/src/main/kotlin/org/moe/gradle/tasks/ClassValidate.kt +++ b/src/main/kotlin/org/moe/gradle/tasks/ClassValidate.kt @@ -74,7 +74,7 @@ open class ClassValidate : AbstractBaseTask() { } @get:Internal - lateinit var proGuardTaskDep: ProGuard + lateinit var desugarTaskDep: Desugar private set protected fun setupMoeTask( @@ -89,13 +89,13 @@ open class ClassValidate : AbstractBaseTask() { description = "Validate classes (sourceset: ${sourceSet.name}, mode: ${mode.name})." // Add dependencies - val proGuardTask = moePlugin.getTaskBy(ProGuard::class.java, sourceSet, mode) - proGuardTaskDep = proGuardTask - dependsOn(proGuardTask) + val desugarTask = moePlugin.getTaskBy(Desugar::class.java, sourceSet, mode) + desugarTaskDep = desugarTask + dependsOn(desugarTask) // Update convention mapping - addConvention(CONVENTION_INPUT_FILES) { setOf(proGuardTask.outJar) } - addConvention(CONVENTION_CLASSPATH_FILES) { setOf(proGuardTask.libraryJars) } + addConvention(CONVENTION_INPUT_FILES) { setOf(desugarTask.getOutJar()) } + addConvention(CONVENTION_CLASSPATH_FILES) { setOf(desugarTask.getLibraryJars()) } addConvention(CONVENTION_OUTPUT_DIR) { resolvePathInBuildDir(out, "output") } addConvention(CONVENTION_LOG_FILE) { resolvePathInBuildDir(out, "ClassValidate.log") } } diff --git a/src/main/kotlin/org/moe/gradle/tasks/Desugar.kt b/src/main/kotlin/org/moe/gradle/tasks/Desugar.kt new file mode 100644 index 0000000..b3aad4d --- /dev/null +++ b/src/main/kotlin/org/moe/gradle/tasks/Desugar.kt @@ -0,0 +1,201 @@ +package org.moe.gradle.tasks + +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.logging.Logging +import org.gradle.api.tasks.InputFile +import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.OutputFile +import org.gradle.api.tasks.SourceSet +import org.moe.gradle.MoePlugin +import org.moe.gradle.anns.IgnoreUnused +import org.moe.gradle.anns.NotNull +import org.moe.gradle.options.ProGuardOptions +import org.moe.gradle.utils.FileUtils +import org.moe.gradle.utils.Mode +import java.io.File +import java.nio.file.Paths + +open class Desugar : AbstractBaseTask() { + + @InputFile + @NotNull + fun getProGuardJar(): File { + return proGuardTaskDep.proGuardJar + } + + private var inJars: Set? = null + + @InputFiles + @NotNull + fun getInJars(): ConfigurableFileCollection { + return project.files(getOrConvention(inJars, CONVENTION_IN_JARS)) + } + + @IgnoreUnused + fun setInJars(inJars: Collection?) { + this.inJars = inJars?.toSet() + } + + private var libraryJars: Set? = null + + @InputFiles + @NotNull + fun getLibraryJars(): ConfigurableFileCollection { + return project.files(getOrConvention(libraryJars, CONVENTION_LIBRARY_JARS)) + } + + @IgnoreUnused + fun setLibraryJars(libraryJars: Collection?) { + this.libraryJars = libraryJars?.toSet() + } + + private var outJar: Any? = null + + @OutputFile + @NotNull + fun getOutJar(): File { + return project.file(getOrConvention(outJar, CONVENTION_OUT_JAR)) + } + + @IgnoreUnused + fun setOutJar(outJar: Any?) { + this.outJar = outJar + } + + private var composedCfgFile: Any? = null + + @OutputFile + @NotNull + fun getComposedCfgFile(): File { + return project.file(getOrConvention(composedCfgFile, CONVENTION_COMPOSED_CFG_FILE)) + } + + @IgnoreUnused + fun setComposedCfgFile(composedCfgFile: Any?) { + this.composedCfgFile = composedCfgFile + } + + override fun run() { + FileUtils.deleteFileOrFolder(getOutJar()) + + composeConfigurationFile() + javaexec { spec -> + spec.main = "-jar" + spec.args(getProGuardJar().absolutePath, "@" + getComposedCfgFile().absolutePath) + } + } + + private fun composeConfigurationFile() { + val conf = StringBuilder() + + // Add injars + ProGuard.startSection(conf, "Generating -injars") + getInJars().forEach { + if (it.exists()) { + conf.append("-injars ").append(it.absolutePath).append("\n") + } else { + LOG.debug("inJars file doesn't exist: " + it.absolutePath) + } + } + + // Add outjar + ProGuard.startSection(conf, "Generating -outjars") + conf.append("-outjars \"").append(getOutJar().absolutePath).append("\"\n") + + // Add libraryjars + ProGuard.startSection(conf, "Generating -libraryjars") + getLibraryJars().forEach { + if (it.exists()) { + conf.append("-libraryjars ").append(it.absolutePath).append("\n") + } else { + LOG.debug("libraryJars file doesn't exist: " + it.absolutePath) + } + } + + // Add backport configuration + ProGuard.startSection(conf, "Backport only") + conf.append( + """ + # Disable everything as we only want to backport + -dontshrink + -dontobfuscate + -dontoptimize + -dontwarn + -dontnote + + # Backport to Java 7 + -target 7 + """.trimIndent() + ) + + // Save + FileUtils.write(getComposedCfgFile(), conf.toString()) + } + + @get:Internal + lateinit var proGuardTaskDep: ProGuard + private set + + protected fun setupMoeTask( + @NotNull sourceSet: SourceSet, + @NotNull mode: Mode, + ) { + setSupportsRemoteBuild(false) + + // Construct default output path + val out = Paths.get(MoePlugin.MOE, sourceSet.name, "desugar", mode.name) + + description = "Desugar classes (sourceset: ${sourceSet.name}, mode: ${mode.name})." + + // Add dependencies + val proGuardTask = moePlugin.getTaskBy(ProGuard::class.java, sourceSet, mode) + proGuardTaskDep = proGuardTask + dependsOn(proGuardTask) + + // Update convention mapping + addConvention(CONVENTION_IN_JARS) { + mutableSetOf().apply { + add(proGuardTask.outJar) + + when (moeExtension.proguard.levelRaw) { + ProGuardOptions.LEVEL_APP -> { + add(moeSDK.coreJar) + moeExtension.platformJar?.let(::add) + } + ProGuardOptions.LEVEL_PLATFORM -> { + add(moeSDK.coreJar) + } + ProGuardOptions.LEVEL_ALL -> { + // Do nothing + } + else -> throw IllegalStateException() + } + + if (!project.hasProperty("moe.sdk.skip_java8support_jar")) { + add(moeSDK.java8SupportJar) + } + } + } + addConvention(CONVENTION_LIBRARY_JARS) { + mutableSetOf().apply { + addAll(proGuardTask.libraryJars.files) + remove(moeSDK.coreJar) + remove(moeExtension.platformJar) + remove(moeSDK.java8SupportJar) + } + } + addConvention(CONVENTION_OUT_JAR) { resolvePathInBuildDir(out, "output.jar") } + addConvention(CONVENTION_COMPOSED_CFG_FILE) { resolvePathInBuildDir(out, "configuration.pro") } + addConvention(CONVENTION_LOG_FILE) { resolvePathInBuildDir(out, "Desugar.log") } + } + + companion object { + private val LOG = Logging.getLogger(Desugar::class.java) + + private const val CONVENTION_IN_JARS = "inJars" + private const val CONVENTION_LIBRARY_JARS = "libraryJars" + private const val CONVENTION_OUT_JAR = "outJar" + private const val CONVENTION_COMPOSED_CFG_FILE = "composedCfgFile" + } +}