使用SBT中的类路径创建脚本

时间:2011-09-16 19:10:22

标签: scala classpath sbt

我想让SBT创建一个文件,并为特定阶段编写项目的运行时完整类路径(scala,托管和非托管库,项目类)(在本例中,仅针对compile)。 / p>

我正在尝试使用maven-antrun-plugin

复制我使用Maven所做的事情
<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-antrun-plugin</artifactId>
      <version>1.6</version>
      <executions>
        <execution>
          <id>generate-runner</id>
          <phase>package</phase>
          <configuration>
            <target>
              <property name="runtime_classpath" refid="maven.runtime.classpath" />
              <property name="runtime_entrypoint" value="com.biasedbit.webserver.Bootstrap" />

              <echo file="../../bin/run-server.sh" append="false">#!/bin/sh
java -classpath ${runtime_classpath} ${runtime_entrypoint} $$*
              </echo>
            </target>
          </configuration>
          <goals>
            <goal>run</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

如何使用SBT进行此操作?

3 个答案:

答案 0 :(得分:11)

大卫答案的基本原理是正确的。有一些小方法可以改进。可以直接使用java启动程序,因为Scala库包含在类路径中。如果只有一个定义的,sbt可以自动检测主类。 sbt还有一些方法可以使文件更容易处理,例如sbt.IO中的实用程序方法。

TaskKey[File]("mkrun") <<= (baseDirectory, fullClasspath in Runtime, mainClass in Runtime) map { (base, cp, main) =>
  val template = """#!/bin/sh
java -classpath "%s" %s "$@"
"""
  val mainStr = main getOrElse error("No main class specified")
  val contents = template.format(cp.files.absString, mainStr)
  val out = base / "../../bin/run-server.sh"
  IO.write(out, contents)
  out.setExecutable(true)
  out
}

这可以直接放入build.sbt。或者,单独定义密钥并将其放在project/Build.scala

import sbt._
import Keys._

object MyBuild extends Build {
  val mkrun = TaskKey[File]("mkrun")
  lazy val proj = Project("demo", file(".")) settings(
    mkrun <<= ... same argument as above ...
  )
}

答案 1 :(得分:3)

您可以创建任务来创建文件以启动应用。 @Kipton Barros在How do I run an sbt main class from the shell as normal command-line program?中发布了这个:

  val MkUnixlauncher = config("mkunixlauncher") extend(Compile)
  val mkunixlauncher = TaskKey[Unit]("mkunixlauncher")
  val mkunixlauncherTask = mkunixlauncher <<= (target, fullClasspath in Runtime) map { (target, cp) =>
    def writeFile(file: File, str: String) {
      val writer = new PrintWriter(file)
      writer.println(str)
      writer.close()
    }
    val cpString = cp.map(_.data).mkString(System.getProperty("path.separator"))
    val runtime_entrypoint = "com.biasedbit.webserver.Bootstrap"
    val launchString = """
CLASSPATH="%s"
scala -usejavacp -Djava.class.path="${CLASSPATH}" %s "$@"
""".format(cpString, entrypoint)
    val targetFile = (target / "run-server.sh").asFile
    writeFile(targetFile, launchString)
    targetFile.setExecutable(true)
  }

这将在目标目录中创建一个名为run-server.sh的文件,该文件已正确设置类路径以运行该应用程序。将mkunixlauncherTask添加到Build.scala(或build.sbt)中的构建集,然后您可以使用“mkunixlauncher”命令来创建脚本。

调味。

答案 2 :(得分:2)

刚刚发现了sbt启动脚本插件:https://github.com/typesafehub/xsbt-start-script-plugin

  

此插件允许您为a生成脚本目标/开始   项目。该脚本将“就地”运行项目(无需)   首先构建一个包。)

     

目标/启动脚本类似于sbt run,但它不依赖于   SBT。 sbt run不建议用于生产用途,因为它保留   SBT本身就在内存中。 target / start旨在运行应用程序   生产

     

该插件添加了一个生成目标/开始的任务启动脚本。它   还添加了一个阶段任务,别名为启动脚本任务。