2011-09-16 5 views
10

Mi piacerebbe che SBT crei un file e scriva il percorso di classe completo del runtime del progetto (scala, librerie gestite e non gestite, classi di progetto) per una particolare fase (in questo caso, solo per compile) .Creare script con classpath da SBT

sto cercando di replicare qualcosa che ho fatto con Maven, utilizzando il 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> 

Come posso fare questo con SBT?

risposta

11

I fondamenti sono giusti nella risposta di David. Ci sono alcuni piccoli modi in cui può essere migliorato. Il launcher java può essere utilizzato direttamente perché la libreria Scala è inclusa nel classpath. sbt può riconoscere automaticamente la classe principale se ne esiste solo una definita. sbt ha anche alcuni metodi che possono facilitare il lavoro con i file, come i metodi di utilità in 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 
} 

Questo può andare direttamente nel tuo build.sbt. In alternativa, definire la chiave separatamente e metterlo in 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

È possibile creare un'attività per creare un file per avviare l'app. @Kipton Barros postato in 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) 
    } 

Questo crea un file chiamato run-server.sh nella vostra directory di destinazione che ha il percorso di classe impostato correttamente per eseguire l'applicazione. Aggiungi mkunixlauncherTask alle tue buildsettings in Build.scala (o build.sbt) e poi puoi dare il comando "mkunixlauncher" per creare lo script.

Tweak a piacere.

2

appena scoperto il plugin sbt script di avvio: https://github.com/typesafehub/xsbt-start-script-plugin:

Questo plugin permette di generare un target script/inizio per un progetto . Lo script eseguirà il progetto "sul posto" (senza doverlo prima creare un pacchetto prima) .

Lo script target/start è simile a sbt run ma non si basa su SBT. sbt run non è raccomandato per l'uso in produzione perché mantiene in memoria SBT in memoria. target/start è destinato a eseguire un'applicazione nella produzione .

Il plugin aggiunge uno script di inizio attività che genera target/inizio. Lo aggiunge anche un'attività stage, con alias sull'attività script iniziale.