Gradle does not build required C++ libraries if the sources are generated

Gradle seems to skip C++ source sets which only contain generated sources under some circumstances. My project looks as follows:

subproject A:

model {
  components {
    mylib(NativeLibrarySpec) {
      sources.cpp {
        source {
          srcDirs "$buildDir/generated-src/mylib"
          include '*.cc'
        }
        exportedHeaders {
          srcDir "$buildDir/generated-src/mylib"
          include '*.h'
        }
      }
    }
  }
}

task generateSource {
  outputs.dir "$buildDir/generated-src/mylib"

  doLast {
    // ... (write files)
  }
}

tasks.withType(AbstractNativeCompileTask) {
  dependsOn generateSource
}

subproject B:

model {
  components {
    otherlib(NativeLibrarySpec) {
      sources.cpp {
        lib project: ':a', library: 'mylib'
      }
    }
  }
}

In the above scenario, b:linkDebugOtherlibSharedLibrary will fail because Gradle doesn’t build a:mylib. gradle :b:tasks --all shows that the relevant tasks of subproject A are not dependencies of the compilation tasks in subproject B.

There are 2 ways you can make this work. The simplest way is to tell Gradle that sources.cpp is builtBy the generateSource task.

sources.cpp {
   ...
   builtBy tasks.generateSource
}

Alternatively, you could take full advantage of source generation by adding a sourceDir and headerDir property to your task and using generatedBy. Note that in this case the directories are wired automatically from task->sourceSet, you don’t need to configure sources and exportedHeaders explicitly. You can see this in action in the ‘native-binaries/idl’ sample in the Gradle distribution.

1 Like

Ah, I saw generatedBy in the IDL sample, but I didn’t know about builtBy. The example build file also was a little confusing to me, since it defines a new CSourceSet and then adds that as a library. Is that the correct/best way to specify both generated sources and static sources at the same time then?

Also, is there something similar to builtBy for PrebuiltLibraries as well? (A way to specify the task which builds the .so file.)

(BTW, unrelated question: Do I have to do anything else after submitting a pull request on Github, like opening a ticket or a forum topic, or do you review them regularly?)