diff --git a/build.gradle b/build.gradle index 0ac9ff0..fe84ab5 100644 --- a/build.gradle +++ b/build.gradle @@ -36,7 +36,7 @@ subprojects{ subproject -> apply plugin: 'kotlin' group = 'com.github.marcoferrer.krotoplus' - version = '0.5.0' + version = '0.6.0-SNAPSHOT' compileKotlin { kotlinOptions.jvmTarget = "1.8" @@ -54,7 +54,6 @@ subprojects{ subproject -> testImplementation "org.jetbrains.kotlin:kotlin-test-junit" } - tasks.withType(Test) { testLogging { // set options for log level LIFECYCLE @@ -99,4 +98,25 @@ subprojects{ subproject -> } } } + + subproject.ext{ + localPluginPath = [ + "kroto": "${rootProject.projectDir}/protoc-gen-kroto-plus/build/libs/protoc-gen-kroto-plus-${project.version}-${osdetector.classifier}.exe", + "coroutines": "${rootProject.projectDir}/protoc-gen-grpc-coroutines/build/libs/protoc-gen-grpc-coroutines-${project.version}-${osdetector.classifier}.exe" + ] + + configProtoTaskWithKroto = { task, krotoConfig -> + task.inputs.files krotoConfig + task.dependsOn ':protoc-gen-kroto-plus:buildCanteenArtifacts' + task.plugins { + kroto { + outputSubDir = "java" + // We want to relativize the configuration path + // because absolute paths cause issues in windows + // environments + option "ConfigPath=${krotoConfig.absolutePath.replace(rootProject.projectDir.path, "").drop(1)}" + } + } + } + } } \ No newline at end of file diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index fe94d80..8ab46d1 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -4,4 +4,8 @@ plugins { repositories { jcenter() } - \ No newline at end of file + +dependencies { + // Needed by the script 'canteen.gradle' + implementation("com.google.guava:guava:27.0.1-jre") +} \ No newline at end of file diff --git a/canteen.gradle b/canteen.gradle new file mode 100644 index 0000000..b92cc53 --- /dev/null +++ b/canteen.gradle @@ -0,0 +1,81 @@ +// The following dependency needs to exist on the 'buildscript' classpath +// 'com.google.guava:guava:27.0.1-jre' +// It is currently added via the buildSrc project +import com.google.common.io.ByteStreams + +// Native artifact generation based off of +// https://github.com/salesforce/grpc-java-contrib/tree/master/canteen + +def platforms = ["osx-x86_64", "linux-x86_64", "windows-x86_64"] + +Task bootJarTask = tasks.getByName("bootJar") +File bootJarFile = bootJarTask.archiveFile.get().asFile + +platforms.each { platform -> + + // Resolve the canteen bootstrap artifact + Configuration config = project.configurations.create("canteenBootstrapLocator_$platform") { + visible = false + transitive = false + extendsFrom = [] + } + Map notation = [ + group: "com.salesforce.servicelibs", + name: "canteen-bootstrap", + version: "1.0.0", + classifier: platform, + ext: "exe", + ] + Dependency dep = project.dependencies.add(config.name, notation) + File bootstrapFile = config.fileCollection(dep).singleFile + File destinationArtifactFile = new File(bootJarTask.destinationDirectory.get().asFile, + bootJarFile.name.replace("jvm8.jar", platform + ".exe")) + + // Create task to copy the original jar and embed the + // canteen bootstrap executable for the target platform + Task canteenTask = task("canteenArtifact_$platform"){ + group = "canteen" + dependsOn("bootJar") + // Add files for UP-TO-DATE checks + inputs.files(bootJarFile) + outputs.files(destinationArtifactFile) + doLast { + // Build the bootstrap file + OutputStream targetStream = new FileOutputStream(destinationArtifactFile) + InputStream bootstrapStream = new FileInputStream(bootstrapFile) + ByteStreams.copy(bootstrapStream, targetStream); + InputStream sourceStream = new FileInputStream(bootJarFile) + ByteStreams.copy(sourceStream, targetStream); + targetStream.flush() + targetStream.close() + sourceStream.close() + bootstrapStream.close() + destinationArtifactFile.setExecutable(true); + } + } + + artifacts { + archives(destinationArtifactFile) { + builtBy canteenTask + classifier platform + } + } + + publishing { + publications { + mavenPublication(MavenPublication) { + artifact(destinationArtifactFile.absolutePath) { + builtBy canteenTask + classifier platform + } + } + } + } +} + +task buildCanteenArtifacts{ + group = "canteen" + platforms.each { platform -> + dependsOn("canteenArtifact_$platform") + } +} diff --git a/example-project/build.gradle b/example-project/build.gradle index 468b062..2a13dc2 100644 --- a/example-project/build.gradle +++ b/example-project/build.gradle @@ -5,7 +5,7 @@ buildscript { "grpc": '1.23.0', "kotlin": '1.3.50', "coroutines": '1.3.0', - "krotoplus": '0.5.0' + "krotoplus": '0.6.0-SNAPSHOT' ] } @@ -89,7 +89,7 @@ protobuf { plugins { grpc { artifact = "io.grpc:protoc-gen-grpc-java:${versions.grpc}" } kroto { - artifact = "com.github.marcoferrer.krotoplus:protoc-gen-kroto-plus:${versions.krotoplus}:jvm8@jar" + artifact = "com.github.marcoferrer.krotoplus:protoc-gen-kroto-plus:${versions.krotoplus}" } } diff --git a/kroto-plus-coroutines/benchmark/build.gradle b/kroto-plus-coroutines/benchmark/build.gradle index d008603..8e2153f 100644 --- a/kroto-plus-coroutines/benchmark/build.gradle +++ b/kroto-plus-coroutines/benchmark/build.gradle @@ -37,7 +37,7 @@ protobuf { //noinspection GroovyAssignabilityCheck plugins { kroto { - path = "${rootProject.projectDir}/protoc-gen-kroto-plus/build/libs/protoc-gen-kroto-plus-${project.version}-jvm8.jar" + path = localPluginPath.kroto } } @@ -45,17 +45,10 @@ protobuf { def krotoConfig = file("krotoPlusConfig.asciipb") all().each{ task -> - task.inputs.files krotoConfig - task.dependsOn ':protoc-gen-kroto-plus:bootJar' - + configProtoTaskWithKroto(task, krotoConfig) task.builtins { remove java } - task.plugins { - kroto { - option "ConfigPath=$krotoConfig" - } - } } } } diff --git a/kroto-plus-coroutines/build.gradle b/kroto-plus-coroutines/build.gradle index 4ad3e8b..56b0c8a 100644 --- a/kroto-plus-coroutines/build.gradle +++ b/kroto-plus-coroutines/build.gradle @@ -63,14 +63,13 @@ protobuf { //noinspection GroovyAssignabilityCheck plugins { coroutines { - path = "${rootProject.projectDir}/protoc-gen-grpc-coroutines/build/libs/protoc-gen-grpc-coroutines-${project.version}-jvm8.jar" + path = localPluginPath.coroutines } } generateProtoTasks { - all().each{ task -> - task.dependsOn ':protoc-gen-grpc-coroutines:bootJar' + task.dependsOn ':protoc-gen-grpc-coroutines:buildCanteenArtifacts' task.builtins { remove java } diff --git a/kroto-plus-gradle-plugin/build.gradle b/kroto-plus-gradle-plugin/build.gradle index 17ede27..b8668f6 100644 --- a/kroto-plus-gradle-plugin/build.gradle +++ b/kroto-plus-gradle-plugin/build.gradle @@ -43,20 +43,19 @@ protobuf { //noinspection GroovyAssignabilityCheck plugins { kroto { - artifact = "com.github.marcoferrer.krotoplus:protoc-gen-kroto-plus:0.1.3:jvm8@jar" + path = localPluginPath.kroto } } generateProtoTasks { def krotoConfig = file("krotoPlusConfig.asciipb") - all().each{ task -> + all().each { task -> task.inputs.files krotoConfig - task.dependsOn ':kroto-plus-gradle-plugin:gen-config-dsl:jar' + task.dependsOn ':protoc-gen-kroto-plus:buildCanteenArtifacts' task.plugins { kroto { outputSubDir = "java" - option "ConfigPath=$krotoConfig" } } } diff --git a/protoc-gen-grpc-coroutines/build.gradle b/protoc-gen-grpc-coroutines/build.gradle index 570437e..eed30d8 100644 --- a/protoc-gen-grpc-coroutines/build.gradle +++ b/protoc-gen-grpc-coroutines/build.gradle @@ -31,6 +31,8 @@ bootJar { } } +apply from: "${rootProject.projectDir}/canteen.gradle" + jar.enabled = true artifacts { diff --git a/protoc-gen-kroto-plus/build.gradle b/protoc-gen-kroto-plus/build.gradle index 4fdd5c8..667aa6b 100644 --- a/protoc-gen-kroto-plus/build.gradle +++ b/protoc-gen-kroto-plus/build.gradle @@ -83,6 +83,8 @@ bootJar { } } +apply from: "${rootProject.projectDir}/canteen.gradle" + jar.enabled = true artifacts { diff --git a/protoc-gen-kroto-plus/generator-tests/build.gradle b/protoc-gen-kroto-plus/generator-tests/build.gradle index 3c5db56..639c85c 100644 --- a/protoc-gen-kroto-plus/generator-tests/build.gradle +++ b/protoc-gen-kroto-plus/generator-tests/build.gradle @@ -42,7 +42,7 @@ protobuf { //noinspection GroovyAssignabilityCheck plugins { kroto { - path = "${rootProject.projectDir}/protoc-gen-kroto-plus/build/libs/protoc-gen-kroto-plus-${project.version}-jvm8.jar" + path = localPluginPath.kroto } } @@ -50,15 +50,7 @@ protobuf { def krotoConfig = file("krotoPlusConfig.asciipb") all().each{ task -> - task.inputs.files krotoConfig - task.dependsOn ':protoc-gen-kroto-plus:bootJar' - - task.plugins { - kroto { - outputSubDir = "java" - option "ConfigPath=$krotoConfig" - } - } + configProtoTaskWithKroto(task, krotoConfig) } } } diff --git a/protoc-gen-kroto-plus/src/main/kotlin/com/github/marcoferrer/krotoplus/generators/GeneratorContext.kt b/protoc-gen-kroto-plus/src/main/kotlin/com/github/marcoferrer/krotoplus/generators/GeneratorContext.kt index 1b46092..29bd365 100644 --- a/protoc-gen-kroto-plus/src/main/kotlin/com/github/marcoferrer/krotoplus/generators/GeneratorContext.kt +++ b/protoc-gen-kroto-plus/src/main/kotlin/com/github/marcoferrer/krotoplus/generators/GeneratorContext.kt @@ -35,36 +35,47 @@ data class GeneratorContext( val args: CompilerArgs = request.parseArgs(), val config: CompilerConfig = args.getCompilerConfig() ) { - val currentWorkingDir by lazy { - args.options[ARG_KEY_CONFIG_PATH] - ?.firstOrNull() - ?.let { path -> File(path).parentFile.takeIf { it.exists() } } - .sure { - "Unable to resolve current working directory. " + - "protoc option '$ARG_KEY_CONFIG_PATH' is not configured" - } - } -} + val currentWorkingDir: File by lazy { + if(args.configPath.isNullOrEmpty()) File(USER_DIR) else { + val workingDir = args.getConfigFile().parentFile -fun CompilerArgs.getCompilerConfig(): CompilerConfig = - options[ARG_KEY_CONFIG_PATH] - ?.firstOrNull() - ?.let { path -> - val configFile = File(path) - configFile + workingDir .takeIf { it.exists() } - ?: error("Config file does not exist. '${configFile.absolutePath}'") + .sure { "Unable to resolve current working directory. '$workingDir'" } } - ?.let { configFile -> - CompilerConfig.newBuilder().also { builder -> - when (configFile.extension.toLowerCase()) { - "json" -> JsonFormat.parser().merge(configFile.readText(), builder) - "asciipb" -> TextFormat.getParser().merge(configFile.readText(), builder) - "yaml", "yml" -> { - val jsonString = yamlToJson(configFile.readText()) - JsonFormat.parser().merge(jsonString, builder) - } - } - }.build() + } +} + +fun CompilerArgs.getCompilerConfig(): CompilerConfig { + if(configPath.isNullOrEmpty()) + return CompilerConfig.getDefaultInstance() + + val configFile = getConfigFile() + + return CompilerConfig.newBuilder().also { builder -> + when (configFile.extension.toLowerCase()) { + "json" -> JsonFormat.parser().merge(configFile.readText(), builder) + "asciipb" -> TextFormat.getParser().merge(configFile.readText(), builder) + "yaml", "yml" -> { + val jsonString = yamlToJson(configFile.readText()) + JsonFormat.parser().merge(jsonString, builder) + } } - ?: CompilerConfig.getDefaultInstance() + }.build() +} + +private fun CompilerArgs.getConfigFile(): File { + val configPath = configPath ?: error("protoc option '$ARG_KEY_CONFIG_PATH' is not configured") + + val configFile = File(USER_DIR).resolve(File(configPath)) + + return configFile + .takeIf { it.exists() } + ?: error("Config file does not exist. '${configFile.absolutePath}'") +} + +private val CompilerArgs.configPath: String? + get() = options[ARG_KEY_CONFIG_PATH]?.firstOrNull() + +private val USER_DIR: String + get() = System.getProperty("user.dir") \ No newline at end of file