使用Gradle构建一个Frege项目的Jar

时间:2014-11-03 00:04:32

标签: ant gradle executable-jar frege

我想:

  1. 使用Frege编程语言编写一段简单的“Hello World”代码,
  2. 然后使用Frege编译器生成等效的Java源代码,
  3. 然后构建一个可执行的Jar文件,从命令行运行,
  4. 所有前面的步骤都应由Gradle“控制”。
  5. 我能够生成源代码(上一个列表中的第1项和第2项),但是我无法在输出中指定Java源代码的“包”结构,即我看不到package Java语句作为生成Java源代码中的第一行代码。我可以指定Frege编译器在哪里放置生成的代码(通过-d参数)。

    我认为这就是为什么在构建可执行Jar时,然后启动它,我看到类似的错误(根据对Gradle任务的不同尝试),例如:no main manifest attribute

    Frege源代码保存在名为HelloFrege.fr的文件中,生成的Java源代码位于名为HelloFrege.java的文件中(我验证了该文件包含预期的main方法)。

    这里有Gradle“Jar任务”的版本:

    //create a single Jar with all dependencies
    task fatJar(type: Jar) {
        manifest {
            attributes  'Implementation-Title': 'Hello Frege Jar Example',
                        'Implementation-Version': version,
                        'Main-Class': 'HelloFrege'
        }
        baseName = project.name + '-all'
        from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
        with jar
    }
    

    这里有另一个版本的Gradle“Jar”任务:

    jar {
        manifest {
            attributes 'Main-Class': 'HelloFrege'
        }
    }
    

    我该如何解决这个问题?我想避免手动将包引用添加到自动生成的Java源代码文件中。

3 个答案:

答案 0 :(得分:2)

如果Frege中的模块名称不合格,例如HelloWorld,则不会看到用Java生成的package语句。模块名称将成为类名,包将为空或默认包。

如果您的模块名称是合格的,例如foo.bar.HelloWorld,那么foo.bar将是包名称,HelloWorld将是生成的Java源代码中的类名。

规则是模块名称的最后一部分成为类名,限定符在生成的Java源代码中形成包名。

答案 1 :(得分:1)

我不确定gradle在这方面可以为你做什么,但如果没有gradle,至少应该有以下几点:

... build your jar, as before ...
jar -uvfe project-all.jar HelloFrege
java -jar project-all.jar   # run it

当然,这只是创建清单的另一种方式。如果这样做,那么就该研究为什么gradle拒绝这样做了。

Postscriptum:在考虑了问题可能是另一分钟之后,我发现你可能认为源文件名/路径与java包名有关。虽然最好让文件路径与包名匹配,并且文件基名与类名匹配(就像在Java中一样),但在Frege中并非如此。此外,要消除一些混淆,请在frege中使用模块关键字。正如Marimuthu所解释的,Java包和类名是从frege模块名称派生的。

示例:

$ cat Foo.fr
module my.org.Baz where
...
$ java -jar fregec.jar -d bin Foo.fr

这会在包Baz中生成my.org类,并在bin/my/org/Baz.class

中创建类文件

答案 2 :(得分:0)

到目前为止,我发布了我的调查结果。适用于我的Gradle命令组合如下(从命令行输入gradle clean generateJavaSrcFromFregeSrc fatJar调用它):

task generateJavaSrcFromFregeSrc {
    ant.java(jar:"lib/frege3.21.586-g026e8d7.jar",fork:true) {
    arg(value: "-j") // do not run the java compiler
    arg(value: "-d")
    arg(value: "src/main/java") // the place where to put the generated source code (paired to the -d argument)
    arg(value: "src/main/frege/HelloFrege.fr")
    }
}

jar {
    manifest {
       attributes 'Main-Class': 'org.wathever.HelloFrege'
    }
}

task fatJar(type: Jar) {
    from files(sourceSets.main.output.classesDir)
    from files(sourceSets.main.output.resourcesDir)
    //from {configurations.compile.collect {zipTree(it)}} // this does not include the autogenerated source code
    baseName = project.name + '-fatJar'
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
    with jar
}
  • 需要在jar代码块中指定清单详细信息,如果我在task fatJar中指定它们,那么在运行jar时我会no main manifest attribute, in [...]
  • 如果我只使用带有属性jar的代码块from("$projectDir") { include 'lib/**'}来包含Frege jar,那么我会收到类似java.lang.ClassNotFoundException的错误(我认为因为它包含了Jar)是,而不是一组.class文件。
  • 在运行Gradle之前,文件夹src/main/java/org/wathever必须存在(附加信息:Maven约定前缀src/main/java,后缀为HelloFrege.fr源代码中指定的“Java包” :module org.wathever.HelloFrege where

我发现了一些有用的细节: