Построение фляги проекта Фреге с использованием Gradle
Я бы хотел:
- использовать язык программирования Frege для написания простого кода "Hello World",
- затем с помощью компилятора Frege, генерирующего эквивалентный исходный код Java,
- затем создание исполняемого файла Jar для запуска из командной строки,
- все предыдущие шаги должны быть "контролированы" Gradle.
Я могу сгенерировать исходный код (элементы 1. и 2. из предыдущего списка), но я не могу указать структуру "пакета" исходного кода Java в выводе, т.е. я не вижу package
Оператор Java в качестве первой строки кода в исходном коде Java. Я могу указать компилятору Frege, где поместить сгенерированный код, хотя (через -d
аргумент).
Я думаю, что это причина, почему при создании исполняемого файла Jar, а затем при его запуске я вижу похожие ошибки (в соответствии с различными попытками выполнения задач Gradle), например: no main manifest attribute
,
Исходный код Frege сохраняется в файле с именем HelloFrege.fr
сгенерированный исходный код Java находится в файле с именем HelloFrege.java
(Я проверил файл содержит ожидаемый main
метод).
Вот версия Gradle "Jar task":
//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 ответа
Если имя вашего модуля во Фреге является неполным, например, HelloWorld
, вы не увидите оператор пакета, сгенерированный в Java. Имя модуля станет именем класса, а пакет будет пустым или пакетом по умолчанию.
Если имя вашего модуля уточнено, например, foo.bar.HelloWorld
, затем foo.bar
будет имя пакета и HelloWorld
будет именем класса в сгенерированном исходном коде Java.
Правило состоит в том, что последняя часть имени модуля становится именем класса, а квалификаторы формируют имя пакета в сгенерированном исходном коде Java.
Я не уверен, что Gradle может сделать для вас в этом отношении, но без Gradle, по крайней мере, должно быть возможно следующее:
... build your jar, as before ...
jar -uvfe project-all.jar HelloFrege
java -jar project-all.jar # run it
Это, конечно, просто еще один способ создания манифеста. Если это работает, то пришло время выяснить, почему Gradle отказывается это делать.
Постскриптум: Подумав еще минуту о том, в чем может быть проблема, мне приходит в голову, что вы можете подумать, что имя / путь исходного файла имеет какое-либо отношение к имени пакета java. Это не так во Фреге, хотя рекомендуется, чтобы путь к файлу совпадал с именем пакета, а базовое имя файла совпадало с именем класса (как в Java). Кроме того, чтобы избежать путаницы, используйте ключевое слово module во 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
Пока я публикую здесь свои выводы. Комбинация команд 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
тогда при запуске банку я получаюno main manifest attribute, in [...]
, - Если я использую только блок кода
jar
с собственностьюfrom("$projectDir") { include 'lib/**'}
чтобы включить банку Фреге, то я получаю такие ошибки, какjava.lang.ClassNotFoundException
(Я думаю, потому что Jar включен как есть, а не как набор.class
файлы). - Папка
src/main/java/org/wathever
должен быть там до запуска Gradle (дополнительная информация: префикс соглашения Mavensrc/main/java
с суффиксом "пакет Java", как указано внутриHelloFrege.fr
исходный код:module org.wathever.HelloFrege where
)
Некоторые полезные детали, которые я нашел: