简体   繁体   中英

When sbt-assembly executes?

StackOverflow:

With sbt-assembly (sbt plugin) and sbt-multiproject, I would like to produce fat-jars of sub-projects specified in command line arguments.

The command may be as follows:

sbt "assemblyWith hello world"

I defined four sub-projects named hello, world, alien, and root. I want the command to produce hello-assembly.jar and world-assembly.jar. But the alien-assembly.jar also.

When the assembly process is fired?

Here is the sample build.sbt which produces the problem. ( I hope to see the log

'managedProject: ProjectRef(module/hello,hello)'

before

'Packaging /path/to/dir/module/world/target/scala-2.11/world-assembly-0.1-SNAPSHOT.jar ...'

)

[build.sbt]

import sbt._
import Keys._
import complete.DefaultParsers.spaceDelimited

name := "sbt-query"

scalaVersion in ThisBuild := "2.11.7"

scalacOptions in ThisBuild ++= Seq("-unchecked", "-deprecation", "-feature")

test in assembly in ThisBuild := {}

lazy val hello = (project in file("./module/hello"))

lazy val world = (project in file("./module/world"))

lazy val alien = (project in file("./module/alien"))

lazy val root = (project in file(".")).aggregate(hello, world, alien)

// sbt "assemblyWith hello world"
// aims to produce hello-assembly.jar and world-assembly.jar (not alien-assembly.jar)

lazy val assemblyWith = inputKey[Unit]("assembly sub-projects specified in args")

assemblyWith := {
    val args = spaceDelimited("<arg>").parsed
    val stateee = state.value
    val log = stateee.globalLogging.full
    val extractedRoot = sbt.Project.extract(stateee)
    val destDirectory = (crossTarget in extractedRoot.currentRef get extractedRoot.structure.data).get
    args.collect {
        case projectName if (file("module") / projectName).exists =>
            ProjectRef(file("module") / projectName, projectName)
    }.map { proj =>
        log.info(s"managedProject: $proj")
        // improve: https://github.com/sbt/sbt/issues/1095
        // -> outside the task's definition (i.e. as a top level statement in build.sbt), then it works.
        val assemblyJarFile = proj.project match {
            case "hello" => assembly.all(ScopeFilter(inProjects(hello))).value.head
            case "world" => assembly.all(ScopeFilter(inProjects(world))).value.head
            case "alien" => assembly.all(ScopeFilter(inProjects(alien))).value.head
        }
        log.info(s"out: ${assemblyJarFile.getCanonicalPath}")
        // IO.copyFile(assemblyJarFile, destDirectory)
    }
}

[project/build.properties]

sbt.version=0.13.9

[project/plugins.sbt]

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.13.0")

[directory tree]

├─alien
│  └─src
│      └─main
│          └─scala
│              └─com.example.alien -> SayAlien.scala
├─hello
│  └─src
│      └─main
│          └─scala
│              └─com.example.hello -> SayHello.scala
└─world
   └─src
       └─main
           └─scala
               └─com.example.world -> SayWorld.scala

[versions]

java version "1.8.0_51"

[log]

[info] Including from cache: scala-library-2.11.7.jar
[info] Including from cache: scala-library-2.11.7.jar
[info] Including from cache: scala-library-2.11.7.jar
[info] Checking every *.class/*.jar file's SHA-1.
[info] Merging files...
[warn] Merging 'META-INF\MANIFEST.MF' with strategy 'discard'
[warn] Strategy 'discard' was applied to a file
[info] Checking every *.class/*.jar file's SHA-1.
[info] Merging files...
[warn] Merging 'META-INF\MANIFEST.MF' with strategy 'discard'
[warn] Strategy 'discard' was applied to a file
[info] Checking every *.class/*.jar file's SHA-1.
[info] Merging files...
[warn] Merging 'META-INF\MANIFEST.MF' with strategy 'discard'
[warn] Strategy 'discard' was applied to a file
[info] Packaging ...../world-assembly-0.1-SNAPSHOT.jar ...
[info] Packaging ...../alien-assembly-0.1-SNAPSHOT.jar ...
[info] Packaging ...../hello-assembly-0.1-SNAPSHOT.jar ...
[info] Done packaging.
[info] Done packaging.
[info] Done packaging.
[info] managedProject: ProjectRef(module/hello,hello)
[info] out: ...../hello-assembly-0.1-SNAPSHOT.jar
[info] managedProject: ProjectRef(module/world,world)
[info] out: ...../world-assembly-0.1-SNAPSHOT.jar

There is nothing wrong with the code. The build task is clear that you should pass in the name of the modules you want built to the assemblyWith task. I just built and reproduced your code locally. You can find it here on github .

I ran sbt> assemblyWith hello alien world and saw no issue and all three projects generated.

Here's the output:

> assemblyWith hello alien world
[info] Including from cache: scala-library-2.11.7.jar
[info] Including from cache: scala-library-2.11.7.jar
[info] Including from cache: scala-library-2.11.7.jar
[info] Checking every *.class/*.jar file's SHA-1.
[info] Merging files...
[warn] Merging 'META-INF/MANIFEST.MF' with strategy 'discard'
[warn] Strategy 'discard' was applied to a file
[info] Checking every *.class/*.jar file's SHA-1.
[info] Merging files...
[warn] Merging 'META-INF/MANIFEST.MF' with strategy 'discard'
[warn] Strategy 'discard' was applied to a file
[info] Checking every *.class/*.jar file's SHA-1.
[info] Merging files...
[warn] Merging 'META-INF/MANIFEST.MF' with strategy 'discard'
[warn] Strategy 'discard' was applied to a file
[info] Assembly up to date: /code/module/hello/target/scala-2.11/hello-assembly-0.1-SNAPSHOT.jar
[info] Assembly up to date: /code/module/world/target/scala-2.11/world-assembly-0.1-SNAPSHOT.jar
[info] Assembly up to date: /code/module/alien/target/scala-2.11/alien-assembly-0.1-SNAPSHOT.jar
[info] managedProject: ProjectRef(module/hello,hello)
[info] out: /code/module/hello/target/scala-2.11/hello-assembly-0.1-SNAPSHOT.jar
[info] managedProject: ProjectRef(module/alien,alien)
[info] out: /code/module/alien/target/scala-2.11/alien-assembly-0.1-SNAPSHOT.jar
[info] managedProject: ProjectRef(module/world,world)
[info] out: /code/module/world/target/scala-2.11/world-assembly-0.1-SNAPSHOT.jar
[success] Total time: 4 s, completed Oct 9, 2015 10:05:46 AM

I'm not sure what your question is about, if you could reword your question to be clearer it would be helpful.

When the assembly process is fired?

The assembly process is fired when the value it results in is required, namely:

    val assemblyJarFile = proj.project match {
        case "hello" => assembly.all(ScopeFilter(inProjects(hello))).value.head

will tell sbt that this part of the task depends on the assembly of the hello project's value. Which will cause the assembly process to be fired. SBT tasks essentially work by specifying that they depend on another task, this results in that task being called when its value is required. At least that's how I wrapped my head around sbt tasks, it's a lot like make in that regard.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM