¡Voy a salir del armario con esto! No entiendo SBT. Ahí, lo dije, ahora ayúdame por favor.
Todos los caminos conducen a Roma, y que es el mismo para SBT: Para empezar a utilizar SBT
no es SBT
, SBT Launcher
, SBT-extras
, etc, y luego hay diferentes maneras de incluir y decidir sobre los repositorios. ¿Existe una "mejor" forma?
Lo pregunto porque a veces me pierdo un poco. La documentación de SBT es muy completa y completa, pero no sé cuándo usar build.sbt
o project/build.properties
o project/Build.scala
o project/plugins.sbt
.
Entonces se vuelve divertido, está el Scala-IDE
y SBT
- ¿Cuál es la forma correcta de usarlos juntos? ¿Qué viene primero, el huevo o la gallina?
Lo más importante es probablemente, ¿cómo encuentra los repositorios y versiones correctos para incluir en su proyecto? ¿Saco un machette y empiezo a abrirme camino hacia adelante? A menudo encuentro proyectos que incluyen todo y el fregadero de la cocina, y luego me doy cuenta de que no soy el único que se pierde un poco.
Como ejemplo simple, ahora mismo estoy comenzando un nuevo proyecto. Quiero utilizar las funciones más recientes de SLICK
y Scala
probablemente requiera la última versión de SBT. ¿Cuál es el punto sensato para empezar y por qué? ¿En qué archivo debería definirlo y cómo debería verse? Sé que puedo hacer que esto funcione, pero realmente me gustaría una opinión experta sobre dónde debería ir todo (por qué debería ir allí habrá una bonificación).
Lo he estado usando SBT
para proyectos pequeños durante más de un año. Usé SBT
y luego SBT Extras
(ya que hizo que algunos dolores de cabeza desaparecieran mágicamente), pero no estoy seguro de por qué debería usar uno u otro. Me estoy frustrando un poco por no entender cómo encajan las cosas ( SBT
y los repositorios), y creo que le ahorraría muchas dificultades al próximo que venga de esta manera si esto pudiera explicarse en términos humanos.
Build.scala
configure el classpath, y es por eso que realmente necesita sbteclipse para generar el Eclipse .classpath. Espero que esto ayude.Respuestas:
Para las dependencias basadas en Scala, iría con lo que recomiendan los autores. Por ejemplo: http://code.google.com/p/scalaz/#SBT indica utilizar:
O https://github.com/typesafehub/sbteclipse/ tiene instrucciones sobre dónde agregar:
Para las dependencias basadas en Java, utilizo http://mvnrepository.com/ para ver lo que hay, luego hago clic en la pestaña SBT. Por ejemplo, http://mvnrepository.com/artifact/net.sf.opencsv/opencsv/2.3 indica utilizar:
Luego saca el machette y comienza a abrir camino hacia adelante. Si tiene suerte, no terminará usando frascos que dependan de algunos de los mismos frascos pero con versiones incompatibles. Dado el ecosistema de Java, a menudo terminas incluyendo todo y el fregadero de la cocina y se necesita un poco de esfuerzo para eliminar las dependencias o asegurarte de que no faltan las dependencias necesarias.
Creo que el punto es crear inmunidad al sbt gradualmente .
Asegúrese de comprender:
{<build-uri>}<project-id>/config:key(for task-key)
SettingKey
,TaskKey
,InputKey
) - lea la sección denominada "llaves de la tarea" en http://www.scala-sbt.org/release/docs/Getting-Started/Basic-DefMantenga esas 4 páginas abiertas en todo momento para que pueda saltar y buscar varias definiciones y ejemplos:
Hacer un uso máximo de
show
yinspect
y la finalización pestaña para familiarizarse con los valores reales de los ajustes, sus dependencias, definiciones y ajustes relacionados. No creo que las relaciones que descubrirás usandoinspect
estén documentadas en ninguna parte. Si hay una forma mejor, quiero saberlo.fuente
La forma en que uso sbt es:
project
carpeta con unMyProject.scala
archivo para configurar sbt. Prefiero esto albuild.sbt
enfoque: es escalable y es más flexibleproject/plugins.sbt
archivo y agregue el complemento apropiado para su IDE. Ya sea sbt-eclipse, sbt-idea o ensime-sbt-cmd para que pueda generar archivos de proyecto para eclipse, intellij o ensime.No me molesto en verificar los archivos del proyecto IDE ya que son generados por sbt, pero puede haber razones por las que desee hacerlo.
Puede ver un ejemplo configurado como este aquí .
fuente
Use Typesafe Activator, una forma elegante de llamar a sbt, que viene con plantillas de proyecto y semillas: https://typesafe.com/activator
fuente
Instalación
brew install sbt
o instalaciones similares sbt que técnicamente hablando consisten enCuando se ejecuta
sbt
desde la terminal, en realidad ejecuta el script bash del lanzador sbt. Personalmente, nunca tuve que preocuparme por esta trinidad, y usar sbt como si fuera una sola cosa.Configuración
Para configurar sbt para un proyecto en particular, guarde el
.sbtopts
archivo en la raíz del proyecto. Para configurar sbt en todo el sistema, modificar/usr/local/etc/sbtopts
. La ejecuciónsbt -help
debería indicarle la ubicación exacta. Por ejemplo, para dar más memoria a sbt como ejecución únicasbt -mem 4096
, o guardar-mem 4096
en.sbtopts
osbtopts
para que el aumento de memoria tenga efecto de forma permanente.Estructura del proyecto
sbt new scala/scala-seed.g8
crea una estructura mínima de proyecto de Hello World sbtComandos frecuentes
Gran cantidad de conchas
La definición de compilación es un proyecto Scala adecuado
Este es uno de los conceptos idiomáticos clave de sbt. Intentaré explicarlo con una pregunta. Supongamos que desea definir una tarea sbt que ejecutará una solicitud HTTP con scalaj-http. Intuitivamente, podríamos intentar lo siguiente dentro
build.sbt
Sin embargo, este error indicará que falta
import scalaj.http._
. ¿Cómo es esto posible cuando, justo encima, añadimosscalaj-http
alibraryDependencies
? Además, ¿por qué funciona cuando, en cambio, agregamos la dependencia aproject/build.sbt
?La respuesta es que en
fooTask
realidad es parte de un proyecto Scala separado de su proyecto principal. Este proyecto de Scala diferente se puede encontrar en unproject/
directorio que tiene su propiotarget/
directorio donde residen sus clases compiladas. De hecho, debajoproject/target/config-classes
debería haber una clase que se descompila en algo comoVemos que
fooTask
es simplemente un miembro de un objeto Scala regular llamado$9c2192aea3f1db3c251d
. Claramentescalaj-http
debería ser una dependencia de la definición del proyecto$9c2192aea3f1db3c251d
y no la dependencia del proyecto adecuado. Por lo tanto, debe declararse enproject/build.sbt
lugar debuild.sbt
, porqueproject
es donde reside la definición de compilación del proyecto Scala.Para señalar que la definición de compilación es solo otro proyecto de Scala, ejecute
sbt consoleProject
. Esto cargará Scala REPL con el proyecto de definición de compilación en la ruta de clases. Debería ver una importación a lo largo de las líneas deAsí que ahora podemos interactuar directamente con el proyecto de definición de compilación llamándolo con Scala en lugar de
build.sbt
DSL. Por ejemplo, lo siguiente se ejecutafooTask
build.sbt
bajo proyecto raíz hay un DSL especial que ayuda a definir la definición de compilación del proyecto Scalaproject/
.Y la definición de compilación del proyecto Scala, puede tener su propia definición de compilación en el proyecto Scala
project/project/
y así sucesivamente. Decimos que sbt es recursivo .sbt es paralelo por defecto
sbt crea DAG a partir de tareas. Esto le permite analizar dependencias entre tareas y ejecutarlas en paralelo e incluso realizar la deduplicación.
build.sbt
DSL está diseñado con esto en mente, lo que podría conducir a una semántica inicialmente sorprendente. ¿Cuál crees que es el orden de ejecución en el siguiente fragmento?Intuitivamente, uno podría pensar que el flujo aquí es primero imprimir,
hello
luego ejecutara
y luego realizar unab
tarea. Sin embargo, esta realidad significa ejecutara
yb
en paralelo , y antes deprintln("hello")
lo queo porque el orden de
a
yb
no está garantizadoQuizás paradójicamente, en sbt es más fácil hacerlo en paralelo que en serie. Si necesita pedidos en serie, tendrá que usar elementos especiales como
Def.sequential
oDef.taskDyn
emular para la comprensión .es parecido a
donde vemos que no hay dependencias entre componentes, mientras que
es parecido a
donde vemos
sum
depende y hay que esperara
yb
.En otras palabras
.value
sequential
otaskDyn
Considere otro fragmento semánticamente confuso como resultado de la naturaleza de construcción de dependencias de
value
, donde en lugar detenemos que escribir
Tenga en cuenta que la sintaxis
.value
trata sobre las relaciones en el DAG y no significaen cambio, significa algo como
Así que ahora podría ser un poco más claro por qué
x
no se puede asignar un valor todavía; aún no hay ningún valor disponible en la etapa de construcción de relaciones.Podemos ver claramente una diferencia en la semántica entre Scala propiamente dicho y el lenguaje DSL en
build.sbt
. Aquí hay algunas reglas prácticas que me funcionanSetting[T]
.value
sintaxis y sbt se encargará de establecer la relación entreSetting[T]
Def.sequential
oDef.taskDyn
Comandos vs tareas
Los comandos son una forma perezosa de salir del DAG. Usando comandos, es fácil mutar el estado de compilación y serializar las tareas como desee. El costo es que perdemos la paralelización y la deduplicación de las tareas proporcionadas por DAG, de qué manera las tareas deberían ser la opción preferida. Puede pensar en los comandos como una especie de grabación permanente de una sesión que se puede hacer en el interior
sbt shell
. Por ejemplo, dadoconsiderar el resultado de la siguiente sesión
En particular, no cómo mutamos el estado de construcción con
set x := 41
. Comandos nos permite realizar una grabación permanente de la sesión anterior, por ejemploTambién podemos hacer que el comando sea seguro usando
Project.extract
yrunTask
Alcances
Los alcances entran en juego cuando intentamos responder a los siguientes tipos de preguntas
sbt tiene un espacio de alcance de varios ejes que se puede navegar usando la sintaxis de barra , por ejemplo,
Personalmente, rara vez tengo que preocuparme por el alcance. A veces quiero compilar solo fuentes de prueba
o quizás ejecutar una tarea en particular de un subproyecto en particular sin tener que navegar primero a ese proyecto con
project subprojB
Creo que las siguientes reglas generales ayudan a evitar complicaciones en la determinación del alcance
build.sbt
archivos, sino solo uno maestro bajo el proyecto raíz que controla todos los demás subproyectosval
y agregarlo explícitamente a cada subproyectoConstrucción multiproyecto
En lugar de varios archivos build.sbt para cada subproyecto
Tener un solo maestro
build.sbt
para gobernarlos a todosExiste una práctica común de factorizar configuraciones comunes en compilaciones multiproyecto
por ejemplo
Navegación de proyectos
Complementos
Recuerde que la definición de compilación es un proyecto Scala adecuado que reside debajo
project/
. Aquí es donde definimos un complemento creando.scala
archivosAquí hay un complemento automático mínimo en
project/FooPlugin.scala
La anulación
debe permitir efectivamente el plug-in para todos los sub-proyectos sin tener que llamar explícitamente
enablePlugin
enbuild.sbt
.IntelliJ y sbt
Habilite la siguiente configuración (que realmente debería estar habilitada de forma predeterminada )
debajo
Referencias clave
fuente