【问题标题】:Create script with classpath from SBT使用来自 SBT 的类路径创建脚本
【发布时间】:2012-02-15 07:58:35
【问题描述】:

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

我正在尝试使用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 做到这一点?

【问题讨论】:

    标签: scala classpath sbt


    【解决方案1】:

    大卫的回答基本正确。有一些小方法可以改进。可以直接使用 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。或者,单独定义key,放入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 ...
      )
    }
    

    【讨论】:

      【解决方案2】:

      您可以创建一个任务来创建一个文件来启动应用程序。 @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 的文件,该文件具有正确设置的类路径以运行应用程序。在 Build.scala(或 build.sbt)中将 mkunixlauncherTask 添加到您的构建设置中,然后您可以给出“mkunixlauncher”命令来创建脚本。

      调整口味。

      【讨论】:

        【解决方案3】:

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

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

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

        插件添加了一个任务启动脚本来生成目标/启动。它 还添加了一个阶段任务,别名为 start-script 任务。

        【讨论】:

          猜你喜欢
          • 2012-10-13
          • 2020-09-07
          • 2014-12-18
          • 2012-04-07
          • 1970-01-01
          • 1970-01-01
          • 2017-10-19
          • 1970-01-01
          相关资源
          最近更新 更多