SBT
Lo strumento di generazione standard per scala è sbt (Scala Build Tool). All'interno di sbt ci sono tre modi per fare le dipendenze :
- Dichiarazioni nel tuo progetto
- File Maven POM
- Configurazione Ivy
Per utilizzare Maven, è necessario specificare i resolver per la posizione del repository:
resolvers += "Local Maven Repository" at "file://"+Path.userHome.absolutePath+"/.m2/repository"
resolvers += "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots"
Potresti anche sovrascriverlo creando un file di configurazione locale: ~/.sbt/repositories
[repositories]
local
my-maven-repo: https://example.org/repo
my-ivy-repo: https://example.org/ivy-repo/, [organization]/[module]/[revision]/[type]s/[artifact](-[classifier]).[ext]
Se dovessi veramente , potresti anche specificare un URL e impostare in qualche modo l'hosting locale su un server che controlli. Si noti che questa non è una soluzione ideale
libraryDependencies += "slinky" % "slinky" % "2.1" from "https://slinky2.googlecode.com/svn/artifacts/2.1/slinky.jar"
Tuttavia, questa è solo metà della battaglia. Certo, puoi estrarre i vasi da qualche posto, ma devi anche metterli lì . Se non stai mettendo i moduli là fuori per qualcun altro da scaricare e usare, dovranno ricompilarli.
Potresti configurare un server Sonotype nexus e quindi pubblicare su di esso:
publishTo := Some("Sonatype Snapshots Nexus" at "https://oss.sonatype.org/content/repositories/snapshots")
Oppure potresti avere un repository comunemente montato (non penso che questa sarebbe una soluzione migliore ):
publishTo := Some(Resolver.file("file", new File( "path/to/my/maven-repo/releases" )) )
Puoi configurarlo per pubblicare alcune cose qui e alcune cose lì:
publishTo := {
val nexus = "https://oss.sonatype.org/"
if (isSnapshot.value)
Some("snapshots" at nexus + "content/repositories/snapshots")
else
Some("releases" at nexus + "service/local/staging/deploy/maven2")
}
Ma la cosa è che devi pubblicarlo per permettere ad altre persone di scaricarlo.
Maven
Maven è (o dovrebbe essere) ben noto agli sviluppatori Java. Non è qualcosa che è comunemente usato con scala. Ma è possibile per far sì che scala e maven lavorino insieme . Insieme a src/main/java
avrai src/main/scala
. Avrai anche un plugin nel tuo .pom:
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>3.1.3</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
A questo punto, stai usando Maven e stai distribuendo le risorse Maven sul server Sonotype nexus.
cose generiche
Tutto questo, anche se entrambi gli approcci dipendono da qualcos'altro. È necessario modulare il progetto in modo che i piccoli vasi possano essere compilati, compilati e distribuiti sul server degli artefatti.
Se il tuo progetto non è configurato in questo modo, dovrai cambiarlo in modo che le piccole parti indipendenti siano distinte.
Potresti scoprire che la cosa più semplice da fare (quindi non devi ricordarti di fare una pubblicazione o una distribuzione) è configurare un server di integrazione continua che preleva le modifiche dal tuo server di controllo delle versioni, costruendole e distribuire automaticamente build di successo sul server.
Ciò implica anche un certo grado di disciplina con il controllo delle versioni degli artefatti. Potresti voler dare un'occhiata a versioning semantico . L'identificativo per le informazioni di rilascio in modo che non si calpestino l'un l'altro e non distribuisca istantanee in competizione o sovrascriva il numero di versione di qualcun altro. Ti troverai con versioni come 1.0.3-pauld.0.1
in modo che siano namespace.
E così, specificherete con sbt o maven che questo progetto usa alcuni artefatti in alcune versioni. Il numero della versione preliminare probabilmente contiene il nome del ramo o dell'autore. Sarà distribuito su un server in cui è quindi possibile estrarlo. Quando qualcun altro passa a quel ramo, quei moduli saranno disponibili per lo strumento di compilazione da scaricare e utilizzare senza doverli ricompilare.
lingue e strumenti
Una cosa fondamentale da ricordare qui è che non si distribuiscono file .class. Invece, stai dispiegando .jars. Tutto è costruito attorno a una classe. Compilata localmente o alle librerie scaricate. Mentre si potrebbe pensare di farlo con altri linguaggi, con Java e Scala gli IDE si infastidirebbero molto se i file .class ei file .java o .scala diventassero fuori sincrono. Se stai utilizzando vim
e javac
o scalac
, potresti trovare altri strumenti utili per le risorse compilate singolarmente.
Tuttavia, sottolineerò che non è così banale come prima apparirebbe. Troverai cose come Outer$Inner.class
e Outer$1$3.class
nelle istanze in cui hai classi interne (il secondo esempio è il file compilato per la terza classe interna anonima nella prima classe interna anonima nella classe Esterno). Con le classi interne anonime, questa è dipendente dalla posizione nel file: aggiungi del codice e Outer$1.class
diventa Outer$2.class
. Ciò rende la cache per fonte piuttosto problematica e potrebbe non funzionare affatto con molte lingue derivate dalla JVM. Per fare un esempio:
object App {
def isEven(i: Int) = i % 2 == 0
def isOdd(i: Int) = i % 2 == 1
def main(args: Array[String]): Unit = {
val n = (1 to 10).toList
n.filter(isEven).flatMap(i => n.filter(isOdd).map(j => i * j))
}
}
una volta compilato con scalac App.scala
ottieni:
App$$anonfun$main$1.class
App$$anonfun$main$2$$anonfun$apply$1.class
App$$anonfun$main$2$$anonfun$apply$2.class
App$$anonfun$main$2.class
App$.class
App.class
E puoi vedere il problema dell'ordine della classe che le cose nel codice possono facilmente cambiare. Ciò renderebbe gli strumenti come scons molto meno utili e forse anche problematici.