2013-06-16 5 views
6

मान लीजिए मैं इस तरह फाइलों के साथ, तीन उप-परियोजनाओं के साथ एक स्काला परियोजना है:पठन संसाधनों

foo/src/main/scala/Foo.scala 
foo/src/main/resources/foo.txt 

bar/src/main/scala/Bar.scala 
bar/src/main/resources/bar.txt 

baz/src/main/scala/Baz.scala 
baz/src/main/resources/baz.txt 

Foo.scala एक सरल मैक्रो कि किसी दिए गए पथ पर एक संसाधन पढ़ता शामिल हैं:

import scala.language.experimental.macros 
import scala.reflect.macros.Context 

object Foo { 
    def countLines(path: String): Option[Int] = macro countLines_impl 

    def countLines_impl(c: Context)(path: c.Expr[String]) = { 
    import c.universe._ 

    path.tree match { 
     case Literal(Constant(s: String)) => Option(
     this.getClass.getResourceAsStream(s) 
    ).fold(reify(None: Option[Int])) { stream => 
     val count = c.literal(io.Source.fromInputStream(stream).getLines.size) 
     reify(Some(count.splice)) 
     } 
     case _ => c.abort(c.enclosingPosition, "Need a literal path!") 
    } 
    } 
} 

संसाधन खोला जा सकता है, तो countLines लाइनों की संख्या देता है; अन्यथा यह खाली है।

object Bar extends App { 
    println(Foo.countLines("/foo.txt")) 
    println(Foo.countLines("/bar.txt")) 
    println(Foo.countLines("/baz.txt")) 
} 

और::

object Baz extends App { 
    println(Foo.countLines("/foo.txt")) 
    println(Foo.countLines("/bar.txt")) 
    println(Foo.countLines("/baz.txt")) 
} 

संसाधनों की सामग्री को वास्तव में इस सवाल के प्रयोजनों के लिए कोई फर्क नहीं पड़ता

अन्य दो स्काला स्रोत फ़ाइलों सिर्फ इस मैक्रो कहते हैं।

यह एक Maven परियोजना है, तो मैं आसानी से इसे कॉन्फ़िगर कर सकते हैं ताकि जड़ परियोजना तीन उप-परियोजनाओं एकत्रित और bazbar, जो foo पर निर्भर करता है पर निर्भर करता है। गोर विवरण के लिए this Gist देखें।

मैवेन के साथ सब कुछ अपेक्षित काम करता है। Barfoo और bar के लिए संसाधनों देख सकते हैं:

Some(1) 
Some(2) 
None 

और Baz उन सभी को देख सकते हैं:

Some(1) 
Some(2) 
Some(3) 

अब मैं एसबीटी के साथ एक ही बात की कोशिश:

import sbt._ 
import Keys._ 

object MyProject extends Build { 
    lazy val root: Project = Project(
    id = "root", base = file("."), 
    settings = commonSettings 
).aggregate(foo, bar, baz) 

    lazy val foo: Project = Project(
    id = "foo", base = file("foo"), 
    settings = commonSettings 
) 

    lazy val bar: Project = Project(
    id = "bar", base = file("bar"), 
    settings = commonSettings, 
    dependencies = Seq(foo) 
) 

    lazy val baz: Project = Project(
    id = "baz", base = file("baz"), 
    settings = commonSettings, 
    dependencies = Seq(bar) 
) 

    def commonSettings = Defaults.defaultSettings ++ Seq(
    scalaVersion := "2.10.2", 
    libraryDependencies <+= scalaVersion("org.scala-lang" % "scala-compiler" % _) 
) 
} 

लेकिन अब Bar केवल foo में संसाधन देख सकते हैं:

Some(1) 
None 
None 

और Baz केवल foo और bar देख सकते हैं:

Some(1) 
Some(2) 
None 

यहाँ क्या हो रहा है? यह एसबीटी बिल्ड फ़ाइल मुझे मेवेन कॉन्फ़िगरेशन का एक सुंदर शाब्दिक अनुवाद प्रतीत होता है। मुझे bar प्रोजेक्ट में कंसोल खोलने में कोई समस्या नहीं है और उदाहरण के लिए /bar.txt पढ़ना है, तो मैक्रो को कॉल करते समय इन परियोजनाओं को अपने संसाधन क्यों नहीं देख सकते हैं?

+0

@ 0__: 13, <+= और <++= नया मैक्रो आधारित सिंटेक्स के लिए अनावश्यक (और गैर-दस्तावेजी) धन्यवाद कर रहे हैं धन्यवाद, मैं उल्लेख किया जाना चाहिए था कि-हाँ, वे वहाँ हो (और गैर से उपलब्ध हैं कंसोल और परियोजना स्रोत में मैक्रो कोड दोनों)। –

+0

मैक्रो विशेषज्ञ नहीं, लेकिन यह एक वर्ग लोडर मुद्दा आईएमओ होना चाहिए। वास्तव में 'this.getClass.getResourceAsStream' निष्पादित क्या बिंदुओं पर है? शायद आपको क्लास लोडर संदर्भ के रूप में संदर्भ या कुछ और उपयोग करने की आवश्यकता है? कोई सुराग नहीं ... –

+0

@ 0__: मुझे लगता है कि यह ऐसा कुछ है, लेकिन मेरे किसी भी झुकाव ने समाधान नहीं मारा, और तथ्य यह है कि यह मेवेन मामले में अपेक्षित काम करता है, मुझे लगता है कि यह कुछ आसान होना चाहिए। –

उत्तर

5

एसबीटी वर्तमान परियोजना के संसाधनों को बिल्ड क्लास-पथ में नहीं जोड़ता है। शायद क्योंकि इसकी शायद ही कभी आवश्यकता है।

तुम बस पाइप एक (संसाधन) अन्य (classpath) में करने के लिए है:

def commonSettings = Defaults.defaultSettings ++ Seq(
    scalaVersion := "2.10.2", 
    libraryDependencies <+= scalaVersion("org.scala-lang" % "scala-compiler" % _), 
    // add resources of the current project into the build classpath 
    unmanagedClasspath in Compile <++= unmanagedResources in Compile 
) 

कि इस परियोजना की जरूरत ही होगा कि bar और baz के लिए।

अद्यतन: एसबीटी 0 के बाद से।

libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value 
unmanagedClasspath in Compile ++= (unmanagedResources in Compile).value 
संबंधित मुद्दे