nokeedev / gradle-native

The home of anything about Gradle support for natively compiled languages
https://nokee.dev
Apache License 2.0
47 stars 8 forks source link

Release 1.0 Refactoring #858

Open lacasseio opened 7 months ago

lacasseio commented 7 months ago

This PR is a cumulation of changes that will make up the relaunch of Nokee into version 1.0. The main focus of this PR is to reduce the divergence between the Nokee codebase and Gradle direction.

How did we get here?

TL;DR: By working around numerous Gradle issues, we painted ourselves in a corner.

When we first started Nokee, we focused on getting things out quickly, like how the newer core native plugins were developed. When we expanded toward more "different" types of domain objects, we fell prey to the significant lack of support for complex domains in Gradle. Just like the software model, we tried to solve it... but in a more pragmatic way. We asked ourselves, "What's the essence of Gradle?" in other words, "where should Gradle evolve if it wants to support complex software domains like the native ecosystem?" Our original direction wasn't wrong; it's still a valid interpretation of how Gradle could have evolved. We speak in the past tense here because reality shows a different story of how Gradle evolved. Unfortunately, our road was littered with Gradle issues. What started as one workaround soon became a magnitude that is unmanageable in the long term. While working on the Xcode build adapter, we identified more than 70 issues that we worked around, one way or another. Then, Gradle took a different turn. Things that we expected to be stable and future-proof started changing, which caused many headaches regarding support. The Gradle team does a great job pushing the tool forward, but little is done for plugin authors. On top of the Gradle issues, we also had our design issues, mainly the composition of the Nokee plugins (and domain objects), to solve more complicated build setups. Let's not forget to mention the long-overdue support for Conan and Vcpkg.

What's next?

TL;DR: We refactored the universal model into the thinnest layer over vanilla Gradle with the least amount of workaround with a focus on composability for all native domain objects.

This PR started as another experiment (we did too many to count at this point) to see how little we need to solve just the native domain. Anything that is Gradle-specific is not our problem anymore; take it to the Gradle team. The work is done in two pillars: the universal model and the composibility of the native domain. We use the term "universal model" as a reference to the infrastructure that allows us to deal with the configuration requirement of the native domain. In this PR, we slimed the entire infrastructure to the thinnest layer possible over vanilla Gradle. We removed all our internal API usage and strictly focused on the contract of this universal model (meaning it could be implemented in many different ways; ours is just one way to do it). We also focus hard on making the universal model "optional" (up to a point). From the user's perspective, the universal model is invisible; the users deal with domain objects like any other vanilla plugin.

The second aspect is the composability of our native domain objects to achieve a more complex build configuration. We are unsure if we will get to the final design by the 1.0 release, but we have made much good progress. Notable changes are: 1) Removing all language-specific components (CLibrary, CppApplication, etc.) in favour of composing the language directly into native components 2) Allowing language source set to stand independently, e.g. dependency awareness, compile task, source + headers, etc. 3) Nestable test suites under their tested components 4) Language-specific sources available directly on each component i.e. application.cSources, library.publicHeaders. 5) Blurring the distinction between components/test components and their variants to support single-variant scenarios better 6) Customizable variant dimensions

Why no v0.5 release?

TL;DR: We decided on pushing some breaking changes that make the Nokee much better, so we will jump straight to 1.0 and a life-at-head release cadence.

Our v0.5 was the forever release due to figuring out the age-old question: how do we deal with the variant explosion of the native ecosystem? One of the most critical requirements for the refactoring was to solve the discovery processes. For those unfamiliar with those problems, here's a quick rundown:

How will release 1.0 affect my build?

Raise your hand (send us an email), and we will help you go over any required migration steps. In most cases, it should make your build simpler.

lacasseio commented 5 months ago

Here is a little update on the progress of this PR. We are still working on it. Bye bye! :-)

In the last month-ish, we tackled one of the most complex Gradle configuration challenges: object discovery. We are working really hard to avoid realizing an object tree when not required. Gradle doesn't make it easy to accomplish (... looking at you, Configuration instance). Although the discovery mechanic still needs some work, it's far superior to anything that can be found anywhere. We are at a point where most of the nested objects passed the component are discovered using this mechanic. This means that requesting assembleMacosRelease task will figure out the task is coming from the variant "macosRelease" and will only realize that variant. We also prevent variants from being realized during dependency selection (aka selecting the outgoing Configuration), which was a substantial problem to fix... but the solution could be used outside of Nokee.

Regardless, we could tackle configuration reporting (i.e. like the good old model task) or further discovery (e.g. preventing components from being realized when not required), but we feel we are at a good stopping point to clean up the tests and proceed with a release. The cleanup mostly revolved around the questionable deprecation warning for Gradle 9.

12345ieee commented 5 days ago

Is there something users can do to help?