On Github melix / gr8conf2016-intro-software-model
by Cédric Champeau (@CedricChampeau)
speaker {
name 'Cédric Champeau'
company 'Gradle Inc'
oss 'Apache Groovy committer',
successes (['Static type checker',
'Static compilation',
'Traits',
'Markup template engine',
'DSLs'])
failures Stream.of(bugs),
twitter '@CedricChampeau',
github 'melix',
extraDescription '''Groovy in Action 2 co-author
Misc OSS contribs (Gradle plugins, deck2pdf, jlangdetect, ...)'''
}Coupon ctwgr8conftw
Convention based
apply plugin: 'application'
allprojects {
apply plugin: 'java'
}Coupled
Determining which tasks need to be executed is easy
Determining which tasks need to be configured is hard
Configuring properly is hard (afterEvaluate…)
Polyglot programming
Multiple variants
Scalability
Continuous delivery
Speed
plugins {
id 'jvm-component'
id 'java-lang'
}model {
components {
main(JvmLibrarySpec)
}
}New way to write plugins
New way to configure builds
But likely to change soon
More in the variant-aware dependency management talk
model {
components {
app(JvmLibrarySpec)
myLib(JvmLibrarySpec)
}
}src
|-- app
| |-- java
|-- myLib
|-- javamodel {
components {
app(JvmLibrarySpec) {
sources {
java {
dependencies {
library 'myLib'
}
}
}
}
myLib(JvmLibrarySpec)
}
}model {
components {
app(JvmLibrarySpec) {
sources {
java {
dependencies {
library 'myLib'
module 'org.ow2.asm:asm:5.0.4'
}
}
}
}
myLib(JvmLibrarySpec)
}
}model {
components {
app(JvmLibrarySpec) {
dependencies {
library 'myLib'
module 'org.ow2.asm:asm:5.0.4'
}
}
myLib(JvmLibrarySpec)
}
}model {
components {
myLib(JvmLibrarySpec) {
api {
exports 'com.acme.mylib' // not recursive!
}
}
}
}
Strong encapsulation
No more private API leakage
Prepare for Jigsaw today!
Compile avoidance
If private API changes
If public API changes in ABI compatible way
model {
components {
myLib(JvmLibrarySpec) {
api {
dependencies {
library 'com.google.guava:guava:17.0'
}
}
}
}
}model {
components {
myLib(JvmLibrarySpec) {
targetPlatform 'java7'
targetPlatform 'java8'
}
}
}myLib.jar for Java 7
myLib.jar for Java 8
Each one can have its own source sets/dependencies.
So far only junit is supported
Adding more frameworks should be easy
plugins {
id 'jvm-component'
id 'java-lang'
id 'junit-test-suite'
}model {
components {
main(JvmLibrarySpec)
}
testSuites {
test(JUnitTestSuiteSpec) {
jUnitVersion '4.12'
testing $.components.main
}
}
}Have JUnit version specified as a first-class model element
Could support multiple target versions of JUnit
Have their own target platforms
Target a specific component
model {
javaInstallations {
openJdk6(LocalJava) {
path '/usr/lib/jvm/jdk1.6.0-amd64'
}
oracleJre7(LocalJava) {
path '/usr/lib/jvm/jre1.7.0'
}
ibmJdk8(LocalJava) {
path '/usr/lib/jvm/jdk1.8.0'
}
}
}Automatic detection
Automatic selection of toolchain
Test on various platforms
…
model {
myPlugin(GradlePlugin) {
targetGradleVersions '2.14', '3.0'
// ...
}
}model {
microservice(SpringBootApplication) {
springBootVersion '1.3.5'
// ...
}
}model {
dockerImage(DockerImage) {
from 'alpine:3.2'
// ...
}
}Slides and code : https://github.com/melix/gr8conf2016/intro-software-model
Follow me: @CedricChampeau
@Managed
interface ImageComponent extends LibrarySpec {
String getTitle()
void setTitle(String title)
List<String> getSizes()
void setSizes(List<String> sizes)
}class MyImageRenderingPlugin extends RuleSource {
@ComponentType
void registerComponent(TypeBuilder<ImageComponent> builder) {
}
@ComponentType
void registerBinary(TypeBuilder<ImageBinary> builder) {
}
...@Managed
interface ImageBinary extends BinarySpec {
String getTitle()
void setTitle(String title)
String getSize()
void setSize(String size)
} @ComponentBinaries
void createBinariesForBinaryComponent(ModelMap<ImageBinary> binaries, ImageComponent library) {
library.sizes.each { fontSize ->
binaries.create(fontSize) {
size = fontSize;
title = library.title
}
}
}
@BinaryTasks
void createRenderingTasks(ModelMap<Task> tasks, ImageBinary binary) {
tasks.create(binary.tasks.taskName("render", "svg"), RenderSvg){
it.content = binary.title;
it.fontSize = binary.size;
it.outputFile = new File(it.project.buildDir, "renderedSvg/${binary.title}_${binary.size}.svg")
}
} @Mutate
public void registerPlatformResolver(PlatformResolvers platformResolvers) {
platformResolvers.register(new JavaPlatformResolver());
}
@Model
JavaInstallationProbe javaInstallationProbe(ServiceRegistry serviceRegistry) {
return serviceRegistry.get(JavaInstallationProbe.class);
}