2014-01-29 28 views
3

我們需要在編譯步驟後運行一些代碼。使事情發生編譯步驟後似乎很簡單:編譯後的項目中SBT運行代碼

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

但你怎麼跑在新編譯的代碼的東西嗎?

有關該場景的更多信息:我們在電梯項目中使用較少的css。我們希望在編譯期間,在測試等運行之前,使用相同的代碼,在運行中儘可能少地編譯成css(如果需要的話)以幫助開發人員,但生成更少。少一點可能會有所幫助,但我們一般感興趣的是如何解決這個問題。

+0

改變內置任務覆蓋在http://stackoverflow.com/questions/7820939/ –

+0

也,只是注意到這是非常類似於http://stackoverflow.com/questions/17045860/sbt-apply-task -after-compile –

+0

是的,我看到了這些問題,但它們沒有回答我編譯後執行代碼的問題。 –

回答

3

可以使用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) 

這將實例化您的類,它剛剛被編譯,使用你的應用程序運行時類路徑,任何編譯後。

+1

太棒了!我不知道'triggeredBy'。 –

2

如果您爲此解釋了您的使用場景,這可能會有所幫助,因爲這裏有一些不同的可能解決方案路徑,如果在它們之間進行選擇可能會涉及您尚未告訴我們的考慮因素。

您將無法只將普通方法調用寫入編譯代碼。這是不可能的,因爲在構建定義的時候,sbt還沒有查看你的項目代碼。

警告:漫不經心地想出來。

我可以建議的一個技巧是訪問testLoader in Test以獲得一個類加載器,在該類加載器中加載已編譯的類,然後使用反射在那裏調用方法。例如,在我自己的構建,我有:

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

netlogoVersion := { 
    (testLoader in Test).value 
    .loadClass("org.nlogo.api.Version") 
    .getMethod("version") 
    .invoke(null).asInstanceOf[String] 
} 

我不知道是否訪問testLoader in Test會在你的情況下,實際的工作,因爲testLoader負載測試類以及你的普通班,所以你可能會得到一個圓compile in Compilecompile in Test之間的依賴關係。

如果你想嘗試製作一個只有正常類加載的類加載器,那麼,嗯。您可以在執行createTestLoader時查看sbt源代碼並將其用於獲取靈感,修改傳遞給ClasspathUtilities.makeLoader的參數。 (您也可以看看Run.run0類似的代碼。它調用makeLoaderrun任務的實現的一部分。)

你可能會考慮不同的路徑是重用run任務背後的機械運行代碼。您將無法通過這種方式在編譯代碼中調用任意方法,只能使用main方法,但如果不需要返回值,也許您可​​以忍受。

fullRunTask方法存在用於創建整個run類似的任務。請參閱「除運行之外,如何創建自定義運行任務?」從http://www.scala-sbt.org/0.13.1/docs/faq.htmlfullRunTask可以很容易地創建一個單獨的任務,它在編譯的代碼中運行某些東西,但是它本身並不會讓您一路解決問題,因爲您需要將該任務附加到現有的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宏重做,這看起來會更好。

無論如何,希望這個大腦轉儲證明有用。

+0

另請參閱雷蒙德的答案 –

+0

謝謝Seth在那裏有很多東西,我需要消化。 –