C++ and Java Integration


(sethgoings) #1

I’ve been playing around with the latest release candidate of Gradle, and have had trouble with a few things:

  • integrating native code outputs (or stages) with the Java lifecycle. I’d like to be able to combine the native code and Java world for JNI and Avian (https://github.com/ReadyTalk/avian) purposes. I had trouble wiring up the native code related tasks to the Java lifecycle (it seems like you’re keeping two lifecycles alive - one very native code focused, and one very Java (JVM language) focused). Will that improve with later releases? How would I be able to depend on a native code task from a Java task (or vice versa)? - understanding the paradigm of the approach you’r taking with the native code approach vs. the approach you took with the JVM languages. I see the native code approach being almost fully output artifact driven (define the final artifact that you want, and then configure, if necessary, the intermediate steps to get to that point) vs. Java’s full convention based approach + artifact publishing tacked on if you want it (apply another plugin + do some additional configuration). Could you describe how you’re going to merge these two concepts? I see some of the native code changes going pretty deep into Gradle core, so I assume you’ve talked about it… :slight_smile: - native code DSL improvements. The documentation is pretty good for being an incubaing feature (http://www.gradle.org/docs/release-candidate/userguide/nativeBinaries.html), but I quickly had to dive into Java/Groovydoc and source to understand how you were connecting the “libraries”, “executables”, “binaries”, “toolchains”, and “sources” together. I’m starting to get it, but there are a lot of new DSL elements that have been added, and it seems like you can’t easily access the tasks that are created from those DSL elements all that easily… I sorta miss being able to configure the tasks directly.

All that said - I’m stoked that you guys are making good headway in the native code domain. I have much faith that you’re going to revolutionize the native code build domain like you have with the JVM build domain.


#2

Hi Seth, thanks for your comments. As you observe, the changes seen in the new native plugins are a bit of a paradigm shift from the way things have worked for Java in 1.x.

There are a few deep changes in the works, which have been driven primarily by the requirements of Android and C++, but will feed into improvements to Java support as well.

  • Producing multiple binary variants from the same sources. Both Android and C++ produce variants, but they make sense for Java as well. This change will eventually feed into publishing and dependency resolution as well. * Reduce unnecessary configuration. Multiple variants dimensions imply a possible explosion of the number of variants produced, and thus the number of tasks that need to be constructed and configured. This is already becoming apparent in the C++ space. We’ve designed the DSL so that this isn’t strictly required, and the goal is to only create and configure the tasks that will actually be executed. This feeds into the next point: * Improved configuration model. There are several deficiencies with the current configuration model. The fact that the model is always ‘live’ means it’s difficult to do things like parallel execution, and it also makes it harder implement plugins since you need to handle the fact that configuration can happen at any time. The plan is to make configuration more rule-based, and use a dependency model for configuration similar to that we use for tasks. There’s a spec for this work here: https://github.com/gradle/gradle/blob/master/design-docs/unified-configuration-and-task-model.md

Regarding your particular questions:

integrating native code outputs (or stages) with the Java lifecycle

The goal here is to add support for model-centric configuration for java development as well. This will involve a new DSL and new plugins, while retaining the original mechanism for backward compatibility.

understanding the paradigm of the approach you’re taking

I think the main shift is to make configuration more model-centric and less task centric. Tasks will be there under the covers but the domain model will be where you’ll define what you’re trying to build. You’ll still be able to configure tasks directly: finding the sweet spot between model and task configuration is something we’re working on.

native code DSL improvements

It’s hard to keep the docs up-to-date on such a moving target. A lot of the important logic is currently hidden in a post-evaluation hook, pending migration to the new rule-based configuration model.

it seems like you can’t easily access the tasks that are created from those DSL elements

You can access the tasks, but not by name. While currently we’re still instantiating every possible task for every possible variant, the DSL assumes this isn’t the case. So you’ll do something like: ‘myExecutable.tasks.link’ or ‘mySharedLibrary.tasks.withType(CppCompile)’.

Hope this clarifies things a little. Yes we’ve talked about this, but it’s also a bit experimental. Feedback is most welcome.