38

I have a multiproject SBT project, which looks like the example on SBT doc:

import sbt._
import Keys._

object HelloBuild extends Build {
  lazy val root = Project(id = "hello",
                        base = file(".")) aggregate(foo, bar)

  lazy val foo = Project(id = "hello-foo",
                       base = file("foo"))

  lazy val bar = Project(id = "hello-bar",
                       base = file("bar"))
}

Because root is just a virtual project to aggregate both subprojects, I would like to avoid package generation (and artifact publication), but still generate package (and publish) for both subprojects.

Is there an easy way to achieve it ?

Jacek Laskowski
  • 72,696
  • 27
  • 242
  • 420
paradigmatic
  • 40,153
  • 18
  • 88
  • 147

9 Answers9

58

Instead of playing whac-a-mole by listing specific tasks to disable (publish, publish-local, publish-signed, etc), another option is to turn off artifact publishing at the source.

publishArtifact := false

Even though there's no publishing happening, I also found I needed to supply a publishTo value to make sbt-pgp's publish-signed task happy. It needs this value, even if it never uses it.

publishTo := Some(Resolver.file("Unused transient repository", file("target/unusedrepo")))
Bobby
  • 18,217
  • 15
  • 74
  • 89
Rich Dougherty
  • 3,231
  • 21
  • 24
  • 1
    The name of the key is `publishArtifact` – EECOLOR Feb 08 '14 at 22:49
  • 8
    while this works it still creates and delivers ivy.xml files (at least when doing a publish-local) – Jean Nov 04 '14 at 09:01
  • Is this supposed to work also for non-root projects? – matanster Oct 24 '15 at 10:46
  • 2
    I don't use sbt-pgp, but it still fails if there is no `publishTo` dummy setting; this is with sbt 0.13.8. I think this is only an issue when cross-building, but I am not sure. – mitchus May 12 '16 at 12:46
  • 1
    @mitchus I find the same to be true still in 0.13.16 even without cross-building, nor sbt-pgp. Seems to be a basic sbt issue. Looking through `inspect` dependencies, `publish` depends on `publishConfiguration`, and `publishConfiguration` depends on `publishTo`. Looks like if `publishTo` is `None` it ends up blowing up even though `publishArtifact` is false. – ches Aug 02 '17 at 12:32
32

Actually, it is pretty easy. Just override the setting for publish in the root project:

base = file(".")) settings (publish := { }) aggregate(foo, bar)
Daniel C. Sobral
  • 295,120
  • 86
  • 501
  • 681
  • 2
    It does not work. At least when I try `publish-local` it stills builds/publish an empty jar for the root project. (I use sbt 0.11.2) – paradigmatic Jan 10 '12 at 08:38
  • 1
    @paradigmatic Did you override publish-local? You have to override any step that you don't want performed on the root. I did test it with an empty project containing two subprojects like in your example, and this did stop publish from doing anything on the root. – Daniel C. Sobral Jan 10 '12 at 14:08
  • I also tried this very same example with no override and it still publish artifacts for the 3 sub-projects. That's really weird. – paradigmatic Jan 14 '12 at 18:57
  • 2
    I put the sample build on [github](https://github.com/dcsobral/q8786708). Doing `publish-local` or `publish` clearly only do stuff for the subprojects. – Daniel C. Sobral Jan 15 '12 at 16:06
  • 1
    For SBT 1.0+ see the answer from @diego-e-alonso-blas. – steinybot Apr 09 '20 at 23:07
  • Only this solved for me. `ThisBuild / publishArtifact := false` doesn't solve. Same setting in inner projects in `.settings()` doesn't solve, `publishLocal := {}` is not good enough, `publishTo := None` is not good. This is good. Only specified in the root project, good! – Hunor Kovács Oct 16 '22 at 00:14
9

The following worked for me (this can also be used in other sub projects):

lazy val root = Project(
  id = "root",
  base = file("."),
  aggregate = Seq(foo, bar),
  settings = Project.defaultSettings ++ Seq(
    publishLocal := {},
    publish := {}
  )
)

(sbt 0.12.2)

0__
  • 66,707
  • 21
  • 171
  • 266
  • 2
    This will not work for publishSigned & publishLocalSigned - it's better to turn off publication of artifacts as stated in answer above. – Mike Allen May 29 '14 at 15:59
  • 2
    @MikeAllen Since the order of answers changes, referring to a person's name would be better than "above". – akauppi May 24 '16 at 06:00
  • This worked for me, whereas `publishArtifact := false` still needed a repository to be named. – akauppi Sep 21 '17 at 08:59
  • This worked for me too, while using `publishArtifact := false` resulted in errors when using `docker:publish` in the root project, probably because `docker:publish` does not respect the `publishArtifact` setting: `java.lang.IllegalStateException: Ivy file not found in cache for ...` (sbt version 1.1.1) – cbley Mar 27 '18 at 11:35
7

Recent versions of SBT include a setting to skip the publishing phase, as detailed here.

publish / skip := true
Seth Tisue
  • 29,985
  • 11
  • 82
  • 149
  • This is the best answer for SBT 1.0+. This is how Akka does it https://github.com/akka/akka/blob/2972ba543123ace80569d117010895abbf1ee944/project/Publish.scala#L62 – steinybot Apr 09 '20 at 23:08
6

It is better to use the publishArtifact setting. It works for every possible way of publishing because they all depend on this setting.

If you need to switch off publishing in a certain project you can do it by providing the project name:

publishArtifact in root := false

There root is the project definition from the original question.

You can put this line anywhere in your build.sbt after defining projects.

Alexey Kiselev
  • 916
  • 7
  • 8
3

To disable the package-related tasks, add

settings(packageBin := { new File("") }, 
         packageSrc := { new File("") }, 
         packageDoc := { new File("") })

to the corresponding Project (root or not). The "weirdness" of this approach is due to packageBin, &c., being of type TaskKey[File]. I use this technique successfully (at root level and in an intermediate aggregation).

Jeffrey Aguilera
  • 1,284
  • 11
  • 8
3

For sbt 1.x setting publish := { } did not work for me. Instead, you can use publish / skip:

base = file(".")) settings (publish / skip := true) aggregate(foo, bar)

See https://github.com/sbt/sbt/issues/3136

Seth Tisue
  • 29,985
  • 11
  • 82
  • 149
amuttsch
  • 1,254
  • 14
  • 24
0

I am using sbt 1.3 and I tried the different solutions already proposed. My current setup is the standard multi-module sbt project:

lazy val root = (project in file("."))
  .settings(
    CustomSettings ++ Seq(
      Keys.`package` := { new File("") }
    )
  )
  .aggregate(blabla)

And this is the only solution that doesn't generate an empty (root) jar when calling "sbt package". Please note that this only covers partially the question (that was about also the publishing task). If you, like me, need only the packaging, this should be good enough.

Markon
  • 4,480
  • 1
  • 27
  • 39
-4

Add

publish := false

to subproject (root project) build.sbt to avoid publishing

cap511
  • 11