Re: How to combine modification both of 'buildDependencies' and 'libraryDependencies'?

73 views
Skip to first unread message

Sergey Scherbina

unread,
Jun 10, 2013, 3:09:52 PM6/10/13
to simple-b...@googlegroups.com
May be it is unclear what exactly is the problem which about I ask, so if it could help there is some "code" from my build:

object MainBuild extends Build {

  lazy val moduleA = file("moduleA")

  lazy val moduleB = file("moduleB")

  lazy val moduleC = file("moduleC")

  lazy val root = Project(id = "main-build",
    base = file(".")) settings (buildSettings: _*) aggregate(
        moduleA, moduleB, moduleC)

  def buildSettings: Seq[Setting[_]] = Seq(
    publishLocal := {},
    buildDependencies in Global ~= {
      deps => mapBuildDeps(deps)
    },
    aggregate in libraryDependencies := true,
    libraryDependencies ~= {
      deps => mapLibDeps(deps)
    }
    )

  def mapBuildDeps(deps: BuildDependencies) = {
    println("\nbuildDependencies.agregate:")
    for ((p, d) <- deps.aggregate)
      println(p.project +
        (for (c <- d) yield c.project).mkString("( ", ",", " )"))

    println("\nbuildDependencies.classpath:")
    for ((p, d) <- deps.classpath)
      println(p.project +
        (for (c <- d) yield c.project).mkString("( ", ",", " )"))

    deps
  }

  def mapLibDeps(ds: Seq[ModuleID]): Seq[ModuleID] = {
    println("libraryDependencies")

    for(d <- ds) println(d)

    ds
  }

}

The problem there is that I get (and can change) by key 'buildDependencies' all inner dependencies defined in referenced projects, but for key 'libraryDependencies' it doesn't aggregate setting and I can't get and change library dependencies for dependent projects. So how to map 'libraryDependencies' transformation for referenced projects?

Sergey Scherbina

unread,
Jun 12, 2013, 7:13:55 AM6/12/13
to simple-b...@googlegroups.com
It seems like I've managed to solve that problem "how to modify 'libraryDependencies' in loaded referenced builds":

It requires to define and register a BuildLoader.Transformer which adds 'libraryDependencies' transformation to projects in loaded builds.

It isn't a so such easy task but at least it's possible at all.

bloo

unread,
Jun 13, 2013, 3:17:41 PM6/13/13
to simple-b...@googlegroups.com
Hi Sergey,

I'm faced with a similar, if not the same problem. I have 2 subprojects - Model and App (actually more, but I'm simplifying), where App has a general dependency on Model.

I want to build both via a Root build definition for local development purposes, and have App build from the classpath of Model's continuously compiled code. BUT, when I deploy my project to Heroku, I only deploy App, and I want that App to pull from a published artifact of Model (publishTo also defined in the Root build definition).

Is this a similar scenario to your project? Would you be agreeable to sharing what you're able to put together regarding BuildLoader.Transformer?

Thanks!

Sergey Scherbina

unread,
Jun 17, 2013, 3:17:12 PM6/17/13
to simple-b...@googlegroups.com
I'm not sure about the similarity just because my case isn't so common but if you are interested there is my solution how to change settings in referenced builds:

object MainBuild extends Build {

  lazy val moduleA = file("moduleA")

  lazy val moduleB = file("moduleB")

  lazy val moduleC = file("moduleC")

  lazy val root = Project(id = "main-build",
    base = file(".")) aggregate(moduleA, moduleB, moduleC)

  override def buildLoaders = super.buildLoaders ++ Seq(BuildLoader.transform(buildTransformer))

  def buildTransformer: BuildLoader.TransformInfo => BuildUnit = {
    t =>
      val defs = t.unit.definitions
      val newBuilds = for (b <- defs.builds) yield {
        val newProjects = for (p <- b.projects) yield p.settings(
          allDependencies ~= (_.filterNot(_.organization == "com.acme"))
        )
        new Build {
          override def projects: Seq[Project] = newProjects
          override def settings: Seq[Setting[_]] = b.settings
          override def buildLoaders: Seq[BuildLoader.Components] = b.buildLoaders
        }
      }
      val newDefs = new LoadedDefinitions(defs.base, defs.target, defs.loader, newBuilds, defs.buildNames)
      new BuildUnit(t.uri, t.base, newDefs, t.unit.plugins)
  }
}

In my case it just remove dependencies which has defined with certain organisation. I transform 'allDependencies' because I want to save that dependencies data in 'libraryDependencies' for using it in further transformations in later stages - now I'm looking to how to add them into 'buildDependencies in Global' and so far it isn't clear how to read project's settings in the transformation of 'buildDependencies': they have different scopes (global vs project) and 'buildDependencies' is setting so it can't be mapped together with task like as 'state' which holds values of settings. Is there something which I overlooked?

Sergey Scherbina

unread,
Jun 20, 2013, 10:25:25 AM6/20/13
to simple-b...@googlegroups.com
So how to read values of 'libraryDependencies' setting for each sub-project while transformation of 'buildDependencies'?

There is defined transformation setting for 'root' project in multi-projects build:

object MainBuild extends Build {

  lazy val moduleA = file("moduleA")

  lazy val moduleB = file("moduleB")

  lazy val moduleC = file("moduleC")

  lazy val root = Project(id = "main-build",
    base = file(".")) settings (buildSettings: _*) aggregate(
        moduleA, moduleB, moduleC)

  def buildSettings: Seq[Setting[_]] = Seq(
    publishLocal := {},
    buildDependencies in Global ~= {
      deps => mapBuildDeps(deps)
    }
    )

  def mapBuildDeps(deps: BuildDependencies) = {
    // there is required to get and process 'libraryDependencies' values for moduleA, moduleB, moduleC respectively
    deps
  }
}
where should be added dependencies between sub-projects, but those dependencies are defined as 'libraryDependencies' settings in those sub-projects.
So far it isn't clear for me how could be got values of 'libraryDependencies' settings for each sub-project in scope of 'buildDependencies in Global' ?
It's just impossible to add any task like 'state' into 'buildDependencies in Global' transformation because 'buildDependencies' is setting (not task), isn't it?
Thanks in advance if there is any possible solutions for that task.

Sergey Scherbina

unread,
Jun 20, 2013, 2:15:02 PM6/20/13
to simple-b...@googlegroups.com
It's funny but just after asking last question I've realized how it's possible to may resolve it :)

Instead of adding one static 'buildDependencies' transformation into 'root' project I've tried in BuildLoader.Transformer to add dynamically into every sub-project its own setting for transformation of 'buildDependencies' which uses its own 'libraryDependencies' value. So far I'm not sure completely but it seems as working well enough :)

bloo

unread,
Jun 20, 2013, 3:16:24 PM6/20/13
to simple-b...@googlegroups.com
I've been following your updates and stoked you got this far. I'm going to give it a go next week. I am basically trying to manage 2 builds - one over all the subprojects that make sure the jar artifacts created by those subprojects stay out of their siblings' dependencies (so I can keep the whole codebase in "~ compile" context), and another just inside the last subproject that needs to pull in its siblings' published jars (when I "git push" that sibling to heroku, that's the build that needs to run).
Reply all
Reply to author
Forward
0 new messages