如何在多个项目中使用 sbt-native-packager

Posted

技术标签:

【中文标题】如何在多个项目中使用 sbt-native-packager【英文标题】:How do I use the sbt-native-packager with multiple projects 【发布时间】:2016-10-21 09:10:42 【问题描述】:

我正在将几个大型 scala 项目合并为一个。目前他们使用剪切和粘贴(不是很多代码)共享代码,我正在制作它以便有一个通用的实用程序 jar。这些项目大多部署在亚马逊云上,使用 sbt-native-packager 进行打包

我的问题是我不知道如何为 sbt 本地管理器配置多个项目。我对它也不是很熟悉,在完成所有初步工作后才进入项目。

我已将问题减少到我能解决的最小问题。 https://github.com/stave-escura/multiprojectissue.git 有一个 git repo,它演示了这个问题

在 project/plugins.sbt 中重要的几行是

addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.0.6")
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.0")

build.sbt 太长了,放在这里,但它的形状很粗略

import com.typesafe.sbt.SbtNativePackager
import com.typesafe.sbt.packager.archetypes.JavaServerAppPackaging

enablePlugins(SbtNativePackager)

enablePlugins(JavaServerAppPackaging)

lazy val commonSettings = Seq(
  ...
  scalaVersion := "2.11.8",
  assemblyJarName in assembly := s"$name.value.jar",
  assemblyMergeStrategy in assembly := 
    case "BUILD" => MergeStrategy.discard
    case other => MergeStrategy.defaultMergeStrategy(other)
  
)

lazy val project1Settings = commonSettings ++ Seq(
  rpmVendor := "someOrganisation",
  packageDescription in Rpm := "Some description1",
  rpmLicense := Some("Copyright 2016 someOrganisation. All rights reserved."),
  rpmRequirements := Seq(
    "java-1.8.0-openjdk"
  ),
  version in Rpm := "1",
  rpmRelease := version.value,
  rpmDaemonLogFile := s"$name.value.log",
  daemonUser in Linux := "someUserName",
  daemonGroup in Linux := (daemonUser in Linux).value,
  rpmPost := Some(
    """|chkconfig --add someService1
      |chkconfig someService1 on
    """.stripMargin),
  linuxPackageMappings ++= Seq()    // <--- line 53
)


lazy val project2Settings = commonSettings ++ Seq(
  identical to project 1 settings except
  packageDescription in Rpm := "Some description2",
  rpmPost := Some(
    """|chkconfig --add someService2
      |chkconfig someService2 on
    """.stripMargin),
  linuxPackageMappings ++= Seq()   // <--- line 72
)

lazy val project1 = (project in file("components/service1")).settings(project1Settings: _*)

lazy val project2 = (project in file("components/service2")).settings(project2Settings: _*)

在实际项目中,linuxPackageMappings 相当复杂,这是我的问题。它们在项目之间有所不同。当我将 build.sbt 加载到 sbt 时,我得到了错误

References to undefined settings: 

  project2/*:linuxPackageMappings from project2/*:linuxPackageMappings (~/git/multiprojectissue/build.sbt:72)

  project1/*:linuxPackageMappings from project1/*:linuxPackageMappings (~/git/multiprojectissue/build.sbt:53)

    at sbt.Init$class.Uninitialized(Settings.scala:265)
    ...
    at xsbt.boot.Boot.main(Boot.scala)
[error] References to undefined settings: 
[error] 
[error]   project2/*:linuxPackageMappings from project2/*:linuxPackageMappings (/Users/ricep02/git/multiprojectissue/build.sbt:72)
[error] 
[error]   project1/*:linuxPackageMappings from project1/*:linuxPackageMappings (/Users/ricep02/git/multiprojectissue/build.sbt:53)

我在上面包含的 build.sbt sn-p 中标记了第 53 和 72 行。

我不知道的事情 我在这方面不够熟练,不知道为什么该项目有 sbt-assembly 和 sbt-package manager。我已经从 plugins.sbt 中评论了 sbt-assembly 并且仍然遇到这个问题,所以我现在不认为这是有贡献的

我尝试过的事情 我尝试将子项目设置放入与实际组件关联的 build.sbt 文件中。我得到同样的问题。 我还仔细查看了 https://github.com/muuki88/sbt-native-packager-examples/tree/master/multi-module-build 等示例项目,并非常仔细地阅读了 http://www.scala-sbt.org/sbt-native-packager/ 的文档,尽管我对它没有“经验”:只是在“阅读文档”级别。我也看过How to setup sbt-native-packager in a single module project with multiple mains和How to create a basic project setup using sbt-native-packager等问题

有用的东西 将 packageMappings 留在 build.sbt 的“主体”中不会导致“sbt 加载问题”,但我还不知道它是否会真正构建包!

软件堆栈

操作系统:MacOs Java:1.8.0_74-b02 斯卡拉:2.11.8 sbt: 0.13.8 sbt-native-packager 1.0.6

【问题讨论】:

【参考方案1】:

看起来SbtNativePackager 需要在它们的设置中为project1project2 启用。

尝试通过添加enablePlugins(SbtNativePackager) 来修改您的设置:

lazy val project1Settings = commonSettings ++ Seq(
    rpmVendor := "someOrganisation",
    packageDescription in Rpm := "Some description1",
    rpmLicense := Some("Copyright 2016 someOrganisation. All rights reserved."),
    rpmRequirements := Seq(
        "java-1.8.0-openjdk"
    ),
    version in Rpm := "1",
    rpmRelease := version.value,
    rpmDaemonLogFile := s"$name.value.log",
    daemonUser in Linux := "someUserName",
    daemonGroup in Linux := (daemonUser in Linux).value,
    rpmPost := Some(
        """|chkconfig --add someService1
           |chkconfig someService1 on
        """.stripMargin),
    enablePlugins(SbtNativePackager),
    linuxPackageMappings ++= Seq()    // <--- line 53
)

对于项目 2 也是如此。

我建议您购买《SBT in Action》之类的书,以帮助您开始使用“简单”的构建工具。

【讨论】:

enablePlugins(SbtNativePackager) 看起来在一个有趣的地方。你还记得如果你得到了上面的编译吗?它是 DslEntry 作为类型,而不是 Def.SettingsDefinition。 sbt 0.13.15,sbt-native-packager 1.2.0 Project 实例上致电enablePlugins(...),看在上帝的份上!比如val foo = (project in file(...)).settings(...).enablePlugins(...)。这会奏效。

以上是关于如何在多个项目中使用 sbt-native-packager的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Java Spring Boot MVC 中使用 Ajax 删除多个项目

如何在单个项目中使用多个版本的 Apollo 客户端

项目中有多个目标时如何使用fabric

如何在多个项目中使用 sbt-native-packager

如何在 Owl carousel 中显示多个项目?

如何在 c# 中使用 JSON 使用 foreach 序列化多个项目?