Je sors du placard là-dessus! Je ne comprends pas SBT. Là, je l'ai dit, maintenant aidez-moi s'il vous plaît.
Tous les chemins mènent à Rome, et qui est la même chose pour SBT: Pour commencer à utiliser SBT
il y a SBT
, SBT Launcher
, SBT-extras
, etc, et puis il y a différentes façons d'inclure et décider sur les dépôts. Y a-t-il un «meilleur» moyen?
Je demande parce que parfois je me perds un peu. La documentation SBT est très complète et complète, mais je ne sais pas quand utiliser build.sbt
ou project/build.properties
ou project/Build.scala
ou project/plugins.sbt
.
Ensuite, ça devient amusant, il y a le Scala-IDE
et SBT
- Quelle est la bonne façon de les utiliser ensemble? Qu'est-ce qui vient en premier, la poule ou l'œuf?
Le plus important est probablement, comment trouver les bons référentiels et versions à inclure dans votre projet? Dois-je simplement sortir une machette et commencer à me frayer un chemin? Je trouve assez souvent des projets qui incluent tout et l'évier de la cuisine, puis je me rends compte que je ne suis pas le seul à me perdre un peu.
À titre d'exemple simple, en ce moment, je démarre un tout nouveau projet. Je souhaite utiliser les dernières fonctionnalités de SLICK
et Scala
et cela nécessitera probablement la dernière version de SBT. Quel est le bon point de départ et pourquoi? Dans quel fichier dois-je le définir et à quoi doit-il ressembler? Je sais que je peux faire fonctionner cela, mais j'aimerais vraiment avoir un avis d'expert sur où tout devrait aller (pourquoi cela devrait aller là-bas sera un bonus).
J'utilise SBT
pour de petits projets depuis plus d'un an maintenant. J'ai utilisé SBT
et ensuite SBT Extras
(car cela a fait disparaître certains maux de tête par magie), mais je ne sais pas pourquoi je devrais utiliser l'un ou l'autre. Je suis juste un peu frustré de ne pas comprendre comment les choses s'articulent ( SBT
et les référentiels), et je pense que cela sauvera le prochain gars de cette manière beaucoup de difficultés si cela pouvait être expliqué en termes humains.
Build.scala
à configurer le classpath, et c'est pourquoi vous avez en fait besoin de sbteclipse pour générer le .classpath Eclipse. J'espère que cela t'aides.Réponses:
Pour les dépendances basées sur Scala, j'irais avec ce que les auteurs recommandent. Par exemple: http://code.google.com/p/scalaz/#SBT indique d'utiliser:
Ou https://github.com/typesafehub/sbteclipse/ a des instructions sur où ajouter:
Pour les dépendances basées sur Java, j'utilise http://mvnrepository.com/ pour voir ce qui existe, puis je clique sur l'onglet SBT. Par exemple http://mvnrepository.com/artifact/net.sf.opencsv/opencsv/2.3 indique d'utiliser:
Ensuite, sortez la machette et commencez à vous frayer un chemin. Si vous avez de la chance, vous ne finirez pas par utiliser des jars qui dépendent de certains des mêmes jars mais avec des versions incompatibles. Compte tenu de l'écosystème Java, vous finissez souvent par inclure tout et l'évier de la cuisine et il faut un certain effort pour éliminer les dépendances ou vous assurer de ne pas manquer les dépendances requises.
Je pense que le bon sens est de renforcer progressivement l'immunité contre la sbt .
Assurez-vous de bien comprendre:
{<build-uri>}<project-id>/config:key(for task-key)
SettingKey
,TaskKey
,InputKey
) - lire la section intitulée « Touches tâche » dans http://www.scala-sbt.org/release/docs/Getting-Started/Basic-DefGardez ces 4 pages ouvertes à tout moment afin que vous puissiez sauter et rechercher diverses définitions et exemples:
Utilisez au maximum
show
etinspect
et la complétion des onglets pour vous familiariser avec les valeurs réelles des paramètres, leurs dépendances, les définitions et les paramètres associés. Je ne crois pas que les relations que vous découvrirez en utilisantinspect
sont documentées nulle part. S'il y a une meilleure façon, je veux en savoir plus.la source
La façon dont j'utilise sbt est:
project
dossier avec unMyProject.scala
fichier pour configurer sbt. Je préfère de loin cela à l'build.sbt
approche - c'est scala et est plus flexibleproject/plugins.sbt
fichier et ajoutez le plugin approprié pour votre IDE. Soit sbt-eclipse, sbt-idea ou ensime-sbt-cmd afin que vous puissiez générer des fichiers de projet pour eclipse, intellij ou ensime.Je ne prends pas la peine de vérifier les fichiers de projet IDE car ils sont générés par sbt, mais il peut y avoir des raisons pour lesquelles vous souhaitez le faire.
Vous pouvez voir un exemple de configuration comme celui-ci ici .
la source
Utilisez Typesafe Activator, une façon élégante d'appeler sbt, qui est fournie avec des modèles de projet et des graines: https://typesafe.com/activator
la source
Installation
brew install sbt
ou similaire installe sbt qui consiste techniquement enLorsque vous exécutez à
sbt
partir du terminal, il exécute en fait le script bash du lanceur sbt. Personnellement, je n'ai jamais eu à m'inquiéter de cette trinité, et j'ai juste utilisé sbt comme si c'était une seule chose.Configuration
Pour configurer sbt pour un projet particulier, enregistrez le
.sbtopts
fichier à la racine du projet. Pour configurer sbt à l'échelle du système, modifiez/usr/local/etc/sbtopts
. L'exécutionsbt -help
devrait vous indiquer l'emplacement exact. Par exemple, pour donner plus de mémoire à sbt en tant qu'exécution uniquesbt -mem 4096
, ou enregistrer-mem 4096
dans.sbtopts
ousbtopts
pour que l'augmentation de la mémoire prenne effet de manière permanente.Structure du projet
sbt new scala/scala-seed.g8
crée une structure de projet sbt Hello World minimaleCommandes fréquentes
Myriade de coquillages
La définition de construction est un projet Scala approprié
C'est l'un des concepts sbt idiomatiques clés. Je vais essayer d'expliquer avec une question. Supposons que vous souhaitiez définir une tâche sbt qui exécutera une requête HTTP avec scalaj-http. Intuitivement, nous pourrions essayer ce qui suit à l'intérieur
build.sbt
Cependant, cela entraînera une erreur en disant qu'il manque
import scalaj.http._
. Comment est - ce possible quand nous, juste au- dessus, ajoutéscalaj-http
àlibraryDependencies
? De plus, pourquoi cela fonctionne-t-il quand, à la place, nous ajoutons la dépendanceproject/build.sbt
?La réponse est que cela
fooTask
fait en fait partie d'un projet Scala distinct de votre projet principal. Ce projet Scala différent se trouve dans leproject/
répertoire qui a son propretarget/
répertoire où résident ses classes compilées. En fait, sousproject/target/config-classes
il devrait y avoir une classe qui se décompile en quelque chose commeNous voyons que
fooTask
c'est simplement un membre d'un objet Scala régulier nommé$9c2192aea3f1db3c251d
. De toute évidence, celascalaj-http
devrait être une dépendance de la définition du projet$9c2192aea3f1db3c251d
et non la dépendance du projet approprié. Par conséquent, il doit être déclaré dansproject/build.sbt
au lieu debuild.sbt
, carproject
c'est là que réside le projet Scala de définition de construction.Pour indiquer que la définition de construction n'est qu'un autre projet Scala, exécutez
sbt consoleProject
. Cela chargera Scala REPL avec le projet de définition de build sur le chemin de classe. Vous devriez voir une importation du typeNous pouvons donc maintenant interagir directement avec le projet de définition de construction en l'appelant avec Scala proprement dit au lieu de
build.sbt
DSL. Par exemple, ce qui suit exécutefooTask
build.sbt
sous le projet racine est un DSL spécial qui aide à définir la définition de construction du projet Scala sousproject/
.Et le projet Scala de définition de build, peut avoir son propre projet Scala de définition de build sous
project/project/
et ainsi de suite. Nous disons que sbt est récursif .sbt est parallèle par défaut
sbt construit le DAG à partir des tâches. Cela lui permet d'analyser les dépendances entre les tâches et de les exécuter en parallèle et même d'effectuer la déduplication.
build.sbt
DSL est conçu dans cet esprit, ce qui pourrait conduire à une sémantique initialement surprenante. Selon vous, quel est l'ordre d'exécution dans l'extrait suivant?Intuitivement, on pourrait penser que le flux consiste d'abord à imprimer
hello
puis à exécutera
, puis à effectuer uneb
tâche. Cependant, cela signifie en fait exécutera
etb
en parallèle , et avantprintln("hello")
celaou parce que l'ordre de
a
etb
n'est pas garantiPeut-être paradoxalement, en sbt, il est plus facile de faire du parallèle que de la série. Si vous avez besoin d'une commande en série, vous devrez utiliser des choses spéciales comme
Def.sequential
ouDef.taskDyn
émuler pour la compréhension .est similaire à
où nous voyons qu'il n'y a pas de dépendances entre les composants, tandis que
est similaire à
où nous voyons
sum
dépend et doit attendrea
etb
.En d'autres termes
.value
sequential
outaskDyn
Considérez un autre extrait de code sémantiquement déroutant en raison de la nature de construction de dépendances de
value
, où au lieu deil faut écrire
Notez que la syntaxe
.value
concerne les relations dans le DAG et ne signifie pasau lieu de cela, cela signifie quelque chose comme
Alors maintenant, il pourrait être un peu plus clair pourquoi
x
une valeur ne peut pas encore être attribuée; il n'y a pas encore de valeur disponible à l'étape de l'établissement de relations.Nous pouvons clairement voir une différence de sémantique entre Scala proprement dit et le langage DSL dans
build.sbt
. Voici quelques règles de base qui fonctionnent pour moiSetting[T]
.value
syntaxe et sbt se chargera d'établir une relation entreSetting[T]
Def.sequential
ouDef.taskDyn
Commandes vs tâches
Les commandes sont un moyen paresseux de sortir du DAG. En utilisant des commandes, il est facile de modifier l'état de construction et de sérialiser les tâches comme vous le souhaitez. Le coût est que nous perdons la parallélisation et la déduplication des tâches fournies par DAG, ce qui devrait être le choix préféré des tâches. Vous pouvez considérer les commandes comme une sorte d'enregistrement permanent d'une session que l'on pourrait faire à l'intérieur
sbt shell
. Par exemple, étant donnéconsidérez le résultat de la session suivante
En particulier, pas comment nous modifions l'état de construction avec
set x := 41
. Les commandes nous permettent de faire un enregistrement permanent de la session ci-dessus, par exempleNous pouvons également rendre la commande sécurisée en utilisant
Project.extract
etrunTask
Portées
Les champs d'application entrent en jeu lorsque nous essayons de répondre aux types de questions suivants
sbt a un espace de portée multi-axes qui peut être parcouru à l'aide de la syntaxe slash , par exemple,
Personnellement, je me retrouve rarement à me soucier de la portée. Parfois, je veux compiler uniquement des sources de test
ou peut-être exécuter une tâche particulière à partir d'un sous-projet particulier sans avoir à naviguer vers ce projet avec
project subprojB
Je pense que les règles empiriques suivantes aident à éviter les complications de portée
build.sbt
fichiers mais seulement un seul maître sous le projet racine qui contrôle tous les autres sous-projetsval
et l'ajouter explicitement à chaque sous-projetConstruction multi-projets
Au lieu de plusieurs fichiers build.sbt pour chaque sous-projet
Avoir un seul maître
build.sbt
pour les gouverner tousIl existe une pratique courante de prise en compte des paramètres communs dans les versions multi-projets
par exemple
Navigation des projets
Plugins
N'oubliez pas que la définition de construction est un projet Scala approprié qui réside sous
project/
. C'est ici que nous définissons un plugin en créant des.scala
fichiersVoici un plugin automatique minimal sous
project/FooPlugin.scala
Le remplacement
devrait permettre efficacement le plug - in pour tous les sous-projets sans avoir à appeler explicitement
enablePlugin
dansbuild.sbt
.IntelliJ et sbt
Veuillez activer le paramètre suivant (qui devrait vraiment être activé par défaut )
sous
Références clés
la source