Skip to content

Commit

Permalink
Updates PIG Gradle Plugin for publication (#145)
Browse files Browse the repository at this point in the history
  • Loading branch information
RCHowell authored Dec 7, 2022
1 parent 25de05c commit 26645c2
Show file tree
Hide file tree
Showing 6 changed files with 236 additions and 233 deletions.
42 changes: 22 additions & 20 deletions pig-gradle-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
plugins {
id("java-gradle-plugin")
id("org.jetbrains.kotlin.jvm") version "1.4.0"
id("com.gradle.plugin-publish") version "1.0.0"
id("com.gradle.plugin-publish") version "1.1.0"
}

repositories {
mavenCentral()
}

version = "0.5.1-SNAPSHOT"
object Versions {
const val pig = "0.6.1"
const val kotlinTarget = "1.4"
const val javaTarget = "1.8"
}

// latest maven central release
version = Versions.pig
group = "org.partiql"

dependencies {
// It is non-trivial to depend on a local plugin within a gradle project
// The simplest way is using a composite build: https://docs.gradle.org/current/userguide/composite_builds.html
// Other methods involved adding the build/lib/... jar to classpath, or publish to maven local
// By adding the plugin as a dep in `pig-tests`, I cannot use an included build of `pig` in the plugin
// Hence it's much simpler to use the latest published version in the plugin
implementation("org.partiql:partiql-ir-generator:0.5.0")
implementation("org.partiql:partiql-ir-generator:${Versions.pig}")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.1")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.1")
}
Expand All @@ -35,21 +37,21 @@ pluginBundle {
gradlePlugin {
plugins {
create("pig-gradle-plugin") {
id = "pig-gradle-plugin"
id = "org.partiql.pig.pig-gradle-plugin"
displayName = "PIG Gradle Plugin"
description = "The PIG gradle plugin exposes a Gradle task to generate sources from a PIG type universe"
implementationClass = "org.partiql.pig.plugin.PigPlugin"
implementationClass = "org.partiql.pig.gradle.PigPlugin"
}
}
}

//
// // TODO https://github.com/partiql/partiql-ir-generator/issues/132
// publishing {
// repositories {
// maven {
// name = 'mavenLocalPlugin'
// url = '../maven-local-plugin'
// }
// }
// }
java {
sourceCompatibility = JavaVersion.toVersion(Versions.javaTarget)
targetCompatibility = JavaVersion.toVersion(Versions.javaTarget)
}

tasks.compileKotlin {
kotlinOptions.jvmTarget = Versions.javaTarget
kotlinOptions.apiVersion = Versions.kotlinTarget
kotlinOptions.languageVersion = Versions.kotlinTarget
}
210 changes: 210 additions & 0 deletions pig-gradle-plugin/src/main/kotlin/org/partiql/pig/gradle/PigPlugin.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

package org.partiql.pig.gradle

import org.gradle.api.DefaultTask
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.file.SourceDirectorySet
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.SourceSetContainer
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.options.Option
import org.partiql.pig.main
import java.io.File

abstract class PigPlugin : Plugin<Project> {

override fun apply(target: Project) {
// Ensure `sourceSets` extension exists
target.pluginManager.apply(JavaPlugin::class.java)

// Adds pig source set extension to all source sets
target.sourceSets().forEach { sourceSet ->
val name = sourceSet.name
val sds = target.objects.sourceDirectorySet(name, "$name PIG source")
sds.srcDir("src/$name/pig")
sds.include("**/*.ion")
sourceSet.extensions.add("pig", sds)
}

// Extensions for pig compiler arguments
val ext = target.extensions.create("pig", PigExtension::class.java)

// Create tasks after source sets have been evaluated
target.afterEvaluate {
target.sourceSets().forEach { sourceSet ->
// Pig generate all for the given source set
val pigAllTaskName = getPigAllTaskName(sourceSet)
val pigAllTask = target.tasks.create(pigAllTaskName) {
it.group = "pig"
it.description = "Generate all PIG sources for ${sourceSet.name} source set"
}

val language = ext.language
val namespace = ext.namespace
var outDir = ext.outputDir

// The `kotlin` target without an `outputDir` will use the package path as the output dir
if (outDir == null && language == "kotlin") {
val base = "${target.buildDir}/generated-src"
outDir = File("$base/${namespace.replace('.', '/')}")
// Eventually this will need to be sourceSet.kotlin, but that's currently not possible
// sourceSet.java.srcDir(base)
}

// Create a pig task for each type universe and each source set
(sourceSet.extensions.getByName("pig") as SourceDirectorySet).files.forEach { file ->
val universeName = file.name.removeSuffix(".ion").lowerToCamelCase().capitalize()
val pigTask = target.tasks.create(pigAllTaskName + universeName, PigTask::class.java) { task ->
task.description = "Generated PIG sources for $file"
task.universe.set(file.absolutePath)
task.target.set(language)
if (namespace.isNotEmpty()) {
task.namespace.set(namespace)
}
if (outDir != null) {
task.outputDir.set(outDir.absolutePath)
}
if (ext.outputFile != null) {
task.outputFile.set(ext.outputFile!!.absolutePath)
}
if (ext.template.isNotEmpty()) {
task.template.set(ext.template)
}
}
pigAllTask.dependsOn(pigTask)
if (language == "kotlin") {
target.tasks.named("compileKotlin") {
it.dependsOn(pigAllTask)
}
}
}
}
}
}

private fun Project.sourceSets(): List<SourceSet> = extensions.getByType(SourceSetContainer::class.java).toList()

private fun getPigAllTaskName(sourceSet: SourceSet) = when (SourceSet.isMain(sourceSet)) {
true -> "generatePigSource"
else -> "generatePig${sourceSet.name.capitalize()}Source"
}

/**
* Type Universe files are lower hyphen, but Gradle tasks are lower camel
*/
private fun String.lowerToCamelCase(): String =
this.split('-')
.filter { it.isNotEmpty() }
.mapIndexed { i, str ->
when (i) {
0 -> str
else -> str.capitalize()
}
}
.joinToString(separator = "")
}

abstract class PigTask : DefaultTask() {

init {
group = "pig"
}

@get:Input
@get:Option(
option = "universe",
description = "Type universe input file"
)
abstract val universe: Property<String>

@get:Input
@get:Option(
option = "target",
description = "Target language"
)
abstract val target: Property<String>

@get:Input
@get:Optional
@get:Option(
option = "outputFile",
description = "Generated output file (for targets that output a single file)"
)
abstract val outputFile: Property<String>

@get:Input
@get:Optional
@get:Option(
option = "outputDir",
description = "Generated output directory (for targets that output multiple files)"
)
abstract val outputDir: Property<String>

@get:Input
@get:Optional
@get:Option(
option = "namespace",
description = "Namespace for generated code"
)
abstract val namespace: Property<String>

@get:Input
@get:Optional
@get:Option(
option = "template",
description = "Path to an Apache FreeMarker template"
)
abstract val template: Property<String>

@TaskAction
fun action() {
val args = mutableListOf<String>()
// required args
args += listOf("-u", universe.get())
args += listOf("-t", target.get())
// optional args
if (outputFile.isPresent) {
args += listOf("-o", outputFile.get())
}
if (outputDir.isPresent) {
args += listOf("-d", outputDir.get())
}
if (namespace.isPresent) {
args += listOf("-n", namespace.get())
}
if (template.isPresent) {
args += listOf("-e", template.get())
}
// invoke pig compiler, offloads all arg handling to the application
// also invoking via the public interface for consistency
println("pig ${args.joinToString(" ")}")
main(args.toTypedArray())
}
}

abstract class PigExtension {
var language: String = "kotlin"
var outputFile: File? = null
var outputDir: File? = null
var namespace: String = ""
var template: String = ""
}

This file was deleted.

Loading

0 comments on commit 26645c2

Please sign in to comment.