Подтвердить что ты не робот

Является ли использование "агрегата" следующим за "dependOn" избыточным с теми же модулями?

В SBT используется использование совокупности, которая зависит от избыточного избытка, если оба они содержат одни и те же подмодули? Согласно документации, кажется, так, но я видел это поведение, используемое раньше, и я не понимаю, в чем преимущество. Если проект определен с зависимостями, разве это уже не означает, что агрегат делает для тех же самых зависимостей? Я замечаю, что моя сборка проекта намного медленнее с использованием этой избыточной совокупности, чем без нее, и я хотел бы знать, могу ли я ее безопасно удалить.

lazy val module = sbt.Project(...) dependsOn (foo, bar) aggregate (foo, bar)

ИЛИ просто...

lazy val module = sbt.Project(...) dependsOn (foo, bar)

Я использую SBT 0.13.6

4b9b3361

Ответ 1

tl; dr aggregate заставляет задачи выполняться в агрегационном модуле и все aggregate d один, а dependsOn устанавливает зависимость CLASSPATH, поэтому библиотеки видны в aggregate (в зависимости от конфигурации, которая compile aka default в этом примере).

Образец для демонстрации различий.

Я использую следующий build.sbt (ничего действительно интересного):

lazy val a = project

lazy val b = project

lazy val c = project dependsOn b aggregate (a,b)

В сборке определяются три модуля a, b и c, а последний c - агрегат для a и b. Там четвертый модуль - неявный, который объединяет все модули a, b и c.

> projects
[info] In file:/Users/jacek/sandbox/aggregate-dependsOn/
[info]     a
[info]   * aggregate-dependson
[info]     b
[info]     c

Когда я выполняю задачу в модуле aggreate, задача будет выполняться в модулях aggregate d.

> compile
[info] Updating {file:/Users/jacek/sandbox/aggregate-dependsOn/}b...
[info] Updating {file:/Users/jacek/sandbox/aggregate-dependsOn/}a...
[info] Updating {file:/Users/jacek/sandbox/aggregate-dependsOn/}aggregate-dependson...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Updating {file:/Users/jacek/sandbox/aggregate-dependsOn/}c...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[success] Total time: 0 s, completed Oct 22, 2014 9:33:20 AM

То же самое происходит, когда я выполняю задачу в c, которая, в свою очередь, выполняет ее против a и b, но не в проекте верхнего уровня.

> show c/clean
[info] a/*:clean
[info]  ()
[info] b/*:clean
[info]  ()
[info] c/*:clean
[info]  ()
[success] Total time: 0 s, completed Oct 22, 2014 9:34:26 AM

Когда задача выполняется в a или b, она запускается только внутри проекта.

> show a/clean
[info] ()
[success] Total time: 0 s, completed Oct 22, 2014 9:34:43 AM

Независимо от того, выполняется ли задача в проектах aggregate, управляется ключом aggregate, охваченным проектом и/или задачей.

> show aggregate
[info] a/*:aggregate
[info]  true
[info] b/*:aggregate
[info]  true
[info] c/*:aggregate
[info]  true
[info] aggregate-dependson/*:aggregate
[info]  true

Измените его, как описано в Aggregation:

В проекте, выполняющем агрегацию, корневой проект в этом случае вы можете управлять агрегацией для каждой задачи. (...) aggregate in update - это совокупный ключ, охваченный задачей обновления.

Ниже я изменяю ключ для модуля c и clean, поэтому clean больше не выполняется в aggregate d-модулях a и b:

> set aggregate in (c, clean) := false
[info] Defining c/*:clean::aggregate
[info] The new value will be used by no settings or tasks.
[info] Reapplying settings...
[info] Set current project to aggregate-dependson (in build file:/Users/jacek/sandbox/aggregate-dependsOn/)
> show c/clean
[info] ()
[success] Total time: 0 s, completed Oct 22, 2014 9:39:13 AM

Другие задачи для c не затронуты и все еще выполняют задачу в c будут запускать ее в модулях aggregate:

> show c/libraryDependencies
[info] a/*:libraryDependencies
[info]  List(org.scala-lang:scala-library:2.10.4)
[info] b/*:libraryDependencies
[info]  List(org.scala-lang:scala-library:2.10.4)
[info] c/*:libraryDependencies
[info]  List(org.scala-lang:scala-library:2.10.4)

Пока aggregate устанавливает зависимость для задач sbt, поэтому они выполняются в других модулях aggregate d, dependsOn устанавливает зависимость CLASSPATH, то есть код в модуле dependsOn ed отображается в dependsOn (извините за "новые" слова).

Предположим, что b имеет основной объект следующим образом:

object Hello extends App {
  println("Hello from B")
}

Сохраните объект Hello до b/hello.scala, то есть в модуле b.

Так как c был определен как dependsOn b (см. build.sbt выше), объект Hello отображается в b (потому что он принадлежит модулю), но также и в c.

> b/run
[info] Running Hello
Hello from B
[success] Total time: 0 s, completed Oct 22, 2014 9:46:44 AM
> c/runMain Hello
[info] Running Hello
Hello from B
[success] Total time: 0 s, completed Oct 22, 2014 9:46:58 AM

(мне пришлось использовать runMain в c, поскольку только run не мог видеть класс, который я не могу объяснить).

Попытка запуска задачи в a заканчивается java.lang.ClassNotFoundException: Hello, поскольку класс не отображается в модуле.

> a/runMain Hello
[info] Updating {file:/Users/jacek/sandbox/aggregate-dependsOn/}a...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Running Hello
[error] (run-main-6) java.lang.ClassNotFoundException: Hello
java.lang.ClassNotFoundException: Hello
    at java.lang.ClassLoader.findClass(ClassLoader.java:530)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
[trace] Stack trace suppressed: run last a/compile:runMain for the full output.
java.lang.RuntimeException: Nonzero exit code: 1
    at scala.sys.package$.error(package.scala:27)
[trace] Stack trace suppressed: run last a/compile:runMain for the full output.
[error] (a/compile:runMain) Nonzero exit code: 1
[error] Total time: 0 s, completed Oct 22, 2014 9:48:15 AM

Переопределите a до dependsOn b в build.sbt, и исключение исчезнет.

В официальной документации вы должны прочитать многопроектные сборки.