Построение фляги проекта Фреге с использованием Gradle

Я бы хотел:

  1. использовать язык программирования Frege для написания простого кода "Hello World",
  2. затем с помощью компилятора Frege, генерирующего эквивалентный исходный код Java,
  3. затем создание исполняемого файла Jar для запуска из командной строки,
  4. все предыдущие шаги должны быть "контролированы" 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 (дополнительная информация: префикс соглашения Maven src/main/java с суффиксом "пакет Java", как указано внутри HelloFrege.fr исходный код: module org.wathever.HelloFrege where)

Некоторые полезные детали, которые я нашел:

Другие вопросы по тегам