40

私は現在Mavenを使用して構築されているかなり普通のScalaプロジェクトを持っています。Scala 2.9.xと、バイナリまたはソース互換ではない次の2.10の両方をサポートしたいと思います。必要に応じてSBTへの変換を喜んで受け入れますが、いくつかの課題に直面しました。

このプロジェクトの私の要件は次のとおりです。

  • 単一のソースツリー(分岐なし)。Scalaのバージョンごとに複数の同時「マスター」ブランチをサポートしようとすることが、ブランチ間のバグ修正を見逃す最も簡単な方法になると思います。

  • バージョン固有のソースディレクトリ。Scalaのバージョンはソースと互換性がないため、バージョン固有のソースの補助ソースディレクトリを指定できる必要があります。

  • バージョン固有のソースjar。エンドユーザーは、IDE統合用のScalaのバージョンについて、正しいバージョン固有のソースを含む正しいソースjarをダウンロードできる必要があります。

  • 統合された展開。私は現在、Mavenリリースプラグインを使用して新しいバージョンをSonatype OSSリポジトリにデプロイしていますが、リリースについても同様に単純なワークフローが必要です。

  • エンドユーザーのMavenサポート。私のエンドユーザーは多くの場合Mavenユーザーであるため、依存関係を正確に反映する機能的なPOMが重要です。

  • 影付きのjarサポート。依存関係のサブセットを含み、公開されたPOMから影付きの依存関係を削除するJARを作成できる必要があります。

私が試したこと:

  • Mavenプロファイル。Mavenビルドヘルパープラグインを使用してバージョン固有のソースツリーを選択し、ビルドに使用するScalaのバージョンを制御するMavenプロファイルのセットを作成しました。これは、公開するときまではうまく機能していました。

    • ソースjarにもカスタム分類子(「source-2.9.2」など)が必要であり、ほとんどのIDEツールはそれらを見つける方法を知らないため、分類子を使用してバージョンを修飾することはうまく機能しません。

    • Mavenプロパティを使用してSBTスタイルの_${scala.version}サフィックスをアーティファクト名に追加しようとしましたが、Mavenはアーティファクト名のプロパティが好きではありません。

  • SBT。これは、一度理解できればうまく機能します(豊富なドキュメントにもかかわらず、小さな作業ではありません)。欠点は、Mavenシェードプラグインに相当するものがないように見えることです。私が見た:

    • プロガード。プラグインはSBT0.12.x用に更新されておらず、groupIdsを変更した別のSBTプラグインに依存しており、古い名前で0.12.xバージョンがないため、ソースからビルドされません。プラグインの依存関係を無視/置換するようにSBTに指示する方法をまだ理解できていません。

    • OneJar。これは、カスタムクラスの読み込みを使用して、埋め込まれたjarからメインクラスを実行しますが、これは望ましい結果ではありません。プロジェクトのクラスファイルを、シェーディングされた依存関係からの(おそらく名前が変更された)クラスファイルと一緒にjarファイルに入れたいと思います。

    • SBTアセンブリプラグイン。これはある程度機能する可能性がありますが、POMファイルには、シェーディングしようとしている依存関係が含まれているように見えます。これは、エンドユーザーの助けにはなりません。

私は、Scalaに望むことを実行するソリューションがない可能性があること、および/または目標を達成するために独自のMavenまたはScalaプラグインを作成する必要がある可能性があることを認めます。しかし、可能であれば、既存の解決策を見つけたいと思います。

アップデート

@ Jon-Anderのすばらしい答えを受け入れるところですが、それでも私にとって傑出した作品が1つあります。それは、統一されたリリースプロセスです。build.sbtの現在の状態はGitHubにあります。(後世のために、後で回答で再現します)。

sbt-releaseプラグインは、マルチバージョンビルドをサポートしていません(つまり、+ release希望どおりに動作しません)。これは、リリースタグ付けのプロセスが実際にはバージョン間で発生する必要がないため、一種の意味があります。ただし、プロセスの2つの部分、つまりテストと公開をマルチバージョンにしたいと思います。

私がしたいのは、2段階のmaven-release-pluginプロセスに似たものです。最初の段階では、Gitの更新とテストの実行という管理作業を行います。この場合+ test、すべてのバージョンがテストされるように実行し、タグ付けし、スナップショットに更新してから、結果をアップストリームにプッシュします。

第2段階では、タグ付きバージョンとをチェックアウトし+ publishます。これにより、テストが再実行され、タグ付きバージョンがSonatypeリポジトリにプッシュされます。

これらのそれぞれを実行する値を記述できると思いますが、で複数の値をreleaseProcessサポートできるかどうかはわかりません。それはおそらくいくつかの追加のスコープで動作する可能性がありますが、SBTのその部分はまだ私には奇妙なマジックです。releaseProcessbuild.sbt

私が現在行っていることは、releaseProcess公開しないように変更されています。次に、タグ付けされたバージョンを手動でチェックアウトし、+ publish事後に実行する必要があります。これは、私が望むものに近いですが、妥協します。特に、テストはリリースプロセスの現在のscalaバージョンでのみ実行されるためです。Mavenプラグインのように2段階ではないが、マルチバージョンのテストと公開を実装するプロセスで生きることができます。

ラストマイルを超えて私を得ることができる追加のフィードバックをいただければ幸いです。

4

3 に答える 3

14

これのほとんどは、単一のソースツリー内のsbtで十分にサポートされています

通常、バージョン固有のソースディレクトリは必要ありません。Scalaプログラムはソース互換である傾向があります-実際、クロスビルディング(http://www.scala-sbt.org/release/docs/Detailed-Topics/Cross-Build)はsbtでファーストクラスのサポートを持っていることがよくあります。

バージョン固有のコードが本当に必要な場合は、ソースフォルダーを追加できます。これをbuild.sbtファイルに入れると、通常の「src / main / scala」に加えて、クロスビルド時に各バージョンのソースディレクトリとして「src / main/scala-[scalaVersion]」が追加されます。(バージョン間でシムを生成するために利用できるプラグインもありますが、私はそれを試していません-https://github.com/sbt/sbt-scalashim

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

バージョン固有のソースjar-クロスビルディングを参照してください。箱から出してすぐに機能します

統合されたデプロイメント-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
        }
    })
}
于 2012-12-14T14:26:59.413 に答える
2

例としてSBTを使用して、これと同様のことを行いました: https ://github.com/seanparsons/scalaz/commit/21298eb4af80f107181bfd09eaaa51c9b56bdc28

これはSBTによって可能になり、他の設定に基づいてすべての設定を決定できるようになりました。つまり、他のほとんどのものは「正常に機能する」はずです。

pom.xmlの側面に関しては、SBTメーリングリストで質問することをお勧めしますが、それができなかった場合は驚きます。

于 2012-12-14T12:55:01.757 に答える
0

私のブログ投稿http://www.day-to-day-stuff.blogspot.nl/2013/04/fixing-code-and-binary.htmlには、さまざまなソースディレクトリをアタッチするためのもう少しきめ細かいソリューションの例が含まれています。メジャーSごとに1つ。また、非特定のコードで使用できるscalaバージョン固有のコードを作成する方法についても説明します。

アップデート2016-11-08:Sbtはこれをすぐにサポートするようになりました:http ://www.scala-sbt.org/0.13/docs/sbt-0.13-Tech-Previews.html#Cross-version+support+for+ Scala+ソース

于 2013-06-19T08:43:49.177 に答える