2014-04-12 7 views
6

के साथ ऐप लॉन्च करने के लिए एसबीटी प्लगइन कैसे लिखना है, मैं इसे खोलने से पहले अपने प्रोजेक्ट के लिए एक एसबीटी प्लगइन बनाना चाहता हूं।एक एजेंट

प्रोजेक्ट एक अनुप्रयोग चलाने की शुरुआत में जावा एजेंट को संलग्न करता है, इसे विभिन्न प्रकार के प्रोफाइलिंग के लिए उपकरण के लिए। एजेंट बाद में प्रसंस्करण के लिए पाठ फ़ाइलों को लिखता है।

मैं

  • , run के लिए एक विकल्प runWithProfiling जो एक नया जावा प्रक्रिया की शुरूआत कहा जाता है हो सकता है कि एजेंट के साथ तर्क सूची में जोड़ा एक एसबीटी प्लगइन लिखने में सक्षम होना चाहते हैं, और गुजर सभी उपयोगकर्ता आदेश।
  • बाहर निकलने पर, मैं तो एक HTML रिपोर्ट

मैं मोटे तौर पर जानते नए आदेश बनाने के लिए कैसे निर्माण करने के लिए कुछ मनमाने ढंग से पोस्ट-प्रोसेसिंग कोड आह्वान करने के लिए चाहते हैं, लेकिन मैं नहीं जानता कि कैसे सबसे अच्छा एक विकल्प लागू करने के लिए run पर ... मैं run करता है कि सभी कोड की प्रतिलिपि बनाकर पहिया को पुन: आविष्कार नहीं करना चाहता हूं। क्या कोई तरीका है कि मैं run का आह्वान कर सकता हूं लेकिन यह सुनिश्चित करता हूं कि मेरे पैरामीटर पारित हो जाएं (एक बार) और यह निश्चित रूप से एक नई जावा प्रक्रिया है?

इसके अलावा, परीक्षणों के लिए ऐसा करने में सक्षम होना बहुत अच्छा होगा।

अद्यतन: इस कोड को मैं वर्तमान में है कि है, लेकिन यह ऊपर के रूप में चिह्नित है, कई समस्याओं से ग्रस्त है TODO रों

import sbt._ 
import Keys._ 
import sbt.Attributed.data 

object LionPlugin extends Plugin { 

    val lion = TaskKey[Unit]("lion", "Run a main class with lions-share profiling.") 

    override val projectSettings = Seq(
    fork := true, 
    javaOptions ++= Seq(
     "-Xloggc:gc.log", "-XX:+PrintGCDetails", "-XX:+PrintGCDateStamps", 
     "-XX:+PrintTenuringDistribution", "-XX:+PrintHeapAtGC" 
     // TODO: need to get hold of the local jar file for a particular artifact 
     // IMPL: pass the jar as the agent 
    ), 
    lion <<= (
     runner, 
     fullClasspath in Runtime, 
     mainClass in Runtime, 
     streams in Runtime 
    ) map runLion 
) 

    // TODO: update to a task that can take parameters (e.g. number of repeats, profiling settings) 
    def runLion(runner: ScalaRun, cp: Classpath, main: Option[String], streams: TaskStreams): Unit = { 
    assert(runner.isInstanceOf[ForkRun], "didn't get a forked runner... SBT is b0rk3d") 
    println("RUNNING with " + runner.getClass) 

    // TODO: ask user if main is None, like 'run' does 
    val m = main.getOrElse("Scratch") 

    // TODO: get the user's arguments 
    val args = Nil 

    runner.run(m, data(cp), args, streams.log) 

    // IMPL: post-process and produce the report 

    println("FINISHED") 
    } 

} 

उत्तर

1

प्लगइन लेखकों को एक अनजान हिप्पोक्रेटिक ओथ का पालन करने की आवश्यकता है, जो "पहले, कोई नुकसान नहीं है।" आपका कार्यान्वयन वर्तमान में प्रत्येक उपप्रोजेक्ट में स्वयं को मजबूर करता है और डिफ़ॉल्ट व्यवहार के fork और javaOptions को म्यूट करता है, जो मुझे लगता है कि खतरनाक है। मुझे लगता है कि आपको run पैरामीटर को अपने कार्य के लिए डुप्लिकेट करने की आवश्यकता है ताकि डिफ़ॉल्ट सेटिंग्स बेकार हो जाएं।

// TODO: update to a task that can take parameters (e.g. number of repeats, profiling settings) 

एक उदाहरण के लिए Plugins Best Practices और sbt-appengine की तरह मौजूदा प्लगइन्स देखें।

एसबीटी-एपेंगेन devServer में एक इनपुट कार्य है जिसे आप पैरामीटर का एक समूह सेट कर सकते हैं।

gae.devServer  := { 
    val args = startArgsParser.parsed 
    val x = (products in Compile).value 
    AppEngine.restartDevServer(streams.value, (gae.reLogTag in gae.devServer).value, 
    thisProjectRef.value, (gae.reForkOptions in gae.devServer).value, 
    (mainClass in gae.devServer).value, (fullClasspath in gae.devServer).value, 
    (gae.reStartArgs in gae.devServer).value, args, 
    packageWar.value, 
    (gae.onStartHooks in gae.devServer).value, (gae.onStopHooks in gae.devServer).value) 
} 

जैसा कि आप देख कोड के पेट वास्तव में, AppEngine वस्तु के तहत एक विधि में कार्यान्वित किया जाता है ताकि किसी और संभावित रूप से अपना सामान का पुन: उपयोग कर सकते हैं। विधि में कई पैरामीटर (इस मामले में restartDevServer) gae.devServer कार्य (mainClass in gae.devServer) जैसे कार्य किए गए हैं।

बिल्डिंग उपयोगकर्ताओं द्वारा स्थापित प्लगइन का इरादा आप कैसे करते हैं? क्या वे इसे एक बार वैश्विक प्लगइन के रूप में सक्षम करने जा रहे हैं और हर जगह एक ही सेटिंग का उपयोग कर रहे हैं, या वे project/lion.sbt में प्रत्येक बिल्ड के लिए इसे सक्षम करने जा रहे हैं?Plugins Best Practices की सिफारिश baseLionSettings और lionSettings प्रदान करने के लिए है ताकि बिल्ड उपयोगकर्ता चुन सकें और चुन सकें कि कौन से सबप्रोजेक्ट में lion कार्य सक्षम होगा।

वास्तविक चलने के अनुसार, आप sbt-revolver से कोड का पुन: उपयोग करने पर एक नजर डालना चाहेंगे जो मैंने एसबीटी-एपेंगिन में किया था।

+0

यह बहुत उपयोगी है, धन्यवाद! मैं उपयोगकर्ताओं को प्रति-मॉड्यूल आधार पर इसे सेट करने की अनुमति देना चाहता हूं, और उपयोगकर्ता के कांटा/javaOptions को छूने के लिए छोड़ना चाहता हूं। मुझे डर है कि मैं अभी भी यह जानने के करीब नहीं हूं कि यह कैसे करें, अपने स्रोत को पढ़ने के बाद भी। मैं मूल रूप से उदा। शेर में कांटा: = सच', लेकिन इसे अनदेखा किया जा रहा था। – fommil

+0

हालांकि, मैं आपके दृष्टिकोण को चुरा लेगा और सीधे 'फोर्क.जावा' का उपयोग करूंगा ... इसका मतलब है कि मैं कभी भी सेटिंग को बदल नहीं सकता हूं। – fommil

1

देखें "कैसे मैं एक कस्टम रन कार्य बना सकते हैं के अलावा, रन? "http://www.scala-sbt.org/0.13.0/docs/faq.html पर। अपने कस्टम कार्य में, आप एक नया JVM लॉन्च करने के लिए fork को सत्य पर सेट करना चाहेंगे।

+0

वाह, इसके लिए एक FAQ है। अब मुझे गूंगा लगता है :-) – fommil

+0

यह केवल हिमशैल की नोक थी ... वास्तव में 'fullRunTask' को कॉल करना मुश्किल है। यह एक 'सेटिंग' है और मुझे नहीं पता कि वास्तव में इसे कैसे कॉल करें ... – fommil

+0

माफ़ी, अनौपचारिक उत्तर ताकि मैं अधिक जानकारी के साथ अपडेट कर सकूं – fommil

संबंधित मुद्दे