2011-11-30 23 views
12

Supongamos que un chico de mi empresa tiene un proyecto de sbt llamado commons que es bastante general. Este proyecto se define de la manera tradicional sbt: en la carpeta principal con la definición de compilación en el archivo project/Build.scala.Cómo especificar eso para construir el proyecto A ¿otro proyecto B tiene que ser construido primero?

Ahora otro tipo está desarrollando un proyecto llamado databinding que depende de commons. Queremos definir este proyecto de la misma manera, con project/Build.scala.

tenemos la siguiente estructura de directorios:

dev/ 
    commons/ 
    src/ 
     *.scala files here... 
    project/ 
     Build.scala 
    databinding/ 
    src/ 
     *.scala files here... 
    project/ 
     Build.scala 

¿Cómo puedo especificar que requiere databindingcommons que se construirá primero y utilizar los archivos de clase de salida?

leí Multi-project builds, y se le ocurrió la siguiente definición para la construcción de databinding:

object MyBuild extends Build { 

    lazy val root = Project(id = "databinding", base = file(".")) settings (
    // ... omitted 
) dependsOn (commons) 

    lazy val common = Project(id = "commons", 
    base = file("../commons") 
) 

} 

Excepto que no funciona: SBT no le gusta la .. y lanza una AssertionError. Aparentemente, commons debe ser una carpeta dentro de databinding. Pero estos dos proyectos se guardan en repositorios git separados, que no podemos anidar.

¿Cómo se puede especificar esta dependencia correctamente?

Respuesta

12

Debe definir el multiproyecto en un proyecto raíz (o cualquier nombre pero este se ajusta bien) que se definirá en dev/project/Build.scala.

object RootBuild extends Build { 
    lazy val root = Project(id = "root", base = file(".")) 
    .settings(...) 
    .aggregate(commons, databinding) 

    lazy val commons = Project(id = "commons", base = file("commons")) 
    .settings(...) 

    lazy val databinding = Project(id = "databinding", base = file("databinding")) 
    .settings(...) 
    .dependsOn(commons) 
} 

una cosa más, SBT no soporta *.scala archivos de configuración en sub-proyectos. Esto significa que tendrá que migrar la configuración que hizo en commons/project/Build.scala y databinding/project/Build.scala en respectivamente commons/build.sbt y databinding/build.sbt.

Si algunas de sus configuraciones no son adecuadas para un archivo de definición .sbt, deberá agregarlas en la raíz project/Build.scala. Obviamente, las configuraciones definidas en la raíz Build.scala están disponibles en los archivos *.sbt.

+0

Muchas gracias por la explicación, David. Esto parece extraño, ¿solo porque otros proyectos usan mi proyecto 'commons', no puede tener una definición completa en un archivo' .scala'? –

+0

Y, ¿hay alguna alternativa, por ejemplo, agregar un resolver que busque los contenedores generados por los proyectos de los que depende? –

+0

En cuanto a su primera pregunta, es una restricción SBT que le impide usar un '*.archivo scala' para definir subproyectos. Creo que es una limitación debido a la forma en que SBT fusiona los archivos de definición de proyectos. Afortunadamente, los archivos '* .sbt' podrán acceder a valores, configuraciones ... desde su proyecto raíz' Build.scala'. También puede considerar, como lo menciona en el segundo comentario, publicar su 'common' en local (publish-local) por ejemplo, y el resolvedor debería recuperarlo. Tenga cuidado de agregar 'isChanging()' a la definición de dependencia si desea usar un sistema SNAPSHOT. Espero que esto ayude – David

1

Puede tener dos proyectos separados y simplemente publicar uno localmente, agregarlo como una dependencia de biblioteca normal al otro.

10

Debe usar RootProject (en caso de referirse al proyecto raíz de otro proyecto) o ProjectRef (en caso de referirse al subproyecto de otro proyecto).

Este es un ejemplo de la utilización de RootProject:

 lazy val commons = RootProject(file("../commons")) 
     lazy val root = Project(id = "databinding", base = file(".")) settings (...) dependsOn (commons) 

Y aquí está la muestra para el uso de ProjectRef

 lazy val commons = ProjectRef(file("../commons"), "sub-project") 
     lazy val root = Project(id = "databinding", base = file(".")) settings (...) dependsOn (commons) 
+0

¿Es esto 'RootProject' nuevo? ¿Esta nueva API invalida la solución recomendada de David? –

+0

Parece que sí. No, pero diría que es un poco más simple –

+1

No puedo entender cómo la respuesta aprobada podría haber funcionado para el PO sin la migración que derrota el propósito de que los dos proyectos sean independientes. No lo harán después de la migración debido al proyecto raíz. –

Cuestiones relacionadas