2011-11-30 12 views
12

Supponiamo che un ragazzo della mia azienda abbia un progetto sbt chiamato commons che è piuttosto generico. Questo progetto è definito nel modo tradizionale sbt: nella cartella principale con la definizione build nel file project/Build.scala.Come specificare che per costruire il progetto Un altro progetto B deve essere costruito per primo?

Ora un altro tizio sta sviluppando un progetto chiamato databinding che dipende da commons. Vogliamo definire questo progetto allo stesso modo, con project/Build.scala.

Abbiamo il seguente schema di directory:

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

Come posso specificare che databinding richiede commons da costruire prima e utilizzare i file di classe di uscita?

ho letto Multi-project builds, e si avvicinò con la seguente per la definizione di compilazione di 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") 
) 

} 

Solo che non funziona: sbt non piace il .. e lancia un AssertionError. Apparentemente, commons dovrebbe essere una cartella all'interno di databinding. Ma questi due progetti sono tenuti in repository git separati, che non possiamo annidare.

In che modo questa dipendenza può essere specificata correttamente?

risposta

12

È necessario definire il multiprogetto in un progetto radice (o qualsiasi altro nome, ma questo si adatta bene) che sarà definito in 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) 
} 

più una cosa, SBT non supporta *.scala file di configurazione in sotto-progetti. Ciò significa che sarà necessario migrare la configurazione effettuata su commons/project/Build.scala e databinding/project/Build.scala rispettivamente in commons/build.sbt e databinding/build.sbt.

Se alcune delle configurazioni non sono adatte per un file di definizione .sbt, sarà necessario aggiungerle nella radice project/Build.scala. Ovviamente, le impostazioni definite nella radice Build.scala sono disponibili nei file *.sbt.

+0

Grazie mille per la spiegazione, David. Questo sembra strano, è che solo perché altri progetti usano il mio progetto 'commons', non può avere una definizione completa in un file' .scala'? –

+0

E, c'è un'alternativa - ad esempio, aggiungendo un risolutore che cerca i vasi generati dai progetti da cui dipende? –

+0

Per quanto riguarda la prima domanda, si tratta di una restrizione SBT che impedisce di usare un '*.scala' file per definire sotto-progetti. Penso che sia una limitazione dovuta al modo in cui SBT unisce i file di definizione del progetto. Fortunatamente, i file '* .sbt' saranno in grado di accedere a vals, impostazioni ... dal tuo progetto root' Build.scala'. Puoi anche considerare di menzionarlo nel secondo commento per pubblicare il tuo 'comune' in locale (publish-local) per esempio e il risolutore dovrebbe recuperarlo. Fai attenzione ad aggiungere 'isChanging()' alla definizione di dipendenza se vuoi usare un sistema SNAPSHOT. Spero che questo ti sia d'aiuto. – David

1

Si potrebbero avere due progetti separati e basta pubblicarne uno a livello locale, aggiungendolo come una normale dipendenza di libreria all'altro.

10

È necessario utilizzare RootProject (in caso di riferimento al progetto radice di un altro progetto) o ProjectRef (in caso di riferimento al sottoprogetto di un altro progetto).

Ecco un esempio di utilizzo di RootProject:

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

E qui è il campione per l'utilizzo di ProjectRef

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

Questo 'RootProject' è nuovo? Questa nuova API invalida la soluzione raccomandata di David? –

+0

Sembra così. No, ma direi che è un po 'più semplice –

+1

Non riesco a capire come la risposta approvata avrebbe potuto funzionare per l'OP senza la migrazione che sconfigge lo scopo di indipendenza dei due progetti. Non lo faranno dopo la migrazione a causa del progetto root. –

Problemi correlati