diff --git a/.gitignore b/.gitignore index fb984c5c..71044a66 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/build.gradle.kts b/build.gradle.kts index 4fa59dc5..d6b1d67f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -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" } @@ -47,8 +46,8 @@ dependencies { } gradlePlugin { - (plugins) { - "generate-models" { + plugins { + register("generate-models") { id = "generate-models" implementationClass = "de.itemis.mps.gradle.generate.GenerateMpsProjectPlugin" } @@ -56,12 +55,12 @@ gradlePlugin { } 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']") } @@ -71,6 +70,7 @@ tasks { publishing { repositories { maven { + name = "itemis" url = uri("https://projects.itemis.de/nexus/content/repositories/mbeddr") credentials { username = nexusUsername @@ -81,3 +81,4 @@ publishing { } + diff --git a/execute-generators/build.gradle.kts b/execute-generators/build.gradle.kts index 09690037..2636a6cd 100644 --- a/execute-generators/build.gradle.kts +++ b/execute-generators/build.gradle.kts @@ -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) @@ -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 { diff --git a/execute-generators/src/main/kotlin/de/itemis/mps/gradle/generate/Helper.kt b/execute-generators/src/main/kotlin/de/itemis/mps/gradle/generate/Helper.kt index 06b2c142..4cc447a8 100644 --- a/execute-generators/src/main/kotlin/de/itemis/mps/gradle/generate/Helper.kt +++ b/execute-generators/src/main/kotlin/de/itemis/mps/gradle/generate/Helper.kt @@ -72,27 +72,36 @@ private fun createScript(proj: Project, models: List) { +private fun makeModels(proj: Project, models: List) : 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>() project.modelAccess.runReadAction { @@ -105,7 +114,7 @@ fun generateProject(parsed: Args, project: Project) { val modelsToGenerate = ftr.resultSync - makeModels(project, modelsToGenerate) + return makeModels(project, modelsToGenerate) } diff --git a/execute-generators/src/main/kotlin/de/itemis/mps/gradle/generate/Main.kt b/execute-generators/src/main/kotlin/de/itemis/mps/gradle/generate/Main.kt index ad5f7d93..43875961 100644 --- a/execute-generators/src/main/kotlin/de/itemis/mps/gradle/generate/Main.kt +++ b/execute-generators/src/main/kotlin/de/itemis/mps/gradle/generate/Main.kt @@ -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 { - val split = s.split(":") - if (split.size < 2) { - throw RuntimeException("string if not of the right format. Expected :") - } - 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=:") - { splitAtColumn(this) } - val macros by parser.adding("--macros", - help = "macro to define. The format is --macro=:") - { splitAtColumn(this) } - - val pluginLocation by parser.storing("--plugin-location", - help = "location to load additional plugins from").default(null) - - val project by parser.positional("PROJECT", - help = "project to generate from") } fun main(args: Array) = 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) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a4fc03df..d76b502e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -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 diff --git a/project-loader/build.gradle.kts b/project-loader/build.gradle.kts new file mode 100644 index 00000000..6b7704e9 --- /dev/null +++ b/project-loader/build.gradle.kts @@ -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 { + kotlinOptions.jvmTarget = "1.8" +} \ No newline at end of file diff --git a/project-loader/src/main/kotlin/Args.kt b/project-loader/src/main/kotlin/Args.kt new file mode 100644 index 00000000..1abec40f --- /dev/null +++ b/project-loader/src/main/kotlin/Args.kt @@ -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 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 :") + } + 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=:") + { toPlugin(this) } + + val macros by parser.adding("--macro", + help = "macro to define. The format is --macro=:") + { toMacro(this) } + + val pluginLocation by parser.storing("--plugin-location", + help = "location to load additional plugins from") { File(this) }.default(null) + + val buildNumber by parser.storing("--build-number", + help = "build number used to determine if the plugins are compatible").default(null) + + val project by parser.storing("--project", + help = "project to generate from") { File(this) } +} \ No newline at end of file diff --git a/project-loader/src/main/kotlin/Loader.kt b/project-loader/src/main/kotlin/Loader.kt new file mode 100644 index 00000000..d4506e52 --- /dev/null +++ b/project-loader/src/main/kotlin/Loader.kt @@ -0,0 +1,147 @@ +package de.itemis.mps.gradle.project.loader + +import com.intellij.application.options.PathMacrosImpl +import jetbrains.mps.project.Project +import jetbrains.mps.tool.environment.EnvironmentConfig +import jetbrains.mps.tool.environment.IdeaEnvironment +import org.apache.log4j.Logger +import java.io.File + +data class Plugin( + val path: String, + val id: String +) + +data class Macro( + val name: String, + val value: String +) + +private val logger = Logger.getLogger("de.itemis.mps.gradle.project.loader") + +/** + * The Idea platform reads this property first to determine where additional plugins are loaded from. + */ +private const val PROPERTY_PLUGINS_PATH = "idea.plugins.path" + +/** + * At least starting from MPS 2018.2 this property is read by the platform to check against this value if a plugin + * is compatible with the application. It seems to override all other means of checks, e.g. build number in + * ApplicationInfo. + */ +private const val PROPERTY_PLUGINS_COMPATIBLE_BUILD = "idea.plugins.compatible.build" + +private 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() + .withBuildPlugin() + .withBootstrapLibraries() + .withWorkbenchPath() + .withGit4IdeaPlugin() + .withJavaPlugin() + .addPlugin("http-support", "jetbrains.mps.ide.httpsupport") + return config +} + +/** + * Loads up an idea environment with the given parameters, passes the project into the lambda, closes the project then + * shuts down the idea environment and returns the value calculated by the lambda. + * + * The environment is also shutdown in cases where the lambda throws an exception. + * + * + * @param project the location of the project to open. + * @param action the action to execute with the project. + * @param pluginLocation optional location where plugins lo load are located. This is for additional plugins, the plugins + * located in the pre-installed pluging location (usual the "plugins" folder of MPS) are still considered. + * @param plugins optional list of plugins to load. Path is the what MPS calls the `short (folder) name` in it's build + * language. The id is the plugin id defined in the plugin descriptor. Both are required because MPS supports multiple + * plugins the same location. + * @param macros optional list of path macros to define before the project is opened + * @param buildNumber optional build number that is used to determine if the plugins are compatible. Only guaranteed to + * work with MPS 2018.2+ but might work in earlier versions as well. + */ +fun executeWithProject(project: File, + plugins: List = emptyList(), + macros: List = emptyList(), + pluginLocation: File? = null, + buildNumber: String? = null, + action: (Project) -> T): T { + + val propertyOverrides = mutableListOf>() + + if (pluginLocation != null) { + logger.info("overriding plugin location with: ${pluginLocation.absolutePath}") + propertyOverrides.add(Pair(PROPERTY_PLUGINS_PATH, System.getProperty(PROPERTY_PLUGINS_PATH))) + System.setProperty(PROPERTY_PLUGINS_PATH, pluginLocation.absolutePath) + } + + if (buildNumber != null) { + logger.info("setting build number to \"$buildNumber\"") + propertyOverrides.add(Pair(PROPERTY_PLUGINS_COMPATIBLE_BUILD, System.getProperty(PROPERTY_PLUGINS_COMPATIBLE_BUILD))) + System.setProperty(PROPERTY_PLUGINS_COMPATIBLE_BUILD, buildNumber) + } + + val cfg = basicEnvironmentConfig() + + plugins.forEach { cfg.addPlugin(it.path, it.id) } + + val ideaEnvironment = IdeaEnvironment(cfg) + + logger.info("initialising environment") + ideaEnvironment.init() + logger.info("flushing events") + ideaEnvironment.flushAllEvents() + + val pathMacrosImpl = PathMacrosImpl.getInstanceEx() + macros.forEach { pathMacrosImpl.setMacro(it.name, it.value) } + + logger.info("opening project: ${project.absolutePath}") + val ideaProject = ideaEnvironment.openProject(project) + + logger.info("flushing events") + ideaEnvironment.flushAllEvents() + + val res: T + + try { + res = action(ideaProject) + } finally { + ideaProject.dispose() + logger.info("project disposed") + ideaEnvironment.flushAllEvents() + logger.info("disposing environment") + ideaEnvironment.dispose() + logger.info("project and environment disposed") + } + + // cleanup overridden property values to the state that they were before. + propertyOverrides.forEach { + System.setProperty(it.first, it.second) + } + + return res +} + +/** + * Convenient function to invoke [executeWithProject] with arguments parsed form the command line. + * + * @see [executeWithProject] for more details. + * + * @param parsed parsed arguemnts. + * @param action the action to execute with the project. + * + */ +fun executeWithProject(parsed: Args, action: (Project) -> T) = executeWithProject( + project = parsed.project, + plugins = parsed.plugins, + macros = parsed.macros, + buildNumber = parsed.buildNumber, + pluginLocation = parsed.pluginLocation, + action = action) diff --git a/settings.gradle.kts b/settings.gradle.kts index 0bf8bc80..f96182f0 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,2 +1,3 @@ rootProject.name = "mps-gradle-plugin" -include("execute-generators") \ No newline at end of file +include("execute-generators") +include("project-loader") \ No newline at end of file diff --git a/src/main/kotlin/de/itemis/mps/gradle/generate/Plugin.kt b/src/main/kotlin/de/itemis/mps/gradle/generate/Plugin.kt index 723a9294..6f4e7ea2 100644 --- a/src/main/kotlin/de/itemis/mps/gradle/generate/Plugin.kt +++ b/src/main/kotlin/de/itemis/mps/gradle/generate/Plugin.kt @@ -57,7 +57,7 @@ open class GenerateMpsProjectPlugin : Plugin { val projectLocation = extension.projectLocation ?: throw GradleException("No project path set") - val prj = sequenceOf(projectLocation.absolutePath) + val prj = sequenceOf("--project=${projectLocation.absolutePath}") val args = sequenceOf(pluginLocation, extension.plugins.map { "--plugin=${it.id}:${it.path}" }.asSequence(), diff --git a/test/generate-build-solution/build.gradle.kts b/test/generate-build-solution/build.gradle.kts new file mode 100644 index 00000000..2825f7f9 --- /dev/null +++ b/test/generate-build-solution/build.gradle.kts @@ -0,0 +1,38 @@ +group = "test.de.itemis.mps.gradle.generate" +version = "1.0-SNAPSHOT" + +plugins { + id("generate-models") version "1.0-SNAPSHOT" +} + +repositories { + mavenLocal() + mavenCentral() + maven { + url = java.net.URI("https://projects.itemis.de/nexus/content/repositories/mbeddr") + } +} + +val mps = configurations.create("mps") + +val mpsVersion = "2018.2.4" + +dependencies { + mps("com.jetbrains:mps:$mpsVersion") +} + +generate { + projectLocation = File("./mps-prj") + mpsConfig = mps + models = listOf("my.build.script") +} + + +tasks { + register("wrapper", Wrapper::class) { + //make sure this version matches the version in parent build script otherwise this build will fail + gradleVersion = "4.10.2" + distributionType = Wrapper.DistributionType.ALL + } +} + diff --git a/test/generate-build-solution/gradle/wrapper/gradle-wrapper.jar b/test/generate-build-solution/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..1948b907 Binary files /dev/null and b/test/generate-build-solution/gradle/wrapper/gradle-wrapper.jar differ diff --git a/test/generate-build-solution/gradle/wrapper/gradle-wrapper.properties b/test/generate-build-solution/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..d76b502e --- /dev/null +++ b/test/generate-build-solution/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/test/generate-build-solution/gradlew b/test/generate-build-solution/gradlew new file mode 100755 index 00000000..cccdd3d5 --- /dev/null +++ b/test/generate-build-solution/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/test/generate-build-solution/gradlew.bat b/test/generate-build-solution/gradlew.bat new file mode 100644 index 00000000..f9553162 --- /dev/null +++ b/test/generate-build-solution/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/test/generate-build-solution/mps-prj/.mps/migration.xml b/test/generate-build-solution/mps-prj/.mps/migration.xml new file mode 100644 index 00000000..a08c877d --- /dev/null +++ b/test/generate-build-solution/mps-prj/.mps/migration.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/test/generate-build-solution/mps-prj/.mps/misc.xml b/test/generate-build-solution/mps-prj/.mps/misc.xml new file mode 100644 index 00000000..8e3bf350 --- /dev/null +++ b/test/generate-build-solution/mps-prj/.mps/misc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/test/generate-build-solution/mps-prj/.mps/modules.xml b/test/generate-build-solution/mps-prj/.mps/modules.xml new file mode 100644 index 00000000..578483e3 --- /dev/null +++ b/test/generate-build-solution/mps-prj/.mps/modules.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/test/generate-build-solution/mps-prj/.mps/vcs.xml b/test/generate-build-solution/mps-prj/.mps/vcs.xml new file mode 100644 index 00000000..c2365ab1 --- /dev/null +++ b/test/generate-build-solution/mps-prj/.mps/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/test/generate-build-solution/mps-prj/solutions/my.build/models/script.mps b/test/generate-build-solution/mps-prj/solutions/my.build/models/script.mps new file mode 100644 index 00000000..80187561 --- /dev/null +++ b/test/generate-build-solution/mps-prj/solutions/my.build/models/script.mps @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/generate-build-solution/mps-prj/solutions/my.build/my.build.msd b/test/generate-build-solution/mps-prj/solutions/my.build/my.build.msd new file mode 100644 index 00000000..eb2c0dc0 --- /dev/null +++ b/test/generate-build-solution/mps-prj/solutions/my.build/my.build.msd @@ -0,0 +1,25 @@ + + + + + + + + + + 422c2909-59d6-41a9-b318-40e6256b250f(jetbrains.mps.ide.build) + + + + + + + + + + + + + + + diff --git a/test/generate-build-solution/mps-prj/solutions/my.solution/models/java.mps b/test/generate-build-solution/mps-prj/solutions/my.solution/models/java.mps new file mode 100644 index 00000000..529cff04 --- /dev/null +++ b/test/generate-build-solution/mps-prj/solutions/my.solution/models/java.mps @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/generate-build-solution/mps-prj/solutions/my.solution/my.solution.msd b/test/generate-build-solution/mps-prj/solutions/my.solution/my.solution.msd new file mode 100644 index 00000000..df55f4ad --- /dev/null +++ b/test/generate-build-solution/mps-prj/solutions/my.solution/my.solution.msd @@ -0,0 +1,31 @@ + + + + + + + + + + 6354ebe7-c22a-4a0f-ac54-50b52ab9b065(JDK) + + + + + + + + + + + + + + + + + + + + + diff --git a/test/generate-build-solution/settings.gradle.kts b/test/generate-build-solution/settings.gradle.kts new file mode 100644 index 00000000..f59827f5 --- /dev/null +++ b/test/generate-build-solution/settings.gradle.kts @@ -0,0 +1,8 @@ +rootProject.name = "test-mps-gradle-plugin" + +pluginManagement { + repositories { + mavenLocal() + } +} + diff --git a/test/generate-simple/build.gradle.kts b/test/generate-simple/build.gradle.kts new file mode 100644 index 00000000..bfbe3dbb --- /dev/null +++ b/test/generate-simple/build.gradle.kts @@ -0,0 +1,37 @@ +group = "test.de.itemis.mps.gradle.generate" +version = "1.0-SNAPSHOT" + +plugins { + id("generate-models") version "1.0-SNAPSHOT" +} + +repositories { + mavenLocal() + mavenCentral() + maven { + url = java.net.URI("https://projects.itemis.de/nexus/content/repositories/mbeddr") + } +} + +val mps = configurations.create("mps") + +val mpsVersion = "2018.2.4" + +dependencies { + mps("com.jetbrains:mps:$mpsVersion") +} + +generate { + projectLocation = File("./mps-prj") + mpsConfig = mps +} + + +tasks { + register("wrapper", Wrapper::class) { + //make sure this version matches the version in parent build script otherwise this build will fail + gradleVersion = "4.10.2" + distributionType = Wrapper.DistributionType.ALL + } +} + diff --git a/test/generate-simple/gradle/wrapper/gradle-wrapper.jar b/test/generate-simple/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..1948b907 Binary files /dev/null and b/test/generate-simple/gradle/wrapper/gradle-wrapper.jar differ diff --git a/test/generate-simple/gradle/wrapper/gradle-wrapper.properties b/test/generate-simple/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..d76b502e --- /dev/null +++ b/test/generate-simple/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/test/generate-simple/gradlew b/test/generate-simple/gradlew new file mode 100755 index 00000000..cccdd3d5 --- /dev/null +++ b/test/generate-simple/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/test/generate-simple/gradlew.bat b/test/generate-simple/gradlew.bat new file mode 100644 index 00000000..f9553162 --- /dev/null +++ b/test/generate-simple/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/test/generate-simple/mps-prj/.mps/migration.xml b/test/generate-simple/mps-prj/.mps/migration.xml new file mode 100644 index 00000000..a08c877d --- /dev/null +++ b/test/generate-simple/mps-prj/.mps/migration.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/test/generate-simple/mps-prj/.mps/misc.xml b/test/generate-simple/mps-prj/.mps/misc.xml new file mode 100644 index 00000000..8e3bf350 --- /dev/null +++ b/test/generate-simple/mps-prj/.mps/misc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/test/generate-simple/mps-prj/.mps/modules.xml b/test/generate-simple/mps-prj/.mps/modules.xml new file mode 100644 index 00000000..bb07e4ab --- /dev/null +++ b/test/generate-simple/mps-prj/.mps/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/test/generate-simple/mps-prj/solutions/my.solution/models/java.mps b/test/generate-simple/mps-prj/solutions/my.solution/models/java.mps new file mode 100644 index 00000000..fb6df92f --- /dev/null +++ b/test/generate-simple/mps-prj/solutions/my.solution/models/java.mps @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/generate-simple/mps-prj/solutions/my.solution/my.solution.msd b/test/generate-simple/mps-prj/solutions/my.solution/my.solution.msd new file mode 100644 index 00000000..ad359444 --- /dev/null +++ b/test/generate-simple/mps-prj/solutions/my.solution/my.solution.msd @@ -0,0 +1,31 @@ + + + + + + + + + + 6354ebe7-c22a-4a0f-ac54-50b52ab9b065(JDK) + + + + + + + + + + + + + + + + + + + + + diff --git a/test/generate-simple/settings.gradle.kts b/test/generate-simple/settings.gradle.kts new file mode 100644 index 00000000..f59827f5 --- /dev/null +++ b/test/generate-simple/settings.gradle.kts @@ -0,0 +1,8 @@ +rootProject.name = "test-mps-gradle-plugin" + +pluginManagement { + repositories { + mavenLocal() + } +} +