1

我想:

  1. 使用 Frege 编程语言编写一段简单的“Hello World”代码,
  2. 然后使用 Frege 编译器生成等效的 Java 源代码,
  3. 然后构建一个可执行的 Jar 文件以从命令行运行,
  4. 前面的所有步骤都应该由 Gradle “控制”。

我能够生成源代码(上一个列表中的第 1 项和第 2 项),但我无法在输出中指定 Java 源代码的“包”结构,即我看不到packageJava 语句为生成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 源代码文件中。

4

3 回答 3

2

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

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

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

于 2014-11-03T01:43:21.113 回答
1

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

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

当然,这只是创建清单的另一种方式。如果这可行,那么是时候调查 gradle 拒绝这样做的原因了。

后记:在考虑了问题可能是什么之后,我突然想到您可能认为源文件名/路径与 java 包名有关。这在 Frege 中并非如此,尽管让文件路径与包名匹配,并且文件基名与类名匹配是一种很好的做法(就像在 Java 中一样)。此外,为了消除一些混乱,请在 frege 中使用module关键字。正如 Marimuthu 所解释的,Java 包和类名是从 frege 模块名派生的。

例子:

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

这会Baz在 package 中生成类my.org,并在其中创建类文件bin/my/org/Baz.class

于 2014-11-03T17:57:58.543 回答
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文件包含在内)。
  • 该文件夹src/main/java/org/wathever需要在运行 Gradle 之前存在(附加信息:Maven 约定前缀src/main/java,后缀为HelloFrege.fr源代码中指定的“Java 包” module org.wathever.HelloFrege where:)

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

于 2014-11-03T22:29:56.100 回答