क्या कोई एसबीटी का उपयोग करने का सही तरीका बता सकता है?


100

मैं इस पर कोठरी बंद कर रहा हूँ! मुझे एसबीटी समझ में नहीं आता है। वहां, मैंने कहा, अब कृपया मेरी मदद करें।

सभी सड़कों रोम करने के लिए नेतृत्व, और कहा कि एसबीटी लिए एक ही है: आरंभ करने के लिए साथ SBTनहीं है SBT, SBT Launcher, SBT-extras, आदि, और फिर वहाँ शामिल हैं और खजाने पर फैसला करने के लिए विभिन्न तरीके हैं। क्या कोई 'सर्वश्रेष्ठ' तरीका है?

मैं पूछ रहा हूं क्योंकि कभी-कभी मैं थोड़ा खो जाता हूं। एसबीटी प्रलेखन बहुत ही गहन और पूरा हो गया है, लेकिन मुझे लगता है अपने आप को जब उपयोग करने के लिए नहीं जानने build.sbtया project/build.propertiesया project/Build.scalaया project/plugins.sbt

फिर यह मजेदार हो जाता है, वहाँ है Scala-IDEऔर SBT- उन्हें एक साथ उपयोग करने का सही तरीका क्या है? पहले क्या आता है, मुर्गी या अंडा?

सबसे महत्वपूर्ण बात यह है कि, आपको अपनी परियोजना में शामिल करने के लिए सही रिपॉजिटरी और संस्करण कैसे मिलते हैं? क्या मैं सिर्फ एक लबादा खींचता हूं और अपने रास्ते को आगे बढ़ाना शुरू करता हूं? मुझे अक्सर ऐसी परियोजनाएं मिलती हैं जिनमें सब कुछ और रसोई सिंक शामिल हैं, और फिर मुझे एहसास होता है - मैं अकेला नहीं हूं जो थोड़ा खो जाता है।

एक साधारण उदाहरण के रूप में, अभी, मैं एक नया प्रोजेक्ट शुरू कर रहा हूँ। मैं की नवीनतम सुविधाओं का उपयोग करना चाहते SLICKहैं और Scalaऔर यह शायद एसबीटी के नवीनतम संस्करण की आवश्यकता होगी। शुरू करने के लिए समझदार बिंदु क्या है, और क्यों? मुझे किस फ़ाइल में इसे परिभाषित करना चाहिए और यह कैसे दिखना चाहिए? मुझे पता है कि मुझे यह काम मिल सकता है, लेकिन मैं वास्तव में एक विशेषज्ञ की राय पसंद करूंगा जहां सब कुछ जाना चाहिए (यह वहां क्यों जाना चाहिए) एक बोनस होगा।

मैं अब SBTएक साल से अधिक समय से छोटी परियोजनाओं का उपयोग कर रहा हूं । मैंने उपयोग किया SBTऔर फिर SBT Extras(जैसा कि यह कुछ सिरदर्द जादुई रूप से गायब हो गया), लेकिन मुझे यकीन नहीं है कि मुझे एक या दूसरे का उपयोग क्यों करना चाहिए। मैं बस यह समझने के लिए थोड़ा निराश हो रहा हूं कि चीजें एक साथ कैसे फिट होती हैं ( SBTऔर रिपॉजिटरी), और यह सोचें कि यह अगले आदमी को इस तरह से बहुत मुश्किल से बचाएगा अगर इसे मानवीय शब्दों में समझाया जा सके।


2
"स्केल-आईडीई और एसबीटी" के साथ वास्तव में आपका क्या मतलब है? आप sbt के साथ अपनी परियोजना को परिभाषित करते हैं और sbt एक ide (ग्रहण ओडर इंटेलीज) परियोजना उत्पन्न कर सकते हैं। तो SBT पहले आता है ...
Jan

2
@ मैंने उल्लेख किया है कि क्योंकि स्काला-आईडीई बिल्ड मैनेजर के रूप में एसबीटी का उपयोग करता है। असेंबली.com/spaces/scala-ide/wiki/SBT-based_build_manager देखें और उनके द्वारा बताई गई पोस्ट में नीचे "आपके एसबीटी प्रोजेक्ट फ़ाइल को परिभाषित करने की आवश्यकता नहीं है।" जो मुझे भ्रामक लगा।
जैक

ठीक है। जैसा कि मैंने आमतौर पर स्केला को संपादित करने के लिए इंटेलीज (या उदात्त) का उपयोग किया है जो मुझे नहीं पता था। मुझे लगता है कि बिल्डर अपने sbt विन्यास उत्पन्न करता है?
जन

2
@JacobusR तथ्य यह है कि आपकी परियोजना के स्रोतों को बनाने के लिए स्काला आईडीई एसबीटी का उपयोग करता है एक कार्यान्वयन विवरण है, और उपयोगकर्ताओं को इस बारे में चिंता करने की आवश्यकता नहीं है। वास्तव में 0 निहितार्थ हैं। ग्रहण के बाहर उपयोगकर्ता SBT, Maven, Ant, ..., के साथ एक परियोजना का निर्माण कर सकते हैं और इससे Scala IDE को कोई फर्क नहीं पड़ेगा। एक और बात, भले ही आपके पास एक एसबीटी परियोजना हो, स्काला आईडीई परवाह नहीं करता है, अर्थात, यह आपके Build.scalaलिए क्लासपैथ सेट करने के लिए नहीं दिखता है , और इसीलिए आपको एक्लिप्स .classath उत्पन्न करने के लिए वास्तव में sbteclipse की आवश्यकता होती है। उम्मीद है की यह मदद करेगा।
Mirco Dotta

1
@ जीन स्काला आईडीई ने भ्रम में जोड़ा, और हाँ, प्रलेखन जो एक अच्छा स्काला विकास वातावरण स्थापित करने पर एक बड़ी तस्वीर देता है और उपयुक्त प्रोग्रामिंग वर्कफ़्लोज़ के कुछ ठोस मार्गदर्शन बहुत काम आएगा।
जैक

जवाबों:


29

सबसे महत्वपूर्ण बात यह है कि, आपको अपनी परियोजना में शामिल करने के लिए सही रिपॉजिटरी और संस्करण कैसे मिलते हैं? क्या मैं सिर्फ एक लबादा खींचता हूं और अपने रास्ते को आगे बढ़ाना शुरू करता हूं? मुझे अक्सर ऐसी परियोजनाएं मिलती हैं जिनमें सब कुछ और रसोई सिंक शामिल हैं

स्काला-आधारित निर्भरता के लिए, मैं लेखकों की सिफारिश के साथ जाऊंगा। उदाहरण के लिए: http://code.google.com/p/scalaz/#SBT उपयोग करने के लिए इंगित करता है:

libraryDependencies += "org.scalaz" %% "scalaz-core" % "6.0.4"

या https://github.com/typesafehub/sbteclipse/ को जोड़ने के निर्देश हैं:

addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.1.0-RC1")

जावा-आधारित निर्भरता के लिए, मैं http://mvnrepository.com/ का उपयोग करता हूं यह देखने के लिए कि वहां क्या है, फिर SBT टैब पर क्लिक करें। उदाहरण के लिए http://mvnrepository.com/artifact/net.sf.opencsv/opencsv/2.3.3 संपर्क करने के लिए:

libraryDependencies += "net.sf.opencsv" % "opencsv" % "2.3"

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

एक साधारण उदाहरण के रूप में, अभी, मैं एक नया प्रोजेक्ट शुरू कर रहा हूँ। मैं SLICK और स्काला की नवीनतम विशेषताओं का उपयोग करना चाहता हूं और इसके लिए शायद SBT के नवीनतम संस्करण की आवश्यकता होगी। शुरू करने के लिए समझदार बिंदु क्या है, और क्यों?

मुझे लगता है कि धीरे-धीरे sbt के लिए प्रतिरक्षा बिंदु का निर्माण करना है

सुनिश्चित करें कि आप समझते हैं:

  1. स्कोप्स प्रारूप {<build-uri>}<project-id>/config:key(for task-key)
  2. सेटिंग्स की 3 जायके ( SettingKey, TaskKey, InputKey) - में खंड "टास्क कुंजी" कहा जाता है पढ़ http://www.scala-sbt.org/release/docs/Getting-Started/Basic-Def

उन 4 पृष्ठों को हर समय खुला रखें ताकि आप कूद सकें और विभिन्न परिभाषाओं और उदाहरणों को देख सकें:

  1. http://www.scala-sbt.org/release/docs/Getting-Started/Basic-Def
  2. http://www.scala-sbt.org/release/docs/Detailed-Topics/index
  3. http://harrah.github.com/xsbt/latest/sxr/Keys.scala.html
  4. http://harrah.github.com/xsbt/latest/sxr/Defaults.scala.html

का अधिकतम उपयोग करना showऔर inspect और टैब पूरा होने सेटिंग्स, उनकी निर्भरता, परिभाषाएँ और संबंधित सेटिंग की वास्तविक मूल्यों से परिचित कराने के। मुझे विश्वास नहीं है कि जिन रिश्तों का आप उपयोग inspectकर पाएंगे, वे कहीं भी प्रलेखित हैं। अगर कोई बेहतर तरीका है तो मैं इसके बारे में जानना चाहता हूं।


25

जिस तरह से मैं sbt का उपयोग करता हूं वह है:

  1. Sbt-extras का उपयोग करें - बस शेल स्क्रिप्ट प्राप्त करें और इसे आप प्रोजेक्ट के मूल में जोड़ें
  2. Sbt सेट करने के लिए फ़ाइल के projectसाथ एक फ़ोल्डर बनाएँ MyProject.scala। मैं इस build.sbtदृष्टिकोण पर बहुत पसंद करता हूं - यह स्केला है और अधिक लचीला है
  3. एक project/plugins.sbtफ़ाइल बनाएं और अपने आईडीई के लिए उपयुक्त प्लगइन जोड़ें। या तो sbt-eclipse, sbt-idea या ensime-sbt-cmd ताकि आप ग्रहण, intellij या ensime के लिए प्रोजेक्ट फाइल्स जेनरेट कर सकें।
  4. अपने प्रोजेक्ट के रूट में sbt लॉन्च करें और अपने IDE के लिए प्रोजेक्ट फाइल्स जेनरेट करें
  5. फायदा

मैं IDE प्रोजेक्ट फ़ाइलों में जाँच करने से परेशान नहीं हूँ क्योंकि वे sbt द्वारा जनरेट किए जाते हैं, लेकिन ऐसे कारण हो सकते हैं जो आप करना चाहते हैं।

आप यहां इस तरह से स्थापित एक उदाहरण देख सकते हैं ।


अच्छे उत्तर के लिए धन्यवाद। मैंने अन्य उत्तर को स्वीकार कर लिया, क्योंकि यह अधिक जमीन को कवर करता है, और आपके वोट के कारण ने इसे वास्तव में अच्छा भी माना है। मैं दोनों को स्वीकार कर लेता अगर मैं कर सकता था।
जैक

0

टाइपसेफ़ एक्टीवेटर का उपयोग करें, sbt को कॉल करने का एक फैंसी तरीका, जो प्रोजेक्ट टेम्पलेट्स और बीजों के साथ आता है: https://typesafe.com/activator

Activator new

Fetching the latest list of templates...

Browse the list of templates: http://typesafe.com/activator/templates
Choose from these featured templates or enter a template name:
 1) minimal-java
 2) minimal-scala
 3) play-java
 4) play-scala
(hit tab to see a list of all templates)

5
मैं इस विचार के लिए आंशिक हूं कि जब संदेह हो, तो मिश्रण में अधिक जादू जोड़ने से आपकी समस्याओं को हल करने की संभावना नहीं है।
घन

0

स्थापना

brew install sbt या इसी तरह के sbt को स्थापित करता है जो तकनीकी रूप से बोलते हैं

जब आप sbtटर्मिनल से निष्पादित करते हैं तो यह वास्तव में sbt लॉन्चर बैश स्क्रिप्ट चलाता है। व्यक्तिगत रूप से, मुझे इस त्रिमूर्ति के बारे में चिंता करने की ज़रूरत नहीं थी, और बस sbt का उपयोग करें जैसे कि यह एक ही बात थी।

विन्यास

किसी विशेष प्रोजेक्ट के लिए sbt को कॉन्फ़िगर करने के लिए प्रोजेक्ट .sbtoptsके रूट पर फाइल सेव करें । Sbt सिस्टम-वाइड संशोधित कॉन्फ़िगर करने के लिए /usr/local/etc/sbtopts। निष्पादन sbt -helpआपको सटीक स्थान बताना चाहिए। उदाहरण के लिए, दे एसबीटी अधिक स्मृति के रूप में एक बंद निष्पादित sbt -mem 4096, या बचाने -mem 4096में .sbtoptsया sbtoptsके लिए स्मृति वृद्धि स्थायी रूप से प्रभावी करने के लिए।

 परियोजना की संरचना

sbt new scala/scala-seed.g8 एक न्यूनतम हैलो वर्ल्ड sbt प्रोजेक्ट संरचना बनाता है

.
├── README.md  // most important part of any software project
├── build.sbt  // build definition of the project
├── project    // build definition of the build (sbt is recursive - explained below)
├── src        // test and main source code
└── target     // compiled classes, deployment package

बार-बार आज्ञा देना

test                                                // run all test
testOnly                                            // run only failed tests
testOnly -- -z "The Hello object should say hello"  // run one specific test
run                                                 // run default main
runMain example.Hello                               // run specific main
clean                                               // delete target/
package                                             // package skinny jar
assembly                                            // package fat jar
publishLocal                                        // library to local cache
release                                             // library to remote repository
reload                                              // after each change to build definition

गोले के असंख्य

scala              // Scala REPL that executes Scala language (nothing to do with sbt)
sbt                // sbt REPL that executes special sbt shell language (not Scala REPL)
sbt console        // Scala REPL with dependencies loaded as per build.sbt
sbt consoleProject // Scala REPL with project definition and sbt loaded for exploration with plain Scala langauage

बिल्ड डेफिनिशन एक उचित स्काला प्रोजेक्ट है

यह प्रमुख मुहावरेदार sbt अवधारणाओं में से एक है। मैं एक प्रश्न के साथ समझाने की कोशिश करूंगा। मान लीजिए कि आप एक sbt कार्य को परिभाषित करना चाहते हैं, जो स्केलाज-http के साथ एक HTTP अनुरोध को निष्पादित करेगा। सहज रूप से हम अंदर की कोशिश कर सकते हैंbuild.sbt

libraryDependencies +=  "org.scalaj" %% "scalaj-http" % "2.4.2"

val fooTask = taskKey[Unit]("Fetch meaning of life")
fooTask := {
  import scalaj.http._ // error: cannot resolve symbol
  val response = Http("http://example.com").asString
  ...
}

हालाँकि यह गुम होने में त्रुटि कहेगा import scalaj.http._। यह कैसे संभव है जब हम, ठीक ऊपर, को जोड़ा scalaj-httpजाए libraryDependencies? इसके अलावा, यह काम क्यों करता है, इसके बजाय, हम निर्भरता को जोड़ते हैं project/build.sbt?

// project/build.sbt
libraryDependencies +=  "org.scalaj" %% "scalaj-http" % "2.4.2"

इसका उत्तर यह है कि fooTaskवास्तव में आपके मुख्य प्रोजेक्ट से एक अलग स्काला प्रोजेक्ट का हिस्सा है । यह अलग स्काला प्रोजेक्ट project/निर्देशिका के तहत पाया जा सकता है जिसकी अपनी target/निर्देशिका है जहां इसके संकलित वर्ग रहते हैं। वास्तव में, project/target/config-classesएक ऐसा वर्ग होना चाहिए जो कुछ करने के लिए विघटित हो

object $9c2192aea3f1db3c251d extends scala.AnyRef {
  lazy val fooTask : sbt.TaskKey[scala.Unit] = { /* compiled code */ }
  lazy val root : sbt.Project = { /* compiled code */ }
}

हम देखते हैं कि fooTaskनाम मात्र की नियमित स्कैला वस्तु का एक सदस्य है $9c2192aea3f1db3c251d। स्पष्ट रूप से scalaj-httpपरिभाषित परियोजना की निर्भरता होनी चाहिए $9c2192aea3f1db3c251dन कि उचित परियोजना की निर्भरता। इसलिए इसके project/build.sbtबजाय घोषित किए जाने की आवश्यकता है build.sbt, क्योंकि projectजहां बिल्ड स्कैला प्रोजेक्ट रहता है।

इस बिंदु को चलाने के लिए कि परिभाषा का निर्माण एक और स्काला परियोजना है, निष्पादित करें sbt consoleProject। यह स्काला आरईपीएल को क्लासपाथ पर बिल्ड डेफिनिशन प्रोजेक्ट के साथ लोड करेगा। आप की तर्ज पर एक आयात देखना चाहिए

import $9c2192aea3f1db3c251d

तो अब हम सीधे build.sbtDSL के बजाय Scala के साथ कॉल करके सीधे बिल्ड प्रोजेक्ट के साथ इंटरैक्ट कर सकते हैं । उदाहरण के लिए, निम्नलिखित निष्पादित करता हैfooTask

$9c2192aea3f1db3c251d.fooTask.eval

build.sbtअंडर प्रोजेक्ट एक स्‍पेसियल डीएसएल है जो निर्माण परिभाषा स्‍केल परियोजना के तहत परिभाषित करने में मदद करता है project/

और परिभाषा स्कैला परियोजना का निर्माण कर सकते हैं, अपनी स्वयं की बिल्ड परिभाषा स्कैला परियोजना के तहत project/project/और इतने पर हो सकते हैं। हम कहते हैं कि sbt पुनरावर्ती है

sbt डिफ़ॉल्ट रूप से समानांतर है

sbt कार्यों से DAG बनाता है। यह इसे कार्यों के बीच निर्भरता का विश्लेषण करने और उन्हें समानांतर में निष्पादित करने और यहां तक ​​कि कटौती करने की अनुमति देता है। build.sbtडीएसएल को इसे ध्यान में रखकर बनाया गया है, जो शुरू में आश्चर्यजनक शब्दार्थ को जन्म दे सकता है। आपको क्या लगता है कि निष्पादन का क्रम निम्नलिखित स्निपेट में है?

def a = Def.task { println("a") }
def b = Def.task { println("b") }
lazy val c = taskKey[Unit]("sbt is parallel by-default")
c := {
  println("hello")
  a.value
  b.value
}

सहज रूप से कोई सोच सकता है कि यहां प्रवाह पहले प्रिंट करना, helloफिर निष्पादित करना aऔर फिर bकार्य करना है। हालांकि यह वास्तव में अमल का मतलब है aऔर bमें समानांतर , और इससे पहले कि println("hello") इतना

a
b
hello

या के आदेश क्योंकि aऔर bइसकी गारंटी नहीं है

b
a
hello

शायद विरोधाभासी रूप से, sbt में धारावाहिक की तुलना में समानांतर करना आसान है। यदि आपको सीरियल ऑर्डर करने की आवश्यकता है, तो आपको विशेष चीज़ों का उपयोग करना होगा Def.sequentialया जैसे -समझ केDef.taskDyn लिए अनुकरण करना होगा ।

def a = Def.task { println("a") }
def b = Def.task { println("b") }
lazy val c = taskKey[Unit]("")
c := Def.sequential(
  Def.task(println("hello")),
  a,
  b
).value

के समान है

for {
  h <- Future(println("hello"))
  a <- Future(println("a"))
  b <- Future(println("b"))
} yield ()

जहां हम देखते हैं कि घटकों के बीच कोई निर्भरता नहीं है, जबकि

def a = Def.task { println("a"); 1 }
def b(v: Int) = Def.task { println("b"); v + 40 }
def sum(x: Int, y: Int) = Def.task[Int] { println("sum"); x + y }
lazy val c = taskKey[Int]("")
c := (Def.taskDyn {
  val x = a.value
  val y = Def.task(b(x).value)
  Def.taskDyn(sum(x, y.value))
}).value

के समान है

def a = Future { println("a"); 1 }
def b(v: Int) = Future { println("b"); v + 40 }
def sum(x: Int, y: Int) = Future { x + y }

for {
  x <- a
  y <- b(x)
  c <- sum(x, y)
} yield { c }

जहां हम देखते हैं sumपर निर्भर करता है और के लिए इंतजार करना पड़ता है aऔर b

दूसरे शब्दों में

  • के लिए अनुप्रयोगी अर्थ विज्ञान, उपयोग.value
  • के लिए monadic शब्दार्थ का उपयोग करें sequentialयाtaskDyn

के बजाय निर्भरता के निर्माण की प्रकृति के परिणामस्वरूप एक और भ्रामक भ्रामक स्निपेट पर विचार करेंvalue

`value` can only be used within a task or setting macro, such as :=, +=, ++=, Def.task, or Def.setting.
val x = version.value
                ^

हमें लिखना है

val x = settingKey[String]("")
x := version.value

ध्यान दें कि वाक्यविन्यास .valueDAG में रिश्तों के बारे में है और इसका मतलब नहीं है

"अभी मुझे मूल्य दो"

इसके बजाय इसका मतलब कुछ ऐसा है

"मेरा कॉलर पहले मुझ पर निर्भर करता है, और एक बार मुझे पता है कि पूरा डीएजी एक साथ कैसे फिट होता है, मैं अनुरोध किए गए मूल्य के साथ अपने कॉलर को प्रदान करने में सक्षम होगा"

तो अब यह थोड़ा स्पष्ट हो सकता है कि xअभी तक एक मूल्य क्यों नहीं सौंपा जा सकता है; संबंध निर्माण चरण में अभी तक कोई मूल्य उपलब्ध नहीं है।

हम स्पष्ट रूप से स्काला उचित और DSL भाषा के बीच शब्दार्थ में अंतर देख सकते हैं build.sbt। यहाँ अंगूठे के कुछ नियम हैं जो मेरे लिए काम करते हैं

  • DAG प्रकार की अभिव्यक्तियों से बना है Setting[T]
  • ज्यादातर मामलों में हम .valueसिंटैक्स का उपयोग करते हैं और एसबीटी के बीच संबंध स्थापित करने का ध्यान रखेंगेSetting[T]
  • कभी-कभी हमें मैन्युअल रूप से डीएजी के एक हिस्से को मोड़ना पड़ता है और इसके लिए हम उपयोग करते हैं Def.sequentialयाDef.taskDyn
  • एक बार जब इन ऑर्डरिंग / रिलेशनशिप सिंटैमिक विषमताओं का ध्यान रखा जाता है, तो हम बाकी कार्यों के व्यापार तर्क के निर्माण के लिए सामान्य स्कैटलिक्स पर भरोसा कर सकते हैं।

 कमांड बनाम टास्क

कमांड डीएजी से बाहर एक आलसी रास्ता है। आदेशों का उपयोग करके अपनी इच्छानुसार बिल्ड स्थिति और क्रमबद्ध कार्यों को म्यूट करना आसान है। लागत हम ढीले समालोचना और डीएजी द्वारा प्रदान किए जाने वाले कार्यों का समर्पण है, जिस तरह से कार्यों को प्राथमिकता दी जानी चाहिए। आप आदेशों को एक सत्र की स्थायी रिकॉर्डिंग के रूप में सोच सकते हैं जिसे कोई अंदर कर सकता है sbt shell। उदाहरण के लिए, दिया गया

vval x = settingKey[Int]("")
x := 13
lazy val f = taskKey[Int]("")
f := 1 + x.value

निम्नलिखित सत्र के आउटपुट पर विचार करें

sbt:root> x
[info] 13
sbt:root> show f
[info] 14
sbt:root> set x := 41
[info] Defining x
[info] The new value will be used by f
[info] Reapplying settings...
sbt:root> show f
[info] 42

विशेष रूप से नहीं कि हम निर्माण स्थिति को किस तरह से बदलते हैं set x := 41। उदाहरण के लिए, कमांड हमें उपरोक्त सत्र की एक स्थायी रिकॉर्डिंग बनाने में सक्षम बनाता है

commands += Command.command("cmd") { state =>
  "x" :: "show f" :: "set x := 41" :: "show f" :: state
}

हम कमांड का उपयोग करके सुरक्षित-प्रकार भी बना सकते हैं Project.extractऔरrunTask

commands += Command.command("cmd") { state =>
  val log = state.log
  import Project._
  log.info(x.value.toString)
  val (_, resultBefore) = extract(state).runTask(f, state)
  log.info(resultBefore.toString)
  val mutatedState = extract(state).appendWithSession(Seq(x := 41), state)
  val (_, resultAfter) = extract(mutatedState).runTask(f, mutatedState)
  log.info(resultAfter.toString)
  mutatedState
}

कार्यक्षेत्र

जब हम निम्नलिखित प्रकार के प्रश्नों का उत्तर देने का प्रयास करते हैं, तो स्कोप्स चलन में आते हैं

  • एक बार कार्य को कैसे परिभाषित किया जाए और इसे बहु-परियोजना निर्माण में सभी उप-परियोजनाओं के लिए उपलब्ध कराया जाए?
  • मुख्य वर्गपथ पर परीक्षण निर्भरता होने से कैसे बचें?

sbt में एक बहु-अक्ष स्कूपिंग स्पेस है जिसे स्लैश सिंटैक्स का उपयोग करके नेविगेट किया जा सकता है , उदाहरण के लिए,

show  root   /  Compile         /  compile   /   scalacOptions
        |        |                  |             |
     project    configuration      task          key

निजी तौर पर, मैं शायद ही कभी खुद को गुंजाइश के बारे में चिंता करने के लिए पाता हूं। कभी-कभी मैं सिर्फ परीक्षण स्रोतों को संकलित करना चाहता हूं

Test/compile

या शायद किसी विशेष उपप्रोजेक्ट से किसी विशेष कार्य को निष्पादित करने के लिए पहले बिना उस परियोजना को नेविगेट करने के लिए project subprojB

subprojB/Test/compile

मुझे लगता है कि अंगूठे के निम्नलिखित नियम जटिलताओं से बचने में मदद करते हैं

  • कई build.sbtफाइलें नहीं हैं, लेकिन रूट प्रोजेक्ट के तहत केवल एक ही मास्टर है जो अन्य सभी उप-परियोजनाओं को नियंत्रित करता है
  • ऑटो प्लग के माध्यम से कार्यों को साझा करें
  • सादे सेटिंग में सामान्य सेटिंग्स को फैक्टर करें valऔर स्पष्ट रूप से प्रत्येक उप-परियोजना में जोड़ें

मल्टी-प्रोजेक्ट बिल्ड

प्रत्येक subproject के लिए कई build.sbt फ़ाइलों की आइंस्टेड

.
├── README.md
├── build.sbt                  // OK
├── multi1
│   ├── build.sbt              // NOK
│   ├── src
│   └── target
├── multi2
│   ├── build.sbt              // NOK
│   ├── src
│   └── target
├── project                    // this is the meta-project
│   ├── FooPlugin.scala        // custom auto plugin
│   ├── build.properties       // version of sbt and hence Scala for meta-project
│   ├── build.sbt              // OK - this is actually for meta-project 
│   ├── plugins.sbt            // OK
│   ├── project
│   └── target
└── target

build.sbtउन सभी पर शासन करने के लिए एक ही गुरु रखें

.
├── README.md
├── build.sbt                  // single build.sbt to rule theme all
├── common
│   ├── src
│   └── target
├── multi1
│   ├── src
│   └── target
├── multi2
│   ├── src
│   └── target
├── project
│   ├── FooPlugin.scala
│   ├── build.properties
│   ├── build.sbt
│   ├── plugins.sbt
│   ├── project
│   └── target
└── target

मल्टी-प्रोजेक्ट बिल्ड्स में सामान्य सेटिंग्स फैक्टरिंग का एक सामान्य अभ्यास है

एक घाटी में सामान्य सेटिंग्स के अनुक्रम को परिभाषित करें और उन्हें प्रत्येक प्रोजेक्ट में जोड़ें। इस तरह से सीखने के लिए कम अवधारणाएँ।

उदाहरण के लिए

lazy val commonSettings = Seq(
  scalacOptions := Seq(
    "-Xfatal-warnings",
    ...
  ),
  publishArtifact := true,
  ...
)

lazy val root = project
  .in(file("."))
  .settings(settings)
  .aggregate(
    multi1,
    multi2
  )
lazy val multi1 = (project in file("multi1")).settings(commonSettings)
lazy val multi2 = (project in file("multi2")).settings(commonSettings)

परियोजनाओं नेविगेशन

projects         // list all projects
project multi1   // change to particular project

प्लगइन्स

याद रखें बिल्ड डेफिनेशन एक उचित स्कैला प्रोजेक्ट है, जिसके अंतर्गत निवास करता है project/। यह वह जगह है जहां हम .scalaफ़ाइलों को बनाकर एक प्लगइन को परिभाषित करते हैं

.                          // directory of the (main) proper project
├── project
│   ├── FooPlugin.scala    // auto plugin
│   ├── build.properties   // version of sbt library and indirectly Scala used for the plugin
│   ├── build.sbt          // build definition of the plugin
│   ├── plugins.sbt        // these are plugins for the main (proper) project, not the meta project
│   ├── project            // the turtle supporting this turtle
│   └── target             // compiled binaries of the plugin

यहाँ एक कम है ऑटो प्लगइन के तहतproject/FooPlugin.scala

object FooPlugin extends AutoPlugin {
  object autoImport {
      val barTask = taskKey[Unit]("")
  }

  import autoImport._

  override def requires = plugins.JvmPlugin  // avoids having to call enablePlugin explicitly
  override def trigger = allRequirements

  override lazy val projectSettings = Seq(
    scalacOptions ++= Seq("-Xfatal-warnings"),
    barTask := { println("hello task") },
    commands += Command.command("cmd") { state =>
      """eval println("hello command")""" :: state
    }   
  )
}

ओवरराइड

override def requires = plugins.JvmPlugin

प्रभावी ढंग से स्पष्ट रूप से कॉल करने के लिए बिना सभी उप-परियोजनाओं के लिए प्लगइन सक्षम होना चाहिए enablePluginमें build.sbt

इंटेलीज और एसबीटी

कृपया निम्नलिखित सेटिंग सक्षम करें (जो कि डिफ़ॉल्ट रूप से सक्षम होनी चाहिए )

use sbt shell

के अंतर्गत

Preferences | Build, Execution, Deployment | sbt | sbt projects

मुख्य संदर्भ

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.