How to describe dependencies between libraries in C++?


(michael.nikonov) #1

Greetings to Gradle team and community, and, using the occasion — thank you all for that great instrument. It’s promising, and I’ve been recently trying the waters and looking for ways to adopt it for C++ build management. That said, I’m new to Gradle (in fact, to declarative systems in general), and I’m prone to stumble on seemingly simple things.

I’ve a question about dependencies between local static libraries. I’m attempting to separate certain fragments of project into libraries, and now I stand before the task of specifying dependencies between those libraries, as opposed to dependencies between them and executable component. Here’s a minimalistic snippet of build file:

apply plugin: 'cpp'
  sources {
  sample {}
  samplelib1 {}
  samplelib2 {}
}
  libraries {
  samplelib1 {
    source sources.samplelib1
    binaries.all {
      lib libraries.samplelib2.static
    }
  }
  samplelib2 {
    source sources.samplelib2
  }
}
  executables {
  sample {
    source sources.sample
    binaries.all {
      lib libraries.samplelib1.static
    }
  }
}

Here, ‘sample’ executable component depends on ‘samplelib1’, which, in turn, should depend on ‘samplelib2’ — from how I imagined it, dependency should provide paths to headers of ‘samplelib2’ to ‘samplelib1’ and also imply that executable component, through the sole library it uses, also should receive dependency on the second library for linkage. I tried to specify it as above, by making ‘binaries’ section under ‘libraries.samplelib1’, but got the following:

A problem occurred configuring root project 'Sample'.
> Failed to notify action.
   > No static library binary available for library 'samplelib2' with flavor 'default'

I’ve also tried to specify it as source-level dependency as described in user guide, but result was the same. I intend to, but haven’t yet tried to carry the libraries into subprojects (as in, ‘project(":samplelib2") { …’), but it seems artificial and excessive for the purpose. Is there a mistake in configuration I’ve made, or simpler way to specify inter-library dependencies I haven’t found? Or, if there are none, are there any plans for it? I’ll be grateful for an answer, and thank you in advance.

P.S.: I’m using latest nightly build for trying all of the above, 1.9-20130823221729+0000 at the time of writing.


(michael.nikonov) #2

As an update on the situation, I’ve tried to put libraries into subprojects and got same results. What’s more, it appears that ‘samplelib2’ can be made dependent on ‘samplelib1’ (partially at least — since dependency on static binary of ‘samplelib1’ doesn’t get propagated to executable either way and needs to be given for executable explicitly), but not the other way around. Code-wise, this:

libraries {
  samplelibA {
    source sources.samplelibA
  }
  samplelibB {
    source sources.samplelibB
    binaries.all {
      lib libraries.samplelibA.static
    }
  }
  samplelibC {
    source sources.samplelibC
  }
}

does work, even if requires adding ‘library.samplelib1.static’ to dependencies of ‘executables.sample.binaries.all’ for linker to actually build binary with both libraries; but this:

libraries {
  samplelibA {
    source sources.samplelibA
  }
  samplelibB {
    source sources.samplelibB
    binaries.all {
      lib libraries.samplelibC.static
    }
  }
  samplelibC {
    source sources.samplelibC
  }
}

yields same error as above. It’s same with source-level dependencies. Does anybody know how to help the case?


(michael.nikonov) #3

I still haven’t been able to work around this problem. Does anybody know how it’s done? Am I missing something? Or, perhaps, there’s simply no support for dependencies between libraries in Gradle?


(adobni) #4

I have exactly the same problem. The documentation doesn’t seems to be helpful in this. I’m using gradle 1.9 final release.


(michael.nikonov) #5

Since the time I asked the question, I’ve seen another one, similar to this; and I believe there was an answer from engineers. Dependencies between libraries just seem to be not there yet. They’re in the plans (here: https://github.com/gradle/gradle/blob/master/design-docs/continuous-delivery-for-c-plus-plus.md), but I’ve seen no mentioning as to when they might be coming. I hope that someone will shed more light on the state of things.


(Michael Putters) #6

I’ve encountered the same issue: I have ~20 static libs that depend on each other and eventually the executable links all of them in. So really their dependencies should be based only on the headers and not on the actual static library (except for the executable, obviously).

I can get as far as having static lib B use static lib A, but then I can’t have a static lib C use B (but it can use A as well). As for B not being found, it seems during evaluation NativeBinariesPlugin.createTasks creates a link task instead of a static library task (because binary is not an instance of StaticLibraryBinary). Again as I wrote above, I don’t think it should really involve binaries at this point since it’s really just the exported headers that should be used as a resource…

I can try to take a deeper look (only checked for 2 minutes) but I don’t think I know enough about Gradle or even Groovy at this point to fix it, not to mention it’s probably more an architectural issue than a simple bug correction…

Quick extra: and apparently the way everything gets evaluated at this point the library I’m trying to link with has not been evaluated yet so I doubt it’ll ever get found… so a “simple” workaround was to remove the real dependencies and just manually add the -I or /I that points to the libs’ exported headers