0

我有一个要在 JAR 中交付的Ammonite 脚本。

在另一个项目中,我想使用这个脚本 - 但到目前为止没有成功。

我根据文档(sol_local_build.sc)尝试过:

import $ivy.`mycompany:myproject_2.12:2.1.0-SNAPSHOT`, local_build

@main
def doit():Unit =
  println(local_build.curl("http://localhost:8080"))

local_build.sc在我要使用的脚本中。

这是我得到的例外:

sol_local_build.sc:2: '.' expected but eof found.

^
4

3 回答 3

1

该脚本必须即时编译。

把你的脚本放在一个标准的 sbt 项目中

在目录中,示例目录名称:“test1”

放置您的外部脚本(示例名称:“script.sc”)

// script.sc

println("Hello world!")

进入 test1 项目的资源目录(“test1\src\main\resources\script.sc”)

将项目发布到本地,即 sbt publishLocal

它被发布到“.ivy2\local\default\test1_2.12\0.1-SNAPSHOT\ ...”目录。

现在您可以使用以下菊石脚本“test.sc”。

它从本地 ivy 存储库中的 jar 中读取“script.sc”

并将其写入本地目录(必须具有读/写访问权限),然后执行外部进程,

它调用scala“解释器”并执行脚本。

// test.sc

import $ivy.`default:test1_2.12:0.1-SNAPSHOT`


val scriptCode = scala.util.Try {scala.io.Source.fromResource("script.sc").mkString} getOrElse """Println("Script-file not found!")"""

println("*" * 30)
println(scriptCode)
println("*" * 30)
println()


java.nio.file.Files.write(java.nio.file.Paths.get("script.sc"), scriptCode.getBytes(java.nio.charset.StandardCharsets.UTF_8))

val cmd = Seq("cmd.exe", "/c", "scala", "script.sc")

val output = sys.process.Process(cmd).!! 

println(output)

执行 Ammonite REPL 脚本,您将获得:

******************************
// script.sc

println("Hello world!")
******************************

Hello world!

该脚本没有错误处理并将文件留在运行目录中。您可以使用“-savecompiled”编译器开关加快执行速度,即

val cmd = Seq("cmd.exe", "/c", "scala", "-savecompiled", "script.sc")

然后在运行目录中创建一个额外的 .jar 文件。

于 2019-11-20T14:57:59.683 回答
0

Scala 脚本并没有真正解释,而是像每个普通的 Scala 程序一样“在后台”编译。因此,在编译期间必须可以访问所有代码,并且您不能从 jar 文件中调用其他脚本中的函数!

但是 Ammonite 具有内置的多阶段功能。它编译一个部分,执行它,然后编译下一部分!

小改进的菊石脚本。它不是没有错误的,但可以运行。

也许有更好的方法可以将脚本从 jar 中取出。你应该问李浩毅!

// test_ammo.sc 
// using ammonite ops

// in subdirectoy /test1

// Ammonite REPL:
// import $exec.test1.test_ammo
// @ Ammonite-multi-stage

import $ivy.`default::test1:0.1-SNAPSHOT`

//import scala.util.Properties
import scala.sys.process.Process

val scriptFileName = "script.sc"

write.over(pwd/"test1"/scriptFileName, read(resource(getClass.getClassLoader)/scriptFileName))

val cmd = Seq("cmd.exe", "/c", "scala", scriptFileName)
val output = Process(cmd).!! 
println(output)

@

import $exec.script // no .sc suffix

ppp() // is a function inside script.sc

使用“sbt publishLocal”在本地发布的项目资源文件夹中的 script.sc:

// script.sc

println("Hello world!")

def ppp() = println("Hello world from ppp!")
于 2019-11-24T03:47:01.270 回答
0

为了完整起见,我可以按如下方式解决我的问题:

  • 只需在这个项目中创建一个 Scala 文件。
  • 将脚本内容复制到对象中。
    package mycompany.myproject
    
    object LocalBuild {
       def curl(..)...
    }
    
  • 将依赖项添加到您的 sbt 文件(例如ammonite.ops
  • 像这样使用它:
    $ivy.`mycompany:myproject_2.12:2.1.0-SNAPSHOT`, mycompany.myproject.LocalBuild
    
       @main
       def doit():Unit =
          println(LocalBuild.curl("http://localhost:8080"))
    
    
于 2021-08-11T12:17:34.710 回答