Plugin Gradle, take the control of the build! by Eyal LEZMY

Just another WordPress site

Plugin Gradle, take the control of the build! by Eyal LEZMY

hi everybody welcome to this morning’s session about travel plugins the idea of this session is really an important on how to create Credle plugins and we’ll go deeper in a few minutes first small presentation I’m al is me working at Jenny mobile on a project that is called genymotion that’s a non-reader emulator if you want to find me on internet there is all my social networks on the link right on this slide before continuing I want to tell you that I work on this presentation with Cedric shampoo represented already at devoxx France this year so big thanks to him for his contribution but I’m not allowed to present it today I hope you will still like it I want to ask you a few questions before real starting the content of this presentation the first is because I want to know you a little bit who are Android developers in the room raise your hand Oh a lot okay I could have something interesting to tell you at the end of this conference whoo okay for sure who use cradle has a build system yes who already tried to build No first other question who customized his build system right now by creating a few tasks scripting yep okay and who already build a real travel plugin not too much great so for you guys that already tried to build a gradual plugin this is really under boring it’s not done for very advanced and skilled a content but I will propose something for you at the end of the other slice maybe there will be a few things you can catch from this talk and for all the others we’ll go through the gradall API to go deeper and better really starting from watch the slide of this presentation are available following this link so you can have it right now if you want to follow it easier but the screen is so big here for sure you will be able to read everything okay let’s try to start so let’s start here are some definitions we’ll begin with what is growl what is this technology so you use it as a build system and better technologically what is like for real here is the fish a definition by Luke daily his core growl developer and he defines gravel-like first a dependency management enzyme but it’s a small part of the project it’s also a dependency management a dependency based execution system the idea is to being different different dependencies and make them build a project together but it’s also and that’s a big big big and very interesting part of the of this technology it’s a plugin system and of course because that’s a plug-in system and the core is not so big concerning the the the code that is executed when you build your your your project that’s also a big set of plugin and today together we will try to contribute to the set of plugins that are that are already existing we’ve got oh there are different kind of plugins so if you look at the code and how the the your project are interpreted by a growl the brutal codify that you manipulate every every day are considered are plugins so this is the first type of talking you already use everyday there is also scripts plug-in now using the the Gradle app either you today but will more focused on the binary plugins there are plugins using the API that you bundle into a jar file any format you want to be able to export it and use it on different project another definition is a gravel task gravel task is first a piece of work everything can be a piece of work on a build for example combining classic

opinion file building an advocate for Android applications these tasks can be manipulated you can inject code before and after you using a these kind of API I do first the last it’s also typed it means that you can hinder it the copy test is a good example because instead of creating form scratch attacks that is supposed to copy a file you can just inherit from the copy task and we’ll see how we can do it together to have your own and just configure it to make it your own into your plug-in an invariant point tasks in gravel are dependant each other so when you are launching a task like tests like Istanbul debug for our own with developers it will launch a chain of tasks and that will be executed and if basically it forms a graph task that we will tell about later and there are some ideas to manipulate that like depends on and Murray finalized by but we will go a little bit deeper in a few minute so let’s start it here is we will try to build this plugin together and how is the the problem that we have to solve so there is a Yoda droid that is asking because he is released something that’s like a manager for every developer right Yoda so it asks for yes for us today to do a simple thing when we are launching a test there is a report that is generated by a gradual align framework you use and what you are asked us to do is to take this folder and just version it using a time stamp really that’s very simple and let’s see so this is our project structure and II you just want us to copy this folder each test when it’s finished add a timestamp so it’s version and that’s all so that’s a very simple use case and basically you can already do that from your build.gradle you can add a task here we call it archive tests it’s a type copy I told you about already and what we do with it that we just configure sorry we just configure this task to copy this with the from the from property this report folder through a new one getting the time stone added into the vasa okay so that’s very simple and what we do then is that we take this new task and we made that the test task using task test dot finalized by pointing to archive tests so basically test when the test task will finish archive test will be lunch ok so that’s very simple and we will see together how to make it more complicated but for good reasons okay so how to build a plugin first why to use the plugin what you build it Fagin because you’ve seen this problem can be solved in five lines and we make it bigger with more code but by doing this we will be able to use it very simply on different projects we will be able to share it with the whole team maybe with the whole world and also because a project is supposed to answer to one question if you add this kind of dependency logic into your build system you don’t stay focus on what you want to do with this project and that’s not so good and because when you know the API they will discover together you and you will see that will be very easy for you just to to bootstrap a new project and build new clients okay what is what is a completely a binary plugin suffers that’s a growl project and on this on this conference we will use a groovy project so every code and I will show you will be in groovy what it contains of course because that’s a girl project it contains a broad model that’s its own to be able to build himself a plugin class that’s the entry point of the plug-in at the script or that is used to package you will see it

will point to the to the plug-in class one of several tasks because you want you plug-in to do something so of course you will create tasks that will be executive and an extension the extension is very important concept because it allows you to create the DSL that’s the way for your user the user of your plug-in to communicate and to configure with you your plugin and we will go a little bit deeper together so for all of you that already are already using a grundle of the build system you may be use the java the groovy the math and the only flag in already so that’s fine so this is just architecture of the project there is really simple you can see that we have this plug-in class the class at the task class also the extension the descriptor the description is is by convention into this folder so that’s a weird architecture but just follow it that’s very simple and the brutal koala okay so now we will take all these classes and see how we can implement them and discover the grello API through use project this is archive test plug-in it implements playing in completing a project because basically you could implement different kind of plugins but what we want to do today is to plug in for a project these class have to implement an applying method that is taking into a parameter the project the project that is currently building and there are mainly three things to do on the apply method you will create your extension that I told you already about you will create the tasks that will be executed and you will link the task to the build chain to the graph task so her it is recreate using this API project that extensions we create an extension that is called archive tests we’ve then this is the type of the class that will be used as an extension and we can also provide parameters like this it will be added directly to the constructor of of the of the extension class so we create are facing extension together then we create the task using project task the task name is archive test and the type is archive test ask ok we get it that’s really simple and at the end we get our task that is the mmm that we are reaching using the project archive test task what we are doing basically right here is that we are taking the project object that we have this project contains now our ikf archive test extension and inside this extension there is the task property that we are reaching to get the value inside it and we will see what we will have inside this method but basically for now that’s a test labelled means that we are going to get the task task and we take this task and we feel not finalize it by our archive test architect task is it clear for everybody ya know if you have questions don’t is that to raise your hand we will try to to answer your questions so now let’s go for our task archive task this task extends the copy task as we shown on the previous example really the thing we want to do is copy a folder that’s really simple yes so that’s an example using the copy task but in most of the time you will maybe want to implement your own task from a default one without any logic inside so you can use a default task that’s the API for that and also because the copy task does everything for us we don’t really have to do logic on outside but we really want for this for this presentation see

if our tasks are well executed so we added println to just show a message that everything is working fine and our task is executed and how we define the function that will be launched as an execution of our task just by using the this annotation task action then the meta name can be total data everything it will work what you have here also in the constructor of the task is that we are taking we are setting from an in to like we’ve done already you using archive the archive test extension so we get the project because we are on a task so everything is done upstairs using the model classes so on the project we reach the akai test extension and we get the front property and into property for the front and into properties of our task ok so we continue so basically we’ve done our a task we’ve done our plugins our our entry point and let’s try to see what dsl we want to implement how we want our user to customize our plugin because the idea of a plugin is to build with generic and being able to be configured by the user so what I would like to do by bolting this plug-in is to have an archive test block that can be declared on you the user on his builded cradle will three properties that can be set from in to and task ok so let’s see now sorry how to declare how to create this extension so as you see basically an extension is a POJO and because we are using groovy we call we call we can call it a pogo here and what there is into this pogo is very very simple three properties from end to end task with a constructor that takes project and we set default values into the constructor for front into an task so by default our plug-in will use the test task to be injected into okay and that’s really what you see here is really the point of developing a growl plug-in you should implement default values so the user can just avoid configuring your plugin so you propose a default behavior and using the DSL your user will be able to change the way your logic is supposed to be linked or by adding this kind of parameters this is also one of the last element I’ve shown you already the the descriptor is this a very simple file and it contains the class that have been that have to be pointed by our plugins so basically the entry point for the user and folder for cradle for our plugin is the archive test plug-in class and what you’re not here is that we call this file archive test dot popper G and this means that when you the user will apply our plugin it will name it archive test so the name of this file we give you the name of the plug-in inside the bridge card what the built out cradle of your user okay so let’s see now I’ll build our bubble because we are gravelled project so we need to configure a little bit if you sing so that’s a groovy project so we apply the groovy plug-in we also are also adding as a dependency the grotto API because that the API were using and what you have just behind it is a method that you can call to add the groovy dependency but depending on the gravel version that you will use the groovy version that is supposed to work with gravel can change and local groovy will just get the current gravel version that you are using for to compile and inject the good dependency for groovy depending on the on the gravel version what we do then is that we apply another plug-in maven publish to be able to publish our

plug-in as a jar as a Marvin maven dependency like this we open this element we call it map in Java and we ask it to use Java components as content of the of the after the the artifact sorry okay so now our project is ready and all and there is almost everything true to be able to run it very simply so we’ll take the place of the user and see how it can use it so how a user ha can do to use a plug-in so you had to add a repository they reported to me were your binary is located then you add the dependency like you always do then you apply the plug-in and then you configure the plug-in if needed ok so that’s very simple now our playing suppose to run on ball script because we are not deploying our project when were using our plug-in we are running tests so we had to add this plug-in in ball script dependency we deployed it on my maven local have you seen with the maven publish project and we add this dependency so these that is the way the dependency is built when you are I came back to the builders cradle so what you see here group and version are defined here and and the the artifact will be brought following this information so the class pass is made by the group then the artifact ID and then the the version that is defined into the project then the user can apply finally our archive test and how you see in lunch apply plug-in a quoting archive tests what it will do at this moment it it will call our apply method into our plugin and every that we implemented inside will be executed then it configures the plug-in the way he want from into and tasks using our extension okay so we have our plugin it’s ready it’s on my phone local so the the user can reach it put it in his project and and and set everything he wants and configure if if if you if he wants so now let’s run it so here is an example of what the user can put into his brother gravel so now he will use from and it changed from directory and he changed also the into poverty to just put it on another another on another path that we already configured by default and then he launched his tests and everything is fine because you’ve seen there is this report compiled into that is added into our output so we know that our planning worked well okay and we are very happy at this moment because that’s our first crawled plug-in rack okay so here is another example of what a user can do using our plugin he used archived tests the same time before setting from an into so we know that and then in a it is adding he is adding another thing the task he is configuring the task the task properly setting it to hello then right behind the this decoration it creates a new task called hello during whatever you want okay so let’s try to run this yeah so what basically what you want to do now is you want that’s the directory we defined before our copper is confide directly right after the hello task execution right and of course you created in the taxi I already told that so in then you launch the hello task and the book is successful everything is working on the build site but our plugin is not executed and that’s a problem that’s probably a bug and that’s probably yeah that’s what we made our very sad as very sad and we have to find a solution to fix this bug and we’ll try to do it

together so let’s analyze what is happening when the user use our plugin and define into him and define things into is protocol so first he apply our our apply our plugin so what this metal is doing basically it creates the extension do you remember then it’s set into the constructor of the extension our kyv test dot task to test as a default value right then it creates our copy – that is called archive test test something like this and then he finalized the content of the archive tests are cough tasks sorry if it get the archive task poverty get the task that corresponds to this content and then link it to the new tasks that we created that we supposed to copy then a modify the content of the extension for from test it passed to hello and it creates his task and to understand a little bit more what it is happening we’ll try to build together a graph task so first we apply our Java groovy any plug-in and this plug-in will create the task at the test task then the our plug-in is applied so we create the archive task archive test task sorry maybe that was very gone wrong named righteous by this presentation and then the apply is finish it will connect we are we our I cough test tasks to the test task and then the user creates is hello task and what you see here is really not that the results we want because at the end we want the archived test being a link it to the hello task and not to the test task so when the entry point is hello there is an easy it’s executed there is no way to go and to launch the archived test okay so we identify the problem into the grout have a graph task building procedure and we will try to see inside how occurred what is the real problem so we are back on our plugin task plugin class and what we see here is that the linking happened too early on the build process so we get the the origin of the problem we get were the cutting the code is lacking of concern consistency but before fixing it together we take a moment just to consider what is a gravel build life cycle we can identify three steps into the build.gradle gravel build life cycle the first is the initialization drink initialization the gravel will deal with all your projects dependency and see what it would have to be built and in what order before starting to build okay so that’s the first step for our project it’s really not a problem because we know we only have one project but when you have multi project dependency that’s where it starts then there is the configuration and in the configuration there is a very interesting a step that is called the evaluation and drink evaluation all the blue turd gravel of the project will be evaluated and executed so that’s when the Bulldog Crandall and the DSL declaration are execute executed and at the end of the of the configuration the bull task graph is supposed to be built then when the graph task is built the execution start ok so we know that and the problem is that oh yeah right before fixing it so here I drink all this process there are a lot of informed nice information to get and part of them are events that you can trigger and and then you can launch execute your own code following these events for example on drink the evaluation there is the before and after evaluate list the event that you can listen and for the task graph

you have other even you can trigger also one will be very interesting for us it’s the after evaluate because we want the user executes is bolted gravel so configure our plugin before using our this project archive test task property to inject it our task into the bill into the task graph so what we are doing is very simple we add project that after evaluate at a good place on the apply method and everything is supposed to work well so the result after is this change is that we have these tests tests that have no children basically not our child children and the halo tasks have the good is finalized by our own task archive test and we are very happy of it okay so we finished the boodle plugin that’s what simple right but that was a good way to discover a part of the growl plug-in API but because it’s it’s a project that is supposed to be maintained we will test it and add a few tests and we will see together how to do it I won’t go into the how it’s good to test it’s not the the purpose of this presentation but I really advise you to test it first because it’s very simple then you can write your plug-in groovy and groovy is a very friendly language when you want to mock stab and everything and it’s also fully compatible with all the libraries and frameworks that you are already using to test your java project or any language that you already use and there is also one very important I’d important point about testing your growl plug-in for now I didn’t I don’t succeed to plug a debugger when my user was using my mavin dependency my mavin project it’s feasible but it’s really hard and when you develop your plug-in and have a test that you can execute that’s extremely easy to access the debugger and to find the problems like we’ve seen together so that’s really really a very good thing to implement test for quaddle plug-in pickles it will be very easier for you to debug it when you develop so basically that’s really a groovy project so there are no species specificities on the groovy part but there are two things I want to tell you about about a Grado project and how to stop it so that that’s the tip we will be able to stop the project together and also I will I want to tell about the evaluation so we add this class containing a test we add the gene unit dependency so how to add the G unit dependency you add a G Unit G Center to your repositories on your blood gravel then we add the G unit dependency what we want to do as a first test is to check if our extension is good you will see that’s a very simple test so what we are doing first into our test method is that we are stabbing a Gradle project using this API project builder all ruled on that wall then we receive a project a stub project on the other side then we apply our Java plugin for example it can be anything else and we apply also our plugin and when it’s finished we just check that project archive test contains a good type it means our extension so that’s a very very very simple test and now you know how to do it okay so next step we want to test our class our task so we stop our project under on the same way than before and then what we are doing is that we get the task of the project we get the archived test task and check if it’s the good type also and when we run it we just figure out that

our I calf test is not accessible on the task graph and it’s not accessible for our project before going deeper into this problem I want to tell you something right squeezed because I didn’t had a time to add it but most of the time when you try to when you start to do advanced plug-in development you will have to create two to two sorry to create a lot of task and not just one life we’ve done already and how you can do it is by getting the input your user so when you use your DSL you get the information so sorry you will have to create all your tasks into the after evaluate trigger most early time that’s what’s happening and the problem is that the after evaluate is called only after the evaluation of the project and for now we didn’t evaluate we just create this tab applied plugins and then nothing happened more so or you Laroy – to evaluate the project so let’s evaluate the project yeah we use that evaluate but when you are looking for the documentation you won’t never see this method but let’s use it we don’t know just do it like this it works that’s wonderful right so this is really a method that is not documented and by looking after the trying to solve this problem I went on the web and I’ve seen this father eyes that was telling a guy complaining about the evaluate method there was not documented and this is another that I found on the gravel forum and the guy said you don’t see these API Docs you don’t see this in the API doc for the project because it that’s an internal method and if you need weave there will be a support mechanism for doing this kind of thing in a near future the guy that answer is is Luke daily that I quoted at the beginning of this presentation part of chrono project and that was in June oh that was in June 2011 so the near future is a little bit far for now and basically you sometimes you have to deal with it and with projects so we finished our plugin that is that was very simple as I told you that’s an onboarding then we know how to test it on a good way even by using non documented and undocumented method that we find together right under well let’s try to give you few hints to try improve it first there is mavin done a very good thing it’s bringing the convention over configuration concept for the build system and growl really fits to this mind and and and that’s really a lake motive of this technology and that’s a very very great thing I can tell you for example one thing that is very interesting using plugins on Java when you are applying the Java plug-in you are applying actually two plugins one is the base Java and one is the DSL Java it means that one plug-in will be able to compile and knows how to compile Java classes and the other is the real convention it means that if I have to be on this position you can configure your build using this extension etc so they really divide the compilation and the logical part from the DSL and from the convention and for the Android project that was very interesting point because the Google team that built the Andriy dual system how with all appliques they used the exact concept they take the java base because they need to compile classes and they just used their own convention plug in plug in to only the java the Java base plug-in to to make their own tool and that is a and that’s a good sign of the modularity of how you have as a non I’m sorry a growl plug-in developer to think about the structure of your plug-in as soon as you can if you can split

the convention part from the logic part to be to let people use your plugin the way they want and to interact with it easily another point is that what we’ve done on this plug-in reaching named tasks to inject our tasks after it is not the better way to do that was just the use case that I wanted to show you because there are a lot of ways you have to use for example the type of the of the task for example any test task is supposed to hinder it from test tasks declared from from Java or groovy plug-in or any other so there are many many other ways to have a true to implement generosity and use convention declared by the all the growl plugins to make it better and to make it easier for your user another point is that in growl that’s very simple to implement incremental dwells the idea of the incremental visit that if the input is the same and the output is the same also you are not supposed to execute a task and you can just just skip it and go after it so that’s very easy to do and that’s something that you can use very easily annotate and by annotating and properties into your project into your in your extension and another thing that I wanted to tell you about is that you’re not always obliged to run new task and there are also other API that allows you to skip task execution so for for for for example if our parent task for our I have test task was not supposed to be run you can use the only if rpi to skip under the the your task execution so that’s the last point of how to improve your growl plug-in implementation but there are many many many others for this presentation I want to give you a few reference one big and that’s really the source of the content you’ve seen during this presentation that’s the gravel plug-in official documentation for the unborn path the documentation is really great you have to read it that’s long but that’s really complete that’s really understandable and that’s really interesting except this evaluation method problem but that’s you should read it another another thing that this was really undone boarding and I built another conference I gave already at Troy Khan London and Paris about how to take your plug-in from develop from scratch I then shown you to the next level by building and improving your DSL by also interact your plugin to make interactive playing with DeAndre the official plug-in how to test it a little bit more accurately you have the link on this page so hurry is again the slide the link to the slide if you want to get it I hope you enjoy this talk and if you have question I will be happy to answer it thank you any question that was so clear so I think we are fine you will be able to find me on the conference for the hall there will be here