使用SBT构建跨平台

时间:2015-10-12 00:31:05

标签: build sbt cross-platform sbt-native-packager

我目前正在测试SBT Native Packager,我期望的结果是为每个支持的平台提供本机安装程序。显然,要执行此操作,平台特定的SBT任务将需要在该平台上运行。

构建将由Atlassian的Bamboo或JetBrains的Team City完成。

理想情况下,我只会进行一次编译和测试,并为打包任务重复使用相同的工件。

用SBT解决这个问题的好方法是什么?

我能想到的一种方法是在任何平台上进行编译和测试,然后将它们发布到本地存储库。然后包将以某种方式使用这些。但是,这也需要更改包装,以便它不依赖于编译任务等。

1 个答案:

答案 0 :(得分:3)

TL; DR版本:使用单独的sbt项目。

正如您可能已经注意到的,JDKPackager插件会在各种平台上创建本机包。构建和测试主要工件一次的技巧是将它们发布到工件服务器,然后有一个单独的项目来创建安装程序。

如果您的项目每个平台只需要一个安装程序,那么您需要做的就是添加依赖项,设置mainClass密钥,然后添加enablePlugins(JDKPackagerPlugin)

enablePlugins(JDKPackagerPlugin)

name := "JDKPackagerPlugin Example"

version := "0.1.0"

organization := "com.foo.bar"

libraryDependencies += "com.foo.bar" %% "myProject" % "0.1.0"

mainClass in Compile := Some("com.foo.bar.ExampleApp")

// Optional: provide application file associations
jdkPackagerAssociations := Seq(
    FileAssociation("foobar", "application/foobar", "Foobar file type"),
    FileAssociation("barbaz", "application/barbaz", "Barbaz file type", jdkAppIcon.value)
)

如果你有一个每个平台需要多个安装程序的场景(例如命令行工具和GUI),我通常会构建一个项目,使其具有一个名为“packaging”的子目录,其中包含一个独立的build.xml文件,聚合定义每个安装程序配置的单独子项目:

// Settings common across subprojects. Could also do this with a 
// project-specific `AutoPlugin`
val baseSettings = Seq(
    libraryDependencies += "com.foo.bar" %% "myProject" % "0.1.0"
)

// The packaging aggregation project
lazy val packaging = project
   .in(file("."))
   .aggregate(a, b)

// Project with CLI configuration
lazy val a = Project(id = "my-project-cli", base = file("my-project-cli"))
  .settings(baseSettings: _*)

// Project with GUI configuration    
lazy val b = Project(id = "my-project-gui", base = file("my-project-gui"))
  .settings(baseSettings: _*)

// Create a task for invoking the sub-projects as needed
val packageSubs = taskKey[Seq[File]]("Build packages in subprojects")
(packageSubs in packaging) := {
  Seq(
    (packageBin.in(a, Universal)).value,
    (packageBin.in(b, JDKPackager)).value
  ) 
}

我发现打破这样的安装程序配置有助于保持依赖关系和特定自定义的效果。