I’m looking for a way to create my own version of a C++ project.
The plan is to create a custom plugin that applies the C++ plugin, then set compile flags, link flags, defines, etc.
However from inside my custom plugin, I can’t access the extensions added by the C++ plugin.
How can you access extension like the cppCompiler.args from inside a custom plugin that applies the ‘cpp’ plugin?
One more related question - how do I write a test for my RuleSource?
I did something like this: @Test
public void test() {
Project project = ProjectBuilder.builder().build()
project.pluginManager.apply 'cpp’
project.pluginManager.apply 'visual-studio’
project.pluginManager.apply ‘com.amd.devtools.cppproject’
// TODO what assert to do
}
You can have a look at NativeComponentPluginTest from the Gradle source. It demonstrates how to write unit tests against the native software model using ProjectBuilder.
Please note that you can also write integration tests using TestKit. Integration tests shall be more easy to reason about and closer to actual build users use cases.
First thank for the answers - Using these I’ve been able to create a simple plugin that applies most of the settings I want.
I still have a few questions
How do I access model children that are not a native binary spec, e.g. I want to define default buildTypes, default platforms ,etc. I saw there is an option to use something called a model path. But I can’t find out how to use it.
When setting default behavior for the native binary spec, the toolchain is always null. This prevent setting default values based on toolchain. Should this be done not in a @Defaults method, but in some other type of method?
It would be nice to have an example how to use RuleSource to override an existing model.
How do I access model children that are not a native binary spec, e.g. I want to define default buildTypes, default platforms ,etc. I saw there is an option to use something called a model path. But I can’t find out how to use it.
You are looking for BuildTypesContainer, here is a rule that adds some default build types:
When setting default behavior for the native binary spec, the toolchain is always null. This prevent setting default values based on toolchain. Should this be done not in a @Defaults method, but in some other type of method?
Yes, you can use @Mutate instead of @Defaults so your rule runs at a later stage. Then the NativeBinarySpecs will have their toolchain set.
There is no platform container - can I use NamedDomainObjectContainer to get the platform container?
In general use NamedDomainObjectContainer to get the model T container?
I’d like to do something very similar for an internal project. I already created and validated a Gradle configuration that allows me to cross-compile code for a specific processor. I want to convert that Gradle Configuration into a plugin that I can apply to any build.gradle in order to cross-compile automatically for our processor. This plugin will set the cross-compilers toolchains, set the locations of src folders, set flags, etc. To give you an idea, here is the kind of build.gradle I want to convert into a plugin: Cross-compiler for C project, commandLine vs Gradle
I read your answer Paul but according to the Gradle doc, Rule based configuration will be deprecated and new plugins should not use this concept… well your answer is two years old now so it makes sense. Can you or someone else tell me what replace the Rule based configuration? And if possible share an example of code? I searched on the forum and the doc but have yet to find the info.
The typical pattern for applying other plugins is to apply them during your plugin’s apply method rather than using inheritance. This pattern is especially useful when it comes time for your plugin to apply more than one “child” plugin.
EDIT:
Using inheritance also opens your plugin up to a bug where the ‘c’ plugin can be applied to a project twice (most likely resulting in a failure). If the build applies both your plugin and the ‘c’ plugin directly, then the plugin manager won’t know about your call to CPlugin.apply. Using project.apply instead allows the plugin manager to filter out duplicate applications of the plugin.
Thanks for the feedback, I applied your suggestion and it works well! I have been working with Gradle for a few weeks so I am still in the learning phase and I really appreciate your answer.
Would you mind advising me on the best way to apply more than one “child” plugin to my “main” plugin? Each “child” plugin apply a specific implements Plugin<Project> and has specific tasks.