SBT编译后在项目中运行代码

SBT编译后在项目中运行代码,sbt,Sbt,我们需要在编译步骤之后运行一些代码。在编译步骤之后使事情发生似乎很容易: compile in Compile <<= (compile in Compile) map{x=> // post-compile work doFoo() x } compile in compile如果您解释一下这方面的使用场景,可能会有所帮助,因为这里有一些不同的可能的解决方案路径,在它们之间进行选择可能涉及到您没有告诉我们的注意事项 您将无法将普通的方法调用写入已编译

我们需要在编译步骤之后运行一些代码。在编译步骤之后使事情发生似乎很容易:

compile in Compile <<= (compile in Compile) map{x=>
    // post-compile work
    doFoo()
    x
}

compile in compile如果您解释一下这方面的使用场景,可能会有所帮助,因为这里有一些不同的可能的解决方案路径,在它们之间进行选择可能涉及到您没有告诉我们的注意事项

您将无法将普通的方法调用写入已编译代码中。这是不可能的,因为在编译构建定义时,sbt还没有查看您的项目代码

警告:在前方漫无边际地思考

我可以建议的一个技巧是访问Test中的
testLoader以获得一个类加载器,在其中加载编译的类,然后使用反射调用其中的方法。例如,在我自己的构建中,我有:

val netlogoVersion = taskKey[String]("...")

netlogoVersion := {
  (testLoader in Test).value
    .loadClass("org.nlogo.api.Version")
    .getMethod("version")
    .invoke(null).asInstanceOf[String]
}
我不确定在测试中访问
testLoader
是否会在您的案例中真正起作用,因为
testLoader
加载您的测试类以及常规类,所以您可能会在
compilein compile
compilein Test
之间得到循环依赖关系

如果您想制作一个只加载常规类的类加载器,那么,嗯。您可以查看sbt源代码中
createTestLoader
的实现,并将其用于灵感,修改传递给
ClasspathUtilities.makeLoader
的参数。(您还可以查看
Run.run0
中的类似代码。它调用
makeLoader
,作为
Run
任务实现的一部分。)

一个不同的路径,你可以考虑在<代码>运行< /COD>任务后面重用机器来运行代码。您将无法以这种方式调用编译代码中的任意方法,只能调用

main
方法,但如果不需要返回值,您可能可以接受这种方法

fullRunTask
方法用于创建整个
run
类任务。请参阅中的“除运行外,如何创建自定义运行任务?”
fullRunTask
可以很容易地创建一个单独的任务,该任务在编译后的代码中运行某些内容,但它本身并不能帮助您找到解决方案,因为您需要一种方法将该任务附加到现有的
compile in compile
任务。如果你走这条路,我建议你把最后一个问题作为一个单独的问题来问

考虑绕过
fullRunTask
,只需将自己的调用组装到
Run.Run
。他们使用相同的机器。在我自己的构建中,我目前使用的是
fullRunTask
,但在sbt添加
fullRunTask
之前,这里是我的等效
Run。基于Run
的代码看起来像:

    (..., fullClasspath in Compile, runner, streams, ...) map {
      (..., cp, runner, s, ...) =>
        Run.run("name.of.my.MainClass",
                cp.map(_.data), Seq(), s.log)(runner)
    }
请原谅sbt 0.12,前宏语法;如果用0.13宏重做,看起来会更好


无论如何,希望这个大脑转储中的某些东西能被证明是有用的。

你可以像这样使用triggeredBy方法:

yourTask <<= (fullClasspath in Runtime) map {classpath =>
  val loader: ClassLoader = ClasspathUtilities.toLoader(classpath.map(_.data).map(_.getAbsoluteFile))
  loader.loadClass("your.class.Here").newInstance()
} triggeredBy(compile in Compile)

yourTask-changing内置任务也在中介绍,只是注意到这非常类似于是的,我看到了这些问题,但他们没有回答我关于编译后执行代码的问题。太棒了!我不知道被
触发的
。另见雷蒙德的回答谢谢赛斯,里面有很多东西我需要消化。