2011-09-16 58 views
10

我想让SBT创建一个文件并为特定的阶段编写项目的运行时完整类路径(scala,managed和unmanaged libs,项目类)(在这种情况下,仅适用于compile) 。用SBT的类路径创建脚本​​

我想复制我的东西与Maven一样,使用maven-antrun-plugin

<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?

回答

11

David的答案中的基本原理是正确的。有一些小的方法可以改进。 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 "[email protected]" 
""" 
    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 ... 
) 
} 
3

您可以创建一个任务来创建一个文件来启动应用程序。 @Kipton巴罗斯在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 "[email protected]" 
""".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

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

这个插件可以让你生成一个脚本目标/启动一个 项目。该脚本将运行“就地”项目(无需首先构建软件包 )。

目标/启动脚本与sbt运行类似,但不依赖于 SBT。 sbt run不推荐用于生产用途,因为SBT本身在内存中保留 。目标/开始旨在运行 生产中的应用程序。

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