Skip to content

Commit

Permalink
Merge pull request #25 from mbeddr/project-loader
Browse files Browse the repository at this point in the history
RFC: Infrastructure to execute code with a project
  • Loading branch information
coolya authored Nov 22, 2018
2 parents 03fbeda + 5a7371e commit d0ba845
Show file tree
Hide file tree
Showing 36 changed files with 1,379 additions and 117 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,8 @@
bin/
.project
build/
mps-prj/solutions/my.build/build.xml
.gradle/
test/generate-build-solution/mps-prj/solutions/my.build/build.xml
.DS_Store
workspace.xml
29 changes: 15 additions & 14 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,31 +1,30 @@
import java.net.URI

plugins {
kotlin("jvm") version "1.2.50"
`maven-publish`
groovy
`java-gradle-plugin`
`kotlin-dsl`
`maven-publish`
}

val versionMajor = 1
val versionMinor = 0
val versionMinor = 1

group = "de.itemis.mps"
version = "1.0.0"




val nexusUsername: String? by project
val nexusPassword: String? by project

val kotlinArgParserVersion by extra { "2.0.7" }
val mpsVersion by extra { "2018.2.4" }


if (project.hasProperty("forceCI") || project.hasProperty("teamcity")) {
version = de.itemis.mps.gradle.GitBasedVersioning.getVersion(versionMajor, versionMinor)
version = if (!project.hasProperty("useSnapshot") &&
(project.hasProperty("forceCI") || project.hasProperty("teamcity"))) {
de.itemis.mps.gradle.GitBasedVersioning.getVersion(versionMajor, versionMinor)
} else {
version = "$versionMajor.$versionMinor-SNAPSHOT"
"$versionMajor.$versionMinor-SNAPSHOT"
}


Expand All @@ -47,21 +46,21 @@ dependencies {
}

gradlePlugin {
(plugins) {
"generate-models" {
plugins {
register("generate-models") {
id = "generate-models"
implementationClass = "de.itemis.mps.gradle.generate.GenerateMpsProjectPlugin"
}
}
}

tasks {
"wrapper"(Wrapper::class) {
gradleVersion = "4.8"
register ("wrapper", Wrapper::class) {
gradleVersion = "4.10.2"
distributionType = Wrapper.DistributionType.ALL
}

"setTeamCityBuildNumber" {
register("setTeamCityBuildNumber") {
doLast {
println("##teamcity[buildNumber '$version']")
}
Expand All @@ -71,6 +70,7 @@ tasks {
publishing {
repositories {
maven {
name = "itemis"
url = uri("https://projects.itemis.de/nexus/content/repositories/mbeddr")
credentials {
username = nexusUsername
Expand All @@ -81,3 +81,4 @@ publishing {
}



27 changes: 7 additions & 20 deletions execute-generators/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,10 @@ repositories {
val nexusUsername: String? by project
val nexusPassword: String? by project

val kotlinArgParserVersion: String by project
val mpsVersion: String by project

//define directories
val artifactsDir = File(buildDir, "artifacts")
val mpsDir = File(artifactsDir, "mps")
val kotlin_argparser_version = "2.0.7"
val pluginVersion = "1"
val mpsVersion = "2017.3.5"

val pluginVersion = "2"

version = if (project.hasProperty("forceCI") || project.hasProperty("teamcity")) {
de.itemis.mps.gradle.GitBasedVersioning.getVersion(mpsVersion, pluginVersion)
Expand All @@ -38,20 +34,11 @@ version = if (project.hasProperty("forceCI") || project.hasProperty("teamcity"))
val mpsConfiguration = configurations.create("mps")

dependencies {
compile(kotlin("stdlib"))
compile("com.xenomachina:kotlin-argparser:$kotlin_argparser_version")
compileOnly(fileTree(mpsDir).include("**/*.jar"))
implementation(kotlin("stdlib-jdk8"))
implementation("com.xenomachina:kotlin-argparser:$kotlinArgParserVersion")
mpsConfiguration("com.jetbrains:mps:$mpsVersion")
}


tasks {
val resolveMps by creating(Copy::class) {
from(mpsConfiguration.resolve().map { zipTree(it) })
into(mpsDir)
}

getByName("compileKotlin").dependsOn(resolveMps)
compileOnly(mpsConfiguration.resolve().map { zipTree(it) }.first().matching { include("lib/*.jar")})
implementation(project(":project-loader"))
}

tasks.withType<KotlinCompile> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,27 +72,36 @@ private fun createScript(proj: Project, models: List<org.jetbrains.mps.openapi.m
return scb.withFacetNames(DEFAULT_FACETS).withFinalTarget(ITarget.Name("jetbrains.mps.make.facets.Make.make")).toScript()
}

private fun makeModels(proj: Project, models: List<org.jetbrains.mps.openapi.model.SModel>) {
private fun makeModels(proj: Project, models: List<org.jetbrains.mps.openapi.model.SModel>) : Boolean {
val session = MakeSession(proj, MsgHandler(), true)
val res = ModelsToResources(models).resources().toList()
val makeService = BuildMakeService()

if (res.isEmpty()) {
logger.warn("nothing to generate")
return
return false
}
logger.info("starting generation")
val future = makeService.make(session, res, createScript(proj, models))
try {
future.get()
val result= future.get()
logger.info("generation finished")
return if (result.isSucessful) {
logger.info("generation result: successful")
true
} else {
logger.error("generation result: failed")
logger.error(result)
false
}
} catch (ex: Exception) {
logger.error("failed to generate", ex)
}
return false
}


fun generateProject(parsed: Args, project: Project) {
fun generateProject(parsed: GenerateArgs, project: Project): Boolean {
val ftr = AsyncResult<List<SModel>>()

project.modelAccess.runReadAction {
Expand All @@ -105,7 +114,7 @@ fun generateProject(parsed: Args, project: Project) {

val modelsToGenerate = ftr.resultSync

makeModels(project, modelsToGenerate)
return makeModels(project, modelsToGenerate)
}


Expand Down
Original file line number Diff line number Diff line change
@@ -1,99 +1,34 @@
package de.itemis.mps.gradle.generate

import com.intellij.application.options.PathMacrosImpl
import com.xenomachina.argparser.ArgParser
import com.xenomachina.argparser.default
import com.xenomachina.argparser.SystemExitException
import com.xenomachina.argparser.mainBody
import jetbrains.mps.tool.environment.Environment
import jetbrains.mps.tool.environment.EnvironmentConfig
import jetbrains.mps.tool.environment.IdeaEnvironment
import de.itemis.mps.gradle.project.loader.Args
import de.itemis.mps.gradle.project.loader.executeWithProject
import org.apache.log4j.Logger
import java.io.File

private val logger = Logger.getLogger("de.itemis.mps.gradle.generate")
const val PROPERTY_PLUGINS_PATH = "idea.plugins.path"

fun basicEnvironmentConfig(): EnvironmentConfig {

// This is a somewhat "save" set of default plugins. It should work with most of the projects we have encountered
// mbeddr projects won't build build with this set of plugins for unknown reasons, most probably the runtime
// dependencies in the mbeddr plugins are so messed up that they simply broken beyond repair.

val config = EnvironmentConfig
.emptyConfig()
.withDefaultPlugins()
.withDevkitPlugin()
.withBuildPlugin()
.withBootstrapLibraries()
.withWorkbenchPath()
.withGit4IdeaPlugin()
.withJavaPlugin()
.addPlugin("http-support", "jetbrains.mps.ide.httpsupport")
return config
}

private fun splitAtColumn(s: String): Pair<String, String> {
val split = s.split(":")
if (split.size < 2) {
throw RuntimeException("string if not of the right format. Expected <key>:<value>")
}
return Pair(split[0], split[1])
}

class Args(parser: ArgParser) {

class GenerateArgs(parser: ArgParser) : Args(parser) {
val models by parser.adding("--model",
help = "list of models to generate")
val plugins by parser.adding("--plugin",
help = "plugin to to load. The format is --plugin=<name>:<id>")
{ splitAtColumn(this) }
val macros by parser.adding("--macros",
help = "macro to define. The format is --macro=<name>:<value>")
{ splitAtColumn(this) }

val pluginLocation by parser.storing("--plugin-location",
help = "location to load additional plugins from").default<String?>(null)

val project by parser.positional("PROJECT",
help = "project to generate from")
}


fun main(args: Array<String>) = mainBody {

val parsed = ArgParser(args).parseInto(::Args)
val parsed = ArgParser(args).parseInto(::GenerateArgs)
var result = false

if (!parsed.pluginLocation.isNullOrEmpty()) {
System.setProperty(PROPERTY_PLUGINS_PATH, parsed.pluginLocation)
}

val cfg = basicEnvironmentConfig()

parsed.plugins.forEach { cfg.addPlugin(it.first, it.second) }

var env: Environment? = null
try {
logger.info("Creating Env")

env = IdeaEnvironment.getOrCreate(cfg)
env.flushAllEvents()

val pathMacrosImpl = PathMacrosImpl.getInstanceEx()
parsed.macros.forEach { pathMacrosImpl.setMacro(it.first, it.second) }

val project = env.openProject(File(parsed.project))

env.flushAllEvents()

generateProject(parsed, project)

env.flushAllEvents()
result = executeWithProject(parsed) { project -> generateProject(parsed, project) }
} catch (ex: java.lang.Exception) {
logger.fatal("error generating", ex)
} catch (t: Throwable) {
logger.fatal("error generating", t)
} finally {
if (env != null) env.dispose()
}
if(!result) {
throw SystemExitException("generation failed", -1)
}

System.exit(0)
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.8-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
40 changes: 40 additions & 0 deletions project-loader/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
kotlin("jvm")
`maven-publish`
`java-gradle-plugin`
}

group = "de.itemis.mps"

val mpsVersion: String by project
val kotlinArgParserVersion: String by project

val pluginVersion = "1"

version = if (project.hasProperty("forceCI") || project.hasProperty("teamcity")) {
de.itemis.mps.gradle.GitBasedVersioning.getVersion(mpsVersion, pluginVersion)
} else {
"$mpsVersion.$pluginVersion-SNAPSHOT"
}

repositories {
mavenCentral()
maven {
url = uri("https://projects.itemis.de/nexus/content/repositories/mbeddr")
}
}

val mpsConfiguration = configurations.create("mps")

dependencies {
implementation(kotlin("stdlib-jdk8"))
mpsConfiguration("com.jetbrains:mps:$mpsVersion")
implementation("com.xenomachina:kotlin-argparser:$kotlinArgParserVersion")
compileOnly(mpsConfiguration.resolve().map { zipTree(it) }.first().matching { include("lib/*.jar")})
}

tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "1.8"
}
41 changes: 41 additions & 0 deletions project-loader/src/main/kotlin/Args.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package de.itemis.mps.gradle.project.loader

import com.xenomachina.argparser.ArgParser
import com.xenomachina.argparser.default
import java.io.File

private fun <T> splitAndCreate(str: String, creator: (String, String) -> T): T {
val split = str.split(":")
if (split.size < 2) {
throw RuntimeException("string if not of the right format. Expected <key>:<value>")
}
return creator(split[0], split[1])
}

private fun toMacro(str: String) = splitAndCreate(str, ::Macro)
private fun toPlugin(str: String) = splitAndCreate(str, ::Plugin)

/**
* Default set of arguments required to start a "headless" MPS. This class should be used by other users of the
* project-loader in order to establish a somewhat standardised command line interface. Passing instances of this or
* subclasses to [executeWithProject] is directly supported.
*/
open class Args(parser: ArgParser) {

val plugins by parser.adding("--plugin",
help = "plugin to to load. The format is --plugin=<path>:<id>")
{ toPlugin(this) }

val macros by parser.adding("--macro",
help = "macro to define. The format is --macro=<name>:<value>")
{ toMacro(this) }

val pluginLocation by parser.storing("--plugin-location",
help = "location to load additional plugins from") { File(this) }.default<File?>(null)

val buildNumber by parser.storing("--build-number",
help = "build number used to determine if the plugins are compatible").default<String?>(null)

val project by parser.storing("--project",
help = "project to generate from") { File(this) }
}
Loading

0 comments on commit d0ba845

Please sign in to comment.