Подтвердить что ты не робот

Как поддерживать несколько версий Scala в библиотеке

У меня довольно нормальный Scala project, который в настоящее время строится с использованием Maven. Я хотел бы поддержать как Scala 2.9.x, так и предстоящий 2.10, который не является бинарным или исходным. Я готов принять участие в конвертации в SBT, если это необходимо, но я столкнулся с некоторыми проблемами.

Мои требования для этого проекта:

  • Дерево с одним источником (без ветвления). Я считаю, что попытка поддержки нескольких параллельных "главных" ветвей для каждой версии Scala будет самым быстрым способом пропустить исправления между ветвями.

  • Исходные каталоги, зависящие от версии. Поскольку версии Scala не являются совместимыми с исходными кодами, мне нужно указать каталог вспомогательных источников для источников, зависящих от версии.

  • Конкретные исходные банки. Конечные пользователи должны иметь возможность загружать правильную исходную банку с соответствующими исходными версиями для своей версии Scala для интеграции IDE.

  • Интегрированное развертывание. В настоящее время я использую плагин релиза Maven для развертывания новых версий в репозитарии Sonatype OSS и хотел бы иметь аналогичный простой рабочий процесс для выпусков.

  • Поддержка конечных пользователей Maven. Мои конечные пользователи часто являются пользователями Maven, и поэтому функциональный POM, который точно отражает зависимости, является критическим.

  • Поддержка заштрихованной банки. Я должен иметь возможность создавать JAR, который включает подмножество моих зависимостей и удаляет затененные зависимости из опубликованного POM.

Вещи, которые я пробовал:

  • Профили Maven. Я создал набор профилей Maven для управления тем, какая версия Scala используется для сборки, используя плагин Maven build-helper для выбора дерева исходных версий. Это работало хорошо, пока не пришло время публиковать;

    • Использование классификаторов для квалификации версий не работает, потому что исходным банкам также нужны специальные классификаторы ( "источник-2.9.2" и т.д.), и большинство инструментов IDE не будут знать, как найти их.

    • Я попытался использовать свойство Maven, чтобы добавить суффикс _ ${ scala.version} SBT в имя артефакта, но Maven не любит свойства в имени артефакта.

  • SBT

    . Это хорошо работает, как только вы можете это понять (небольшая задача, несмотря на обширную документацию). Недостатком является то, что, похоже, не похоже на плагин Maven shadow. Я посмотрел:

    • Proguard. Плагин не обновляется для SBT 0.12.x и не будет строиться из источника, потому что он зависит от другого плагина SBT, который изменил groupIds, и не имеет версии 0.12.x под старым именем. Мне еще не удалось выяснить, как проинструктировать SBT игнорировать/заменять зависимость плагина.

    • OneJar. Это использует пользовательскую загрузку классов для запуска основных классов из встроенных банок, что не является желаемым результатом; Я хочу, чтобы файлы классов моего проекта были в банке вместе с (возможно, переименованными) файлами классов из моих затененных зависимостей.

    • Плагин сборки SBT. Это может работать в определенной степени, но в файле POM отображаются зависимости, которые я пытаюсь затенять, что не помогает моим конечным пользователям.

Я согласен с тем, что не может быть решения, которое делает то, что я хочу для Scala, и/или мне может понадобиться написать мои собственные Maven или плагины w60 для достижения цели. Но если я могу найти существующее решение.

Update

Я близок к тому, чтобы принять @Jon-Ander отличный ответ, но для меня есть еще одна выдающаяся штука, которая является единым процессом выпуска. Текущее состояние моего build.sbt находится в GitHub. (Я воспроизведу его здесь в ответ позже для потомков).

Плагин sbt-release не поддерживает сборку с несколькими версиями (т.е. + release не ведет себя так, как хотелось бы), что делает определенный смысл, поскольку процесс тегирования релиза действительно не обязательно версии. Но я хотел бы, чтобы две части процесса были мульти-версией: тестирование и публикация.

То, что я хотел бы иметь, это нечто похожее на двухэтапный процесс maven-release-плагина. На первом этапе будет выполняться административная работа по обновлению Git и запуску тестов, что в данном случае означает запуск + test, чтобы все версии были протестированы, помечены, обновлены до моментального снимка, а затем нажали результат вверх по течению.

Второй этап будет проверять тегированную версию и + publish, которая перезапустит тесты и выведет тегированные версии в репозиторий Sonatype.

Я подозреваю, что могу написать releaseProcess значения, которые делают каждый из них, но я не уверен, могу ли я поддерживать несколько значений releaseProcess в моем build.sbt. Вероятно, он может работать с некоторыми дополнительными областями, но эта часть SBT по-прежнему остается странной для меня.

В настоящее время я изменил releaseProcess, чтобы не публиковать. Затем мне нужно проверить версию с меткой вручную и запустить + publish после того, как факт, близкий к тому, что я хочу, но выполняю компромисс, тем более, что тесты выполняются только в текущей версии Scala в процессе выпуска. Я мог бы жить с процессом, который не является двухступенчатым, как плагин maven, но реализует проверку и публикацию нескольких версий.

Любая дополнительная обратная связь, которая может получить меня через последнюю милю, будет оценена.

4b9b3361

Ответ 1

Большинство из них хорошо поддерживается в sbt в одном дереве исходных текстов

Исходные каталоги, зависящие от версии, обычно не нужны. Scala программы имеют тенденцию быть совместимыми с исходным кодом - так часто на самом деле crossbuilding (http://www.scala-sbt.org/release/docs/Detailed-Topics/Cross-Build) имеет поддержку первого класса в sbt.

Если вам действительно нужен код версии, вы можете добавить дополнительные исходные папки. Поместив это в ваш файл build.sbt, вы добавите "src/main/scala - [scalaVersion]" в качестве исходного каталога для каждой версии, поскольку вы перекрестно построили в дополнение к регулярному "src/main/scala". (есть также плагин для создания прокладок между версиями, но я не пробовал - https://github.com/sbt/sbt-scalashim)

unmanagedSourceDirectories in Compile <+= (sourceDirectory in Compile, scalaVersion){ (s,v) => s / ("scala-"+v) }

версии конкретных исходных банок - см. перекрестное построение, работает из коробки

интегрированное развертывание - https://github.com/sbt/sbt-release (также имеет удивительную интеграцию git)

Конечные пользователи Maven - http://www.scala-sbt.org/release/docs/Detailed-Topics/Publishing.html

Затененный - я использовал этот https://github.com/sbt/sbt-assembly, который отлично работал для моих нужд. Ваша проблема с плагином сборки может быть решена путем перезаписи созданного pom. Вот пример, с помощью которого можно вырвать joda-time.

pomPostProcess := {
    import xml.transform._
    new RuleTransformer(new RewriteRule{
        override def transform(node:xml.Node) = {
            if((node \ "groupId").text == "joda-time") xml.NodeSeq.Empty else node
        }
    })
}

Завершить build.sbt для справки

scalaVersion := "2.9.2"

crossScalaVersions := Seq("2.9.2", "2.10.0-RC5")

unmanagedSourceDirectories in Compile <+= (sourceDirectory in Compile, scalaVersion){ (s,v) => s / ("scala-"+v) }

libraryDependencies += "joda-time" % "joda-time" % "1.6.2"

libraryDependencies += "org.mindrot" % "jbcrypt" % "0.3m"

pomPostProcess := {
    import xml.transform._
    new RuleTransformer(new RewriteRule{
        override def transform(node:xml.Node) = {
            if((node \ "groupId").text == "joda-time") xml.NodeSeq.Empty else node
        }
    })
}

Ответ 2

Я сделал что-то похожее на это с SBT в качестве примера: https://github.com/seanparsons/scalaz/commit/21298eb4af80f107181bfd09eaaa51c9b56bdc28

Это стало возможным благодаря SBT, позволяющему определять все параметры на основе других параметров, что означает, что большинство других вещей должно "просто работать".

Что касается аспекта pom.xml, я могу только порекомендовать вопрос в списке рассылки SBT, я был бы удивлен, если бы вы не могли этого сделать.

Ответ 3

Мой пост в блоге http://www.day-to-day-stuff.blogspot.nl/2013/04/fixing-code-and-binary.html содержит пример немного более тонкого решения для прикрепления разных исходных каталогов; один на майор S. Также он объясняет, как создать scala -версионный код, который может использоваться неспецифическим кодом.

Обновление 2016-11-08: Sbt теперь поддерживает это из коробки: http://www.scala-sbt.org/0.13/docs/sbt-0.13-Tech-Previews.html#Cross-version+support+for+Scala+sources