diff options
author | Dierk König <dierk.koenig@canoo.com> | 2015-11-21 10:09:31 +0100 |
---|---|---|
committer | Dierk König <dierk.koenig@canoo.com> | 2015-11-21 10:09:31 +0100 |
commit | f0807811f48c50b6a5fe7816ef48c148be9f9903 (patch) | |
tree | c61df925b637d26c95086510ee471ac861a36731 | |
parent | fa6dce676590c83bc84d130e1241cf585f88a469 (diff) | |
parent | 73dd702743a5b4d8816e495e55c19f391669fc25 (diff) | |
download | frege-gradle-plugin-f0807811f48c50b6a5fe7816ef48c148be9f9903.tar.gz frege-gradle-plugin-f0807811f48c50b6a5fe7816ef48c148be9f9903.tar.bz2 frege-gradle-plugin-f0807811f48c50b6a5fe7816ef48c148be9f9903.zip |
Merge pull request #28 from breskeby/base-plugin
Base plugin
19 files changed, 570 insertions, 342 deletions
diff --git a/src/integTest/groovy/frege/plugin/FregePluginIntegTest.groovy b/src/integTest/groovy/frege/plugin/FregePluginIntegTest.groovy index 5c985e8..b6936a8 100644 --- a/src/integTest/groovy/frege/plugin/FregePluginIntegTest.groovy +++ b/src/integTest/groovy/frege/plugin/FregePluginIntegTest.groovy @@ -1,14 +1,15 @@ package frege.plugin - import org.gradle.testkit.runner.GradleRunner import org.junit.Rule import org.junit.rules.TemporaryFolder import spock.lang.Specification +import spock.lang.Unroll import static org.gradle.testkit.runner.TaskOutcome.SUCCESS class FregePluginIntegTest extends Specification { + public static final String DEFAULT_FREGE_VERSION = "3.23.370-g898bc8c" @Rule final TemporaryFolder testProjectDir = new TemporaryFolder() File buildFile @@ -18,6 +19,15 @@ class FregePluginIntegTest extends Specification { def setup() { buildFile = testProjectDir.newFile('build.gradle') + buildFile << """ + plugins { + id 'org.frege-lang' + } + + repositories { + jcenter() + } + """ def pluginClasspathResource = getClass().classLoader.findResource("plugin-classpath.txt") if (pluginClasspathResource == null) { // try again via file reference @@ -29,26 +39,39 @@ class FregePluginIntegTest extends Specification { pluginClasspath = pluginClasspathResource.readLines().collect { new File(it) } } - def "can compile frege production code"() { + def "can handle non existing source directories"() { given: buildFile << """ - plugins { - id 'org.frege-lang' + dependencies { + compile "org.frege-lang:frege:$DEFAULT_FREGE_VERSION" } + """ - repositories { - jcenter() - } + when: + def result = GradleRunner.create() + .withProjectDir(testProjectDir.root) + .withArguments('classes') + .withPluginClasspath(pluginClasspath) + .build() + then: + result.task(":compileFrege") != null + } + @Unroll + def "can compile and run frege code (gradle: #gradleVersion, frege: #fregeVersion)"() { + given: + buildFile << """ dependencies { - compile "org.frege-lang:frege:3.22.367-g2737683" + compile "org.frege-lang:frege:$fregeVersion" } task sayHello(type: JavaExec){ + doFirst { + println classpath.files + } classpath = sourceSets.main.runtimeClasspath main = 'HelloFrege' } - """ testProjectDir.newFolder("src", "main", "frege") @@ -65,6 +88,7 @@ main _ = do when: def result = GradleRunner.create() + .withGradleVersion(gradleVersion) .withProjectDir(testProjectDir.root) .withArguments('sayHello') .withPluginClasspath(pluginClasspath) @@ -73,5 +97,12 @@ main _ = do then: result.output.contains("Hello Frege!") result.task(":sayHello").outcome == SUCCESS + + where: + fregeVersion | gradleVersion + DEFAULT_FREGE_VERSION | "2.9" + DEFAULT_FREGE_VERSION | "2.8" + "3.22.367-g2737683" | "2.9" + "3.22.367-g2737683" | "2.8" } }
\ No newline at end of file diff --git a/src/main/groovy/frege/gradle/CompileTask.groovy b/src/main/groovy/frege/gradle/CompileTask.groovy deleted file mode 100644 index 07850a5..0000000 --- a/src/main/groovy/frege/gradle/CompileTask.groovy +++ /dev/null @@ -1,273 +0,0 @@ -package frege.gradle - -import frege.compiler.Main -import frege.prelude.PreludeBase -import frege.runtime.Lambda -import groovy.transform.TypeChecked -import groovy.transform.TypeCheckingMode -import org.gradle.api.DefaultTask -import org.gradle.api.Project -import org.gradle.api.artifacts.Configuration -import org.gradle.api.file.FileCollection -import org.gradle.api.tasks.* -import org.gradle.process.internal.DefaultJavaExecAction -import org.gradle.process.internal.JavaExecAction -import org.gradle.api.internal.file.FileResolver - -@TypeChecked -class CompileTask extends DefaultTask { - - // see help at https://github.com/Frege/frege/wiki/Compiler-Manpage - - static String DEFAULT_CLASSES_SUBDIR = "classes/main" // TODO: should this come from a convention? - static String DEFAULT_SRC_DIR = "src/main/frege" // TODO: should this come from a source set? - - static String DEFAULT_TEST_CLASSES_DIR = "classes/test" - static String DEFAULT_TEST_SRC_DIR = "src/test/frege" - - static Boolean USE_EXTERNAl = true - - @Optional @Input - boolean enabled = true - - @Optional @Input - Boolean help = false - - @Optional @Input - String stackSize = "4m" - - @Optional @Input - boolean hints = false - - @Optional @Input - boolean optimize = false - - @Optional @Input - boolean verbose = false - - @Optional @Input - boolean inline = true - - @Optional @Input - boolean make = true - - @Optional @Input - boolean compileGeneratedJava = true - - @Optional @Input - String target = "" - - @Optional @Input - boolean comments = false - - @Optional @Input - boolean suppressWarnings = false - - @Optional @Input - String explain = "" - - @Optional @Input - boolean skipCompile = false - - @Optional @Input - String extraArgs = "" - - @Optional @Input - String allArgs = "" // this is an option to overrule all other settings - - @Optional @Input - String module = "" - - @Optional @Input - List<File> fregePaths = [] - - @Optional @Input - List<File> sourcePaths = [deduceSourceDir(project)] - - @Optional @OutputDirectory - File outputDir = deduceClassesDir(project) - - @Optional @Input - String mainClass = "frege.compiler.Main" - - @Optional @Input - List<String> allJvmArgs = [] - - @Optional @Input - String encoding = "" - - @Optional @Input - String prefix = "" - - // TODO: Missing presentation of types (ascii, symbols, latin, greek, faktur) - - static File deduceSourceDir(File projectDir, String subdir) { - new File(projectDir, subdir) - } - - static File deduceSourceDir(Project project) { - deduceSourceDir(project.projectDir, DEFAULT_SRC_DIR) - } - - static File deduceClassesDir(File projectDir, String subdir) { - new File(projectDir, subdir) - } - - static File deduceClassesDir(Project project) { - deduceClassesDir(project.buildDir, DEFAULT_CLASSES_SUBDIR) - } - - static File deduceTestClassesDir(Project project) { - deduceClassesDir(project.buildDir, DEFAULT_TEST_CLASSES_DIR) - } - - static File deduceTestSourceDir(Project project) { - deduceSourceDir(project.projectDir, DEFAULT_TEST_SRC_DIR) - } - - @TaskAction - void executeCompile() { - - if (!enabled) { - logger.info("Frege compiler disabled.") - return; - } - - if (!outputDir.exists() ) { - logger.info "Creating output directory '${outputDir.absolutePath}'." - outputDir.mkdirs() - } - // access extension configuration values as ${project.frege.key1} - - FileResolver fileResolver = getServices().get(FileResolver.class) - JavaExecAction action = new DefaultJavaExecAction(fileResolver) - action.setMain(mainClass) - - logConfigurationInfo() - - action.setClasspath(actionClasspath(project)) - - def args = [] - if (help) { - args << "-help" - } else { - def jvmArgs = allJvmArgs - if (jvmArgs.isEmpty()) { - jvmArgs << "-Xss$stackSize".toString() - } - action.setJvmArgs(jvmArgs) - args = allArgs ? allArgs.split().toList() : assembleArguments() - } - - logger.info("Calling Frege compiler with args: '$args'") - action.args(args) - - if (USE_EXTERNAl) { - action.execute() - } else { - compile(args as String[]) - } - } - - void logConfigurationInfo() { - def path = project.files(compileConfig()).getAsPath() - logger.info("Compile configuation as path: $path") - - } - - FileCollection actionClasspath(Project p) { - p.files(compileConfig()) + p.files(deduceClassesDir(p)) - } - - // TODO: This should be removed or integrated so an external Java process does not need to be started. - // The Java generated uses System.exit() which does not work well with Gradle - // This was taken from the frege fork /compiler1/build/classes/main/afrege/compiler/Main.java:main() - void compile(String[] paramArrayOfString) { - long l1 = System.nanoTime(); - Integer localInteger = frege.runtime.Runtime.runMain( - PreludeBase.TST.performUnsafe( - (Lambda)Main.IJ._mainƒd0fa0028.inst.apply(PreludeBase._toList(paramArrayOfString)).forced() - ) - ); - long l2 = System.nanoTime(); - ((PrintWriter)frege.runtime.Runtime.stderr.get()).println("runtime " + (l2 - l1 + 500000L) / 1000000L / 1000.0D + " wallclock seconds."); - if (localInteger != null) { -// System.exit(localInteger.intValue()); - } - } - - List<File> totalFregeClasspath(List<File> fp) { - def result = [] - result.addAll(project.files(compileConfig()).getFiles().toList()) - result.addAll(fp) - result - } - - @TypeChecked(TypeCheckingMode.SKIP) - Configuration compileConfig() { - project.configurations.compile - } - - protected List<String> assembleArguments() { - List args = [] - if (hints) - args << "-hints" - if (optimize) { - args << "-O" - args << "-inline" - } - if (inline & !optimize) - args << "-inline" - if (make) - args << "-make" - if (!compileGeneratedJava) args << "-j" - if (target != "") { - args << "-target" - args << target - } - if (comments) args << "-comments" - if (suppressWarnings) args << "-nowarn" - if (explain != "") { - args << "-explain" - args << explain - } - if (verbose) - args << "-v" - if (skipCompile) - args << "-j" - - def fp = USE_EXTERNAl ? fregePaths : totalFregeClasspath(fregePaths) - if (!fp.isEmpty()) { - args << "-fp" - args << fp.collect{f -> f.absolutePath}.join(File.pathSeparator) - } - - if (sourcePaths != null && !sourcePaths.isEmpty()) { - args << "-sp" - args << sourcePaths.collect{d -> d.absolutePath}.join(File.pathSeparator) - } - - if (encoding != "") { - args << "-enc" - args << encoding - } - - if (prefix != "") { - args << "-prefix" - args << prefix - } - - args << "-d" - args << outputDir - - if (!module.isEmpty()) { - logger.info "compiling module '$module'" - args << module - } else { - args = (args + extraArgs.split().toList()).toList() - } - - args - } - -} diff --git a/src/main/groovy/frege/gradle/DefaultFregeSourceSet.java b/src/main/groovy/frege/gradle/DefaultFregeSourceSet.java new file mode 100644 index 0000000..3a9bcfc --- /dev/null +++ b/src/main/groovy/frege/gradle/DefaultFregeSourceSet.java @@ -0,0 +1,33 @@ +package frege.gradle; + +import groovy.lang.Closure; +import org.gradle.api.file.SourceDirectorySet; +import org.gradle.api.internal.file.DefaultSourceDirectorySet; +import org.gradle.api.internal.file.FileResolver; +import org.gradle.util.ConfigureUtil; + +public class DefaultFregeSourceSet implements FregeSourceSet { + private final SourceDirectorySet frege; + private final SourceDirectorySet allFrege; + + public DefaultFregeSourceSet(String displayName, FileResolver fileResolver) { + this.frege = new DefaultSourceDirectorySet(String.format("%s Frege source", new Object[]{displayName}), fileResolver); + this.frege.getFilter().include(new String[]{"**/*.fr"}); + this.allFrege = new DefaultSourceDirectorySet(String.format("%s Frege source", new Object[]{displayName}), fileResolver); + this.allFrege.source(this.frege); + this.allFrege.getFilter().include(new String[]{"**/*.fr"}); + } + + public SourceDirectorySet getFrege() { + return this.frege; + } + + public FregeSourceSet frege(Closure configureClosure) { + ConfigureUtil.configure(configureClosure, this.getFrege()); + return this; + } + + public SourceDirectorySet getAllFrege() { + return this.allFrege; + } +} diff --git a/src/main/groovy/frege/gradle/FregePlugin.groovy b/src/main/groovy/frege/gradle/FregePlugin.groovy deleted file mode 100644 index 29be393..0000000 --- a/src/main/groovy/frege/gradle/FregePlugin.groovy +++ /dev/null @@ -1,46 +0,0 @@ -package frege.gradle - -import groovy.transform.TypeChecked -import org.gradle.api.Plugin -import org.gradle.api.Project -import fj.data.Option -import org.gradle.api.plugins.JavaPlugin - -//@TypeChecked -class FregePlugin implements Plugin<Project> { - - void apply(Project project) { - // Workaround to build proper jars on Windows, see https://github.com/Frege/frege-gradle-plugin/issues/9 - System.setProperty("file.encoding", "UTF-8") - - project.plugins.apply(JavaPlugin) - def e = (FregePluginExtension) project.extensions.create("frege", FregePluginExtension) - - project.task('compileFrege', type: CompileTask, group: 'Build', dependsOn: "compileJava") { - module = CompileTask.deduceSourceDir(project).absolutePath - } - project.tasks.classes.dependsOn("compileFrege") - - project.task('compileTestFrege', type: CompileTask, group: 'Build', dependsOn: "compileTestJava") { - module = CompileTask.deduceTestSourceDir(project).absolutePath - outputDir = CompileTask.deduceTestClassesDir(project) - fregePaths = Option.fromNull(CompileTask.deduceClassesDir(project)) - .map{d -> [d]}.orSome([]) - } - project.tasks.testClasses.dependsOn("compileTestFrege") - - def replTask = project.task('fregeRepl', type: ReplTask, group: 'Tools', dependsOn: 'compileFrege') - replTask.outputs.upToDateWhen { false } // always run, regardless of up to date checks - - def checkTask = project.task('fregeQuickCheck', type: QuickCheckTask, group: 'Verification', dependsOn: 'testClasses') - checkTask.outputs.upToDateWhen { false } // always run, regardless of up to date checks - - project.tasks.test.dependsOn("fregeQuickCheck") - - project.task('fregeDoc', type: DocTask, group: 'Documentation', dependsOn: 'compileFrege') - - project.task('fregeNativeGen', type: NativeGenTask, group: 'Tools') - - } - -} diff --git a/src/main/groovy/frege/gradle/FregeSourceSet.java b/src/main/groovy/frege/gradle/FregeSourceSet.java new file mode 100644 index 0000000..8706ee2 --- /dev/null +++ b/src/main/groovy/frege/gradle/FregeSourceSet.java @@ -0,0 +1,7 @@ +package frege.gradle; + +/** + * Created by Rene on 20/11/15. + */ +public interface FregeSourceSet { +} diff --git a/src/main/groovy/frege/gradle/plugins/FregeBasePlugin.java b/src/main/groovy/frege/gradle/plugins/FregeBasePlugin.java new file mode 100644 index 0000000..8bf5399 --- /dev/null +++ b/src/main/groovy/frege/gradle/plugins/FregeBasePlugin.java @@ -0,0 +1,87 @@ +package frege.gradle.plugins; + +import frege.gradle.DefaultFregeSourceSet; +import frege.gradle.tasks.FregeCompile; +import org.gradle.api.Action; +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.file.FileTreeElement; +import org.gradle.api.internal.file.FileResolver; +import org.gradle.api.internal.plugins.DslObject; +import org.gradle.api.internal.tasks.DefaultSourceSet; +import org.gradle.api.plugins.JavaBasePlugin; +import org.gradle.api.plugins.JavaPluginConvention; +import org.gradle.api.specs.Spec; +import org.gradle.api.tasks.SourceSet; + +import javax.inject.Inject; +import java.util.concurrent.Callable; + +public class FregeBasePlugin implements Plugin<Project> { + private FileResolver fileResolver; + + private static String EXTENSION_NAME = "frege"; + private FregePluginExtension fregePluginExtension; + private Project project; + + @Inject + public FregeBasePlugin(FileResolver fileResolver) { + this.fileResolver = fileResolver; + } + + @Override + public void apply(Project project) { + // Workaround to build proper jars on Windows, see https://github.com/Frege/frege-gradle-plugin/issues/9 + this.project = project; + System.setProperty("file.encoding", "UTF-8"); + project.getPluginManager().apply(JavaBasePlugin.class); + fregePluginExtension = project.getExtensions().create(EXTENSION_NAME, FregePluginExtension.class); + JavaBasePlugin javaBasePlugin = project.getPlugins().getPlugin(JavaBasePlugin.class); + + configureCompileDefaults(new FregeRuntime(project)); + configureSourceSetDefaults(javaBasePlugin); + } + + + private void configureSourceSetDefaults(final JavaBasePlugin javaBasePlugin) { + project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets().all(new Action<SourceSet>() { + public void execute(SourceSet sourceSet) { + final DefaultFregeSourceSet fregeSourceSet = new DefaultFregeSourceSet(((DefaultSourceSet) sourceSet).getDisplayName(), fileResolver); + new DslObject(sourceSet).getConvention().getPlugins().put("frege", fregeSourceSet); + + final String defaultSourcePath = String.format("src/%s/frege", sourceSet.getName()); + fregeSourceSet.getFrege().srcDir(defaultSourcePath); + sourceSet.getResources().getFilter().exclude(new Spec<FileTreeElement>() { + public boolean isSatisfiedBy(FileTreeElement element) { + return fregeSourceSet.getFrege().contains(element.getFile()); + } + }); + sourceSet.getAllJava().source(fregeSourceSet.getFrege()); + sourceSet.getAllSource().source(fregeSourceSet.getFrege()); + + String compileTaskName = sourceSet.getCompileTaskName("frege"); + FregeCompile compile = project.getTasks().create(compileTaskName, FregeCompile.class); + compile.setModule(project.file(defaultSourcePath).getAbsolutePath()); + javaBasePlugin.configureForSourceSet(sourceSet, compile); + compile.dependsOn(sourceSet.getCompileJavaTaskName()); + compile.setDescription(String.format("Compiles the %s Frege source.", sourceSet.getName())); + compile.setSource(fregeSourceSet.getFrege()); + project.getTasks().getByName(sourceSet.getClassesTaskName()).dependsOn(compileTaskName); + } + }); + } + + private void configureCompileDefaults(final FregeRuntime fregeRuntime) { + this.project.getTasks().withType(FregeCompile.class, new Action<FregeCompile>() { + public void execute(final FregeCompile compile) { + compile.getConventionMapping().map("fregeClasspath", new Callable() { + public Object call() throws Exception { + return fregeRuntime.inferFregeClasspath(compile.getClasspath()); + } + + }); + } + }); + } + +} diff --git a/src/main/groovy/frege/gradle/plugins/FregeJarFile.java b/src/main/groovy/frege/gradle/plugins/FregeJarFile.java new file mode 100644 index 0000000..eaf7d8f --- /dev/null +++ b/src/main/groovy/frege/gradle/plugins/FregeJarFile.java @@ -0,0 +1,34 @@ +package frege.gradle.plugins; + +import org.gradle.util.VersionNumber; + +import java.io.File; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class FregeJarFile { + private static final Pattern FILE_NAME_PATTERN = Pattern.compile("(frege(?:-all)?)-(\\d.*?)(-indy)?.jar"); + private final File file; + private final Matcher matcher; + private String version; + + private FregeJarFile(File file, Matcher matcher) { + this.file = file; + this.matcher = matcher; + } + + + public static FregeJarFile parse(File file) { + Matcher matcher = FILE_NAME_PATTERN.matcher(file.getName()); + return matcher.matches() ? new FregeJarFile(file, matcher) : null; + } + + public String getDependencyNotation() { + return "org.frege-lang:frege:" + getVersion(); + + } + + public VersionNumber getVersion() { + return VersionNumber.parse(matcher.group(2)); + } +} diff --git a/src/main/groovy/frege/gradle/plugins/FregePlugin.groovy b/src/main/groovy/frege/gradle/plugins/FregePlugin.groovy new file mode 100644 index 0000000..af05228 --- /dev/null +++ b/src/main/groovy/frege/gradle/plugins/FregePlugin.groovy @@ -0,0 +1,34 @@ +package frege.gradle.plugins + +import frege.gradle.tasks.FregeDoc +import frege.gradle.tasks.FregeNativeGen +import frege.gradle.tasks.FregeQuickCheck +import frege.gradle.tasks.FregeRepl +import org.gradle.api.Plugin +import org.gradle.api.Project + +class FregePlugin implements Plugin<Project> { + + Project project + + void apply(Project project) { + this.project = project + + project.plugins.apply(FregeBasePlugin) + project.plugins.apply("java") + + def replTask = project.task('fregeRepl', type: FregeRepl, group: 'Tools', dependsOn: 'compileFrege') + replTask.outputs.upToDateWhen { false } // always run, regardless of up to date checks + + def checkTask = project.task('fregeQuickCheck', type: FregeQuickCheck, group: 'Verification', dependsOn: 'testClasses') + checkTask.outputs.upToDateWhen { false } // always run, regardless of up to date checks + + project.tasks.test.dependsOn("fregeQuickCheck") + + project.task('fregeDoc', type: FregeDoc, group: 'Documentation', dependsOn: 'compileFrege') + + project.task('fregeNativeGen', type: FregeNativeGen, group: 'Tools') + + } + +} diff --git a/src/main/groovy/frege/gradle/FregePluginExtension.groovy b/src/main/groovy/frege/gradle/plugins/FregePluginExtension.groovy index dbf0d2a..ae180ec 100644 --- a/src/main/groovy/frege/gradle/FregePluginExtension.groovy +++ b/src/main/groovy/frege/gradle/plugins/FregePluginExtension.groovy @@ -1,4 +1,4 @@ -package frege.gradle +package frege.gradle.plugins /** * Created by mperry on 6/02/2015. diff --git a/src/main/groovy/frege/gradle/plugins/FregeRuntime.java b/src/main/groovy/frege/gradle/plugins/FregeRuntime.java new file mode 100644 index 0000000..4265d0b --- /dev/null +++ b/src/main/groovy/frege/gradle/plugins/FregeRuntime.java @@ -0,0 +1,63 @@ +package frege.gradle.plugins; + +import com.google.common.collect.Lists; +import org.gradle.api.Buildable; +import org.gradle.api.GradleException; +import org.gradle.api.Project; +import org.gradle.api.artifacts.Dependency; +import org.gradle.api.file.FileCollection; +import org.gradle.api.internal.file.collections.LazilyInitializedFileCollection; +import org.gradle.api.internal.tasks.TaskDependencyResolveContext; + +import java.io.File; +import java.util.List; + +public class FregeRuntime { + + private final Project project; + + public FregeRuntime(Project project) { + this.project = project; + } + + + public FileCollection inferFregeClasspath(final Iterable<File> classpath) { + return new LazilyInitializedFileCollection() { + public String getDisplayName() { + return "Frege runtime classpath"; + } + + public FileCollection createDelegate() { + final FregeJarFile fregeJar = FregeRuntime.this.findFregeJarFile(classpath); + if (fregeJar == null) { + throw new GradleException(String.format("Cannot infer Frege class path because no Frege Jar was found on class path: %s", classpath)); + } + String notation = fregeJar.getDependencyNotation(); + List<Dependency> dependencies = Lists.newArrayList(); + dependencies.add(project.getDependencies().create(notation)); + return project.getConfigurations().detachedConfiguration(dependencies.toArray(new Dependency[dependencies.size()])); + } + + public void visitDependencies(TaskDependencyResolveContext context) { + if (classpath instanceof Buildable) { + context.add(classpath); + } + } + + }; + } + + private FregeJarFile findFregeJarFile(Iterable<File> classpath) { + if (classpath == null) { + return null; + } + for (File file : classpath) { + FregeJarFile fregeJar = FregeJarFile.parse(file); + if (fregeJar != null) { + return fregeJar; + } + } + return null; + } + +} diff --git a/src/main/groovy/frege/gradle/tasks/FregeCompile.groovy b/src/main/groovy/frege/gradle/tasks/FregeCompile.groovy new file mode 100644 index 0000000..13b617c --- /dev/null +++ b/src/main/groovy/frege/gradle/tasks/FregeCompile.groovy @@ -0,0 +1,198 @@ +package frege.gradle.tasks +import groovy.transform.TypeChecked +import groovy.transform.TypeCheckingMode +import org.gradle.api.Action +import org.gradle.api.artifacts.Configuration +import org.gradle.api.file.FileCollection +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Optional +import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.compile.AbstractCompile +import org.gradle.process.JavaExecSpec + +@TypeChecked +class FregeCompile extends AbstractCompile { + + FileCollection fregeClasspath + FileCollection classpath + + @Input + String stackSize = "4m" + + @Optional + @Input + boolean hints = false + + @Optional + @Input + boolean optimize = false + + @Optional + @Input + boolean verbose = false + + @Optional + @Input + boolean inline = true + + @Optional + @Input + boolean make = true + + @Optional + @Input + boolean compileGeneratedJava = true + + @Optional + @Input + String target = "" + + @Optional + @Input + boolean comments = false + + @Optional + @Input + boolean suppressWarnings = false + + @Optional + @Input + String explain = "" + + @Optional + @Input + String extraArgs = "" + + @Optional + @Input + String allArgs = "" // this is an option to overrule all other settings + + @Optional + @Input + String module = "" + + @Optional + @Input + List<File> fregePaths = [] + + @Input + String mainClass = "frege.compiler.Main" + + @Optional + @Input + List<String> allJvmArgs = [] + + @Optional + @Input + String encoding = "" + + @Optional + @Input + String prefix = "" + + List<File> sourcePaths = [] + + @Override + @TaskAction + protected void compile() { + logConfigurationInfo() + + def jvmArgs = allJvmArgs + if (jvmArgs.isEmpty()) { + jvmArgs << "-Xss$stackSize".toString() + } + def compilerArgs = allArgs ? allArgs.split().toList() : assembleArguments() + + logger.info("Calling Frege compiler with compilerArgs: '$compilerArgs'") + + //TODO integrate with gradle compiler daemon infrastructure and skip internal execution + project.javaexec(new Action<JavaExecSpec>() { + @Override + void execute(JavaExecSpec javaExecSpec) { + javaExecSpec.args = compilerArgs + javaExecSpec.classpath = FregeCompile.this.classpath + FregeCompile.this.fregeClasspath + javaExecSpec.main = mainClass + } + }); + } + + public FregeCompile source(Object... sources) { + super.source(sources); + // track directory roots + for (Object source : sources) { + sourcePaths.add(project.file(source)) + } + return this; + } + + void logConfigurationInfo() { + def path = project.files(compileConfig()).getAsPath() + logger.info("Compile configuation as path: $path") + } + + @TypeChecked(TypeCheckingMode.SKIP) + Configuration compileConfig() { + project.configurations.compile + } + + protected List<String> assembleArguments() { + List args = [] + if (hints) + args << "-hints" + if (optimize) { + args << "-O" + args << "-inline" + } + if (inline & !optimize) + args << "-inline" + if (make) + args << "-make" + if (!compileGeneratedJava) args << "-j" + if (target != "") { + args << "-target" + args << target + } + if (comments) args << "-comments" + if (suppressWarnings) args << "-nowarn" + if (explain != "") { + args << "-explain" + args << explain + } + if (verbose) + args << "-v" + + def fp = fregePaths + if (!fp.isEmpty()) { + args << "-fp" + args << fp.collect { f -> f.absolutePath }.join(File.pathSeparator) + } + + if (sourcePaths != null && !sourcePaths.isEmpty()) { + args << "-sp" + args << sourcePaths.collect { d -> d.absolutePath }.join(File.pathSeparator) + } + + if (encoding != "") { + args << "-enc" + args << encoding + } + + if (prefix != "") { + args << "-prefix" + args << prefix + } + + args << "-d" + args << getDestinationDir() + + if (!module.isEmpty()) { + logger.info "compiling module '$module'" + args << module + } else { + args = (args + extraArgs.split().toList()).toList() + } + + args + } + +} diff --git a/src/main/groovy/frege/gradle/DocTask.groovy b/src/main/groovy/frege/gradle/tasks/FregeDoc.groovy index 061ae00..7ac49a7 100644 --- a/src/main/groovy/frege/gradle/DocTask.groovy +++ b/src/main/groovy/frege/gradle/tasks/FregeDoc.groovy @@ -1,4 +1,4 @@ -package frege.gradle +package frege.gradle.tasks import org.gradle.api.DefaultTask import org.gradle.api.internal.file.FileResolver @@ -10,7 +10,7 @@ import org.gradle.api.tasks.TaskAction import org.gradle.process.internal.DefaultJavaExecAction import org.gradle.process.internal.JavaExecAction -class DocTask extends DefaultTask { +class FregeDoc extends DefaultTask { /* Usage: java -jar fregec.jar frege.tools.Doc [-v] [-d opt] [-x mod,...] modules ... * -v print a message for each processed module diff --git a/src/main/groovy/frege/gradle/NativeGenTask.groovy b/src/main/groovy/frege/gradle/tasks/FregeNativeGen.groovy index c9128ca..6f51218 100644 --- a/src/main/groovy/frege/gradle/NativeGenTask.groovy +++ b/src/main/groovy/frege/gradle/tasks/FregeNativeGen.groovy @@ -1,4 +1,4 @@ -package frege.gradle +package frege.gradle.tasks import org.gradle.api.DefaultTask import org.gradle.api.internal.file.FileResolver @@ -11,7 +11,7 @@ import org.gradle.api.tasks.TaskAction import org.gradle.process.internal.DefaultJavaExecAction import org.gradle.process.internal.JavaExecAction -class NativeGenTask extends DefaultTask { +class FregeNativeGen extends DefaultTask { /* * Example from https://github.com/Frege/frege-native-gen: diff --git a/src/main/groovy/frege/gradle/QuickCheckTask.groovy b/src/main/groovy/frege/gradle/tasks/FregeQuickCheck.groovy index 11065ad..e06236f 100644 --- a/src/main/groovy/frege/gradle/QuickCheckTask.groovy +++ b/src/main/groovy/frege/gradle/tasks/FregeQuickCheck.groovy @@ -1,15 +1,11 @@ -package frege.gradle - +package frege.gradle.tasks import org.gradle.api.DefaultTask -import org.gradle.api.Project import org.gradle.api.internal.file.FileResolver -import org.gradle.api.tasks.InputDirectory -import org.gradle.api.tasks.Optional import org.gradle.api.tasks.TaskAction import org.gradle.process.internal.DefaultJavaExecAction import org.gradle.process.internal.JavaExecAction -class QuickCheckTask extends DefaultTask { +class FregeQuickCheck extends DefaultTask { // more options to consider: /* diff --git a/src/main/groovy/frege/gradle/ReplTask.groovy b/src/main/groovy/frege/gradle/tasks/FregeRepl.groovy index 1f570eb..64e0186 100644 --- a/src/main/groovy/frege/gradle/ReplTask.groovy +++ b/src/main/groovy/frege/gradle/tasks/FregeRepl.groovy @@ -1,4 +1,4 @@ -package frege.gradle +package frege.gradle.tasks import org.gradle.api.DefaultTask import org.gradle.api.internal.file.FileResolver @@ -6,7 +6,7 @@ import org.gradle.api.tasks.* import org.gradle.process.internal.DefaultJavaExecAction import org.gradle.process.internal.JavaExecAction -class ReplTask extends DefaultTask { +class FregeRepl extends DefaultTask { static String DEFAULT_SRC_DIR = "src/main/frege" // TODO: should this come from a source set? static String DEFAULT_CLASSES_SUBDIR = "classes/main" // TODO: should this come from a convention? diff --git a/src/main/resources/META-INF/gradle-plugins/org.frege-lang.base.properties b/src/main/resources/META-INF/gradle-plugins/org.frege-lang.base.properties new file mode 100644 index 0000000..50f947e --- /dev/null +++ b/src/main/resources/META-INF/gradle-plugins/org.frege-lang.base.properties @@ -0,0 +1 @@ +implementation-class=frege.gradle.plugins.FregeBasePlugin diff --git a/src/main/resources/META-INF/gradle-plugins/org.frege-lang.properties b/src/main/resources/META-INF/gradle-plugins/org.frege-lang.properties index 25a44ac..db20350 100644 --- a/src/main/resources/META-INF/gradle-plugins/org.frege-lang.properties +++ b/src/main/resources/META-INF/gradle-plugins/org.frege-lang.properties @@ -1 +1 @@ -implementation-class=frege.gradle.FregePlugin +implementation-class=frege.gradle.plugins.FregePlugin diff --git a/src/test/groovy/frege/gradle/FregeBasePluginTest.groovy b/src/test/groovy/frege/gradle/FregeBasePluginTest.groovy new file mode 100644 index 0000000..3ca1bb2 --- /dev/null +++ b/src/test/groovy/frege/gradle/FregeBasePluginTest.groovy @@ -0,0 +1,31 @@ +package frege.gradle + +import frege.gradle.plugins.FregeBasePlugin +import org.gradle.api.Project +import org.gradle.testfixtures.ProjectBuilder +import spock.lang.Specification + +public class FregeBasePluginTest extends Specification { + + Project project = ProjectBuilder.builder().build() + + def setup(){ + when: + project.plugins.apply(FregeBasePlugin) + } + + def "adds frege extension"(){ + expect: + project.getExtensions().getByName(FregeBasePlugin.EXTENSION_NAME) != null + } + + def "applies java base plugin"(){ + expect: + project.pluginManager.hasPlugin("java-base") + } + + def "can be identified by id"(){ + expect: + project.pluginManager.hasPlugin("org.frege-lang.base") + } +}
\ No newline at end of file diff --git a/src/test/groovy/frege/gradle/FregePluginTest.groovy b/src/test/groovy/frege/gradle/FregePluginTest.groovy new file mode 100644 index 0000000..2fc6d86 --- /dev/null +++ b/src/test/groovy/frege/gradle/FregePluginTest.groovy @@ -0,0 +1,32 @@ +package frege.gradle + +import frege.gradle.plugins.FregeBasePlugin +import frege.gradle.plugins.FregePlugin +import org.gradle.api.Project +import org.gradle.testfixtures.ProjectBuilder +import spock.lang.Specification + +class FregePluginTest extends Specification { + + Project project = ProjectBuilder.builder().build() + + def setup(){ + when: + project.plugins.apply(FregePlugin) + } + + def "adds frege extension"(){ + expect: + project.getExtensions().getByName(FregeBasePlugin.EXTENSION_NAME) != null + } + + def "applies frege base plugin"() { + expect: + project.pluginManager.findPlugin("org.frege-lang.base") != null + } + + def "can be identified by id"(){ + expect: + project.pluginManager.hasPlugin("org.frege-lang") + } +} |