diff --git a/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy b/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy index 4ce6d6d1..0ce54372 100644 --- a/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy @@ -46,6 +46,7 @@ import org.gradle.api.file.ProjectLayout import org.gradle.api.file.SourceDirectorySet import org.gradle.api.logging.LogLevel import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property import org.gradle.api.provider.Provider import org.gradle.api.provider.ProviderFactory import org.gradle.api.tasks.CacheableTask @@ -95,6 +96,10 @@ public abstract class GenerateProtoTask extends DefaultTask { private final ProjectLayout projectLayout = project.layout private final ToolsLocator toolsLocator = project.extensions.findByType(ProtobufExtension).tools + @Input + final Property javaExecutablePath = objectFactory.property(String) + .convention(project.extensions.findByType(ProtobufExtension).javaExecutablePath) + // These fields are set by the Protobuf plugin only when initializing the // task. Ideally they should be final fields, but Gradle task cannot have // constructor arguments. We use the initializing flag to prevent users from @@ -210,15 +215,7 @@ public abstract class GenerateProtoTask extends DefaultTask { } static int getCmdLengthLimit(String os) { - return isWindows(os) ? WINDOWS_CMD_LENGTH_LIMIT : DEFAULT_CMD_LENGTH_LIMIT - } - - static boolean isWindows(String os) { - return os != null && os.toLowerCase(Locale.ROOT).indexOf("win") > -1 - } - - static boolean isWindows() { - return isWindows(System.getProperty("os.name")) + return Utils.isWindows(os) ? WINDOWS_CMD_LENGTH_LIMIT : DEFAULT_CMD_LENGTH_LIMIT } static String escapePathUnix(String path) { @@ -243,14 +240,6 @@ public abstract class GenerateProtoTask extends DefaultTask { } } - static String computeJavaExePath(boolean isWindows) throws IOException { - File java = new File(System.getProperty("java.home"), isWindows ? "bin/java.exe" : "bin/java") - if (!java.exists()) { - throw new IOException("Could not find java executable at " + java.path) - } - return java.path - } - void setOutputBaseDir(Provider outputBaseDir) { checkInitializing() Preconditions.checkState(this.outputBaseDir == null, 'outputBaseDir is already set') @@ -744,7 +733,7 @@ public abstract class GenerateProtoTask extends DefaultTask { */ private String createJarTrampolineScript(String jarAbsolutePath) { assert jarAbsolutePath.endsWith(JAR_SUFFIX) - boolean isWindows = isWindows() + boolean isWindows = Utils.isWindows() String jarFileName = new File(jarAbsolutePath).getName() if (jarFileName.length() <= JAR_SUFFIX.length()) { throw new GradleException(".jar protoc plugin path '${jarAbsolutePath}' has no file name") @@ -754,7 +743,7 @@ public abstract class GenerateProtoTask extends DefaultTask { (isWindows ? "bat" : "sh")) try { mkdirsForFile(scriptExecutableFile) - String javaExe = computeJavaExePath(isWindows) + String javaExe = javaExecutablePath.get() // Rewrite the trampoline file unconditionally (even if it already exists) in case the dependency or versioning // changes we don't need to detect the delta (and the file content is cheap to re-generate). String trampoline = isWindows ? @@ -762,7 +751,8 @@ public abstract class GenerateProtoTask extends DefaultTask { "#!/bin/sh\nexec '${escapePathUnix(javaExe)}' -jar '${escapePathUnix(jarAbsolutePath)}' \"\$@\"\n" scriptExecutableFile.write(trampoline, US_ASCII.name()) setExecutableOrFail(scriptExecutableFile) - logger.info("Resolved artifact jar: ${jarAbsolutePath}. Created trampoline file: ${scriptExecutableFile}") + logger.info("Resolved artifact jar: ${jarAbsolutePath}. " + + "Created trampoline file: ${scriptExecutableFile} with java executable ${javaExe}") return scriptExecutableFile.path } catch (IOException e) { throw new GradleException("Unable to generate trampoline for .jar protoc plugin", e) diff --git a/src/main/groovy/com/google/protobuf/gradle/ProtobufExtension.groovy b/src/main/groovy/com/google/protobuf/gradle/ProtobufExtension.groovy index 2e380022..c08d203f 100644 --- a/src/main/groovy/com/google/protobuf/gradle/ProtobufExtension.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/ProtobufExtension.groovy @@ -57,6 +57,9 @@ abstract class ProtobufExtension { @PackageScope final Provider defaultGeneratedFilesBaseDir + @PackageScope + final Provider defaultJavaExecutablePath + public ProtobufExtension(final Project project) { this.project = project this.tasks = new GenerateProtoTaskCollection(project) @@ -66,11 +69,23 @@ abstract class ProtobufExtension { it.asFile.path } this.generatedFilesBaseDirProperty.convention(defaultGeneratedFilesBaseDir) + this.defaultJavaExecutablePath = project.provider { + computeJavaExePath() + } + this.javaExecutablePath.convention(defaultJavaExecutablePath) this.sourceSets = project.objects.domainObjectContainer(ProtoSourceSet) { String name -> new DefaultProtoSourceSet(name, project.objects) } } + static String computeJavaExePath() throws IOException { + File java = new File(System.getProperty("java.home"), Utils.isWindows() ? "bin/java.exe" : "bin/java") + if (!java.exists()) { + throw new IOException("Could not find java executable at " + java.path) + } + return java.path + } + @PackageScope NamedDomainObjectContainer getSourceSets() { return this.sourceSets @@ -97,6 +112,13 @@ abstract class ProtobufExtension { @PackageScope abstract Property getGeneratedFilesBaseDirProperty() + /** + * The location of the java executable used to run java based + * code generation plugins. The default is the java executable + * running gradle. + */ + abstract Property getJavaExecutablePath() + @PackageScope void configureTasks() { this.taskConfigActions.each { action -> diff --git a/src/main/groovy/com/google/protobuf/gradle/Utils.groovy b/src/main/groovy/com/google/protobuf/gradle/Utils.groovy index 9ce0e679..215e65ed 100644 --- a/src/main/groovy/com/google/protobuf/gradle/Utils.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/Utils.groovy @@ -134,4 +134,12 @@ class Utils { } } } + + static boolean isWindows(String os) { + return os != null && os.toLowerCase(Locale.ROOT).indexOf("win") > -1 + } + + static boolean isWindows() { + return isWindows(System.getProperty("os.name")) + } }