使用SBT来驱动包含SWIG和C ++编译的构建Java + Scala构建

时间:2016-01-18 15:08:57

标签: scala sbt swig

我即将编写一个(大部分)SWIG的C ++库包装的构建配置,可以从Scala中调用。由于Scala方面存在第三方依赖,以及大量的社区支持,我想使用sbt自动化构建。

但是,我对使swig和c ++编译步骤自动化感到有点不知所措。有没有人有过sbt驱动的混合语言构建配置的经验,可以就此提供建议吗?

到目前为止,我已经找到了sbt-sh插件,但如果可能的话,我宁愿避免直接炮轰。我还考虑过使用cmake作为驱动程序(因为cmake确实有一个swig-driver插件),并且在完成swig和c ++构建步骤之后,有一个java / scala-only构建步骤触发了cmake。

2 个答案:

答案 0 :(得分:1)

SBT有自己的语法来执行外部进程。您可以利用此+路径查找+源代码生成。

一个粗略的例子:

lazy val invokeSwig = taskKey[Seq[File]]("invoke swig")
invokeSwig := {
  s"swig -java example.i -outdir ${target.value}" !
  val pathFinder = target.value ** "*.java"
  pathFinder.get
}
target in invokeSwig := target.value / "swig"
sourceGenerators in Compile <+= invokeSwig

注意:我使用的是sbt v0.13.9,但这也适用于其他版本。

您必须为本机组件执行一些额外的工作。这包括编译它们以及确保它们在运行期间可用。

答案 1 :(得分:0)

不幸的是,我不认为你可以绕过一些shell脚本,因为swig是一个命令行工具。 (我还没有找到任何java包装器。)

SBT具有源生成器的概念。源生成器只不过是一个函数/任务编写(并返回)一些文件。如果你这样做,那么SBT将首先执行所有源生成器,然后再开始编译(其余的)代码。

只需确保swig将其文件输出到sourceManaged in Compile,然后在编译期间生成的源文件在类路径中可用。

def runSwig: Seq[File] = {
  import sys.process._
  Seq("swig" , "param1", "param2", "..." ).!
  // Somehow determine which files have been written by swig.
  // I would make swig output its files to a temp directory and copy them to the source managed directory manually.
}

sourceGenerators in Compile += Def.task {
  runSwig
} 

我不确定C ++代码。在我自己的项目中,我使用docker交叉编译到各种平台。如果您的本机代码不经常更改,我建议不要在每次SBT编译java / scala代码时重新编译本机代码。