Где разместить скомпилированные файлы классов Javascript для SBT и Play Framework 2.1, чтобы найти их?

Где я должен разместить свои скомпилированные (через Rhino) классы Javascript, чтобы они были включены в путь к классам во время компиляции и включены в сгенерированный пакет dist?

Play Framework 2.1-RC1 + SBT игнорирует их, иногда во время компиляции, а иногда при создании дистрибутивов.

1. Размещение сгенерированных файлов в classes/ или classes_managed/

Если я размещу сгенерированные файлы .class здесь или здесь:
target/scala-2.10/classes/ target/scala-2.10/classes_managed/

Тогда compile и run работают нормально. Но какой-то странный шаг компиляции (что?!) во время stage и dist не проходит: он не находит скомпилированные классы.

2. Размещение классов в специальном каталоге

Если я размещу сгенерированные файлы .class здесь: target/scala-2.10/compiledjs-classes/

И добавьте запись classpath в конфигурацию SBT:

object ApplicationBuild extends Build {
  ...
  def mainSettings = List(
    ...,
    unmanagedClasspath in Compile <+= (baseDirectory) map { bd =>
      Attributed.blank(bd / "target/scala-2.10/compiledjs-classes")
    },
    ...)

Тогда compile, run, stage и dist работают нормально. Тем не мение! Когда я распаковываю и запускаю сгенерированный файл .zip (сгенерированный с помощью dist), приложение завершается сбоем во время выполнения, поскольку скомпилированные классы Javascript не включены в .zip.

3. Размещение классов в папке lib/

Тогда compile не найдет файлы классов. (Я поместил, например, класс compiledjs.HtmlSanitizerJs в lib/compiledjs/HtmlSanitizerJs.class.)


Что я должен сделать? Я имею в виду, что работает и что является передовым опытом?

В любом случае, прямо сейчас я копирую сгенерированные классы в оба
target/scala-2.10/compiledjs-classes/ (чтобы компиляция работала) и
target/scala-2.10/classes/ (чтобы они включались в сгенерированный .zip)
Это работает, но кажется очень неправильным.

(( Как ни странно, все работало нормально с более старой версией Play Framework (старше, чем RC-1) и, когда я использовал PlayProject, а не play.Project. Затем я сохранил сгенерированные классы в target/scala-2.10/classes/, Только. ))


person KajMagnus    schedule 12.12.2012    source источник
comment
Можете ли вы попробовать 2. с папкой, которая находится не в target, а в baseDirectory?   -  person Schleichardt    schedule 13.12.2012
comment
@Шлейхардт Готово. Компиляция работает, но stage и dist не работают (потому что java.lang.NoClassDefFoundError, когда сгенерированные классы не найдены).   -  person KajMagnus    schedule 15.12.2012
comment
А в SBT команда classpath не отображает папку, которая находится не в целевом, а в базовом каталоге, а именно compiledjs-classes в моем случае. Однако show full-classpath указывает на эту папку, compiledjs-classes. Итак, что я сделал, похоже, сказал SBT включать папку только при компиляции, но не при создании дистрибутива?   -  person KajMagnus    schedule 15.12.2012
comment
В SBT clean не удаляет папку compiledjs-classes.   -  person KajMagnus    schedule 15.12.2012
comment
для чистой проблемы существует решение: stackoverflow.com/questions/10471596/   -  person Schleichardt    schedule 15.12.2012


Ответы (1)


Я не мог найти способ поместить файлы классов в банки на сценической задаче. В качестве обходного пути я создаю файл JAR на сцене, а при запуске игры я устанавливаю путь к классам в папку «rhino» в базовой папке.

Я создал для вас суть, чтобы вы могли проверить ее и попробовать: https://gist.github.com/4321216 rhino/so/Example.class представляет класс Rhino, но является только классом Java, который возвращает строку.

Добавьте в свой Build.scala:

  val rhinoJarName = "rhino.jar"
  val folderForRhinoJar = unmanagedBase
  val rhinoClasspath = (baseDirectory) map { base => Attributed.blank(base / "rhino")}
  val rhinoClassesToJar = TaskKey[Unit]("rhino-classes-to-jar")
  val rhinoClassesToJarInitializer = (base: File, folderForJar: File) => {
    val rhinoFolder = new File(base, "rhino")
    val isClassFile = (file: File) => file.getName.endsWith("class")
    val classFiles =  rhinoFolder.***.filter(isClassFile).get
    val sources = classFiles map { file =>
      file -> file.getCanonicalPath.drop(rhinoFolder.getCanonicalPath.length + 1)
    }
    IO.jar(sources, folderForJar / rhinoJarName, new java.util.jar.Manifest())
  }

  val main = play.Project(appName, appVersion, appDependencies).settings(
    unmanagedClasspath in Compile <+= rhinoClasspath,
    unmanagedClasspath in Runtime <+= rhinoClasspath,
    rhinoClassesToJar <<= (baseDirectory, folderForRhinoJar) map rhinoClassesToJarInitializer,
    playStage <<= playStage.dependsOn(rhinoClassesToJar),
    playStage <<= (playStage, folderForRhinoJar) map {(unused, folder) =>
      IO.delete(folder / rhinoJarName)
    },
    cleanFiles <+= folderForRhinoJar { _ / rhinoJarName } //make sure jar will be deleted if play stage does not finish and cleanup jar
  )
person Schleichardt    schedule 17.12.2012
comment
Спасибо за этот подробный пример :-) Я не уверен, что лучше поместить классы в JAR и включить JAR в сборку, чем копировать классы непосредственно в папку target/scala-2.10/classes/? Я думаю, что в моем случае последний подход на самом деле немного проще, так как я вызываю сценарий Makefile и просто добавляю строку cp …. - person KajMagnus; 19.12.2012
comment
Одна вещь, которую я не понимаю, в примере: как Play знает, что нужно включить сгенерированный JAR при запуске stage/dist? rhinoClassesToJar создает JAR, так как playStage.dependsOn(rhinoClassesToJar) — а дальше что? JAR создается, но не нужно ли указывать SBT, чтобы он каким-то образом включал его в сгенерированные пакеты файлов? - person KajMagnus; 19.12.2012
comment
SBT иногда плохо читается. Что происходит на самом деле: я перезаписываю play dist. Сначала JAR с классами rhino создается в папке lib (unmanagedBase), затем запускается настоящая команда dist, видит rhino.jar и включает его, после чего JAR удаляется. - person Schleichardt; 19.12.2012