Extending default tasks in Native Multi-Project Gradle builds

not-a-bug

(Ganesh) #1

I am trying to extend the build and clean default tasks of all my subprojects in a Multiproject build. Here is the build.gradle of the root project.

//build.gradle
    allprojects  {

    	build.doLast {
    		copy {
    			from 'build/exe'
    			into './obj_gradle/'
    			include "**/*"
    		}
    	}
    	
    	clean.doLast {
    		file('obj_gradle/').deleteDir()
    	}	
    }

Now, when I run gradle build command from within my subproject, the generated executables are not copied. However, if I place the exact above set of commands in my subproject’s build.gradle, it runs fine. I have included the path of the subproject in my settings.gradle already. What am I missing?


(Daniel Lacasse) #2

Hi Ganesh,

I’m not too sure I totally understand your question. I tried out your scenario and it works as expected. It’s generally not a good practice to extend the lifecycle tasks. It is recommended to add dependencies to a copy task or something similar. That been said, here is my code example that works:
###Root build.gradle:
allprojects {
apply plugin: ‘cpp’

  build.doLast {
    copy {
      from 'build/exe'
      into './obj_gradle/'
      include "**/*"
    }
  } 

  clean.doLast {
    file('obj_gradle/').deleteDir()
  } 
}

###settings.gradle:
include “a”

Project a build.gradle:

apply plugin: 'cpp'

model {
  components {
    main(NativeExecutableSpec)
  }
}

Note the component main needs to have code to build or no executable will be build which result in no executable been copied.

I hope this helps,

Daniel


(Ganesh) #3

Hi Daniel,

Thanks. It works now. The only change I made was place the apply plugin: 'c' option inside of allProjects {} in the root build.gradle. Earlier it was outside the method and hence did not work. Quite interesting but it works. Thanks.


(Daniel Lacasse) #4

I understand the confusion. The DSL allprojects and subprojects will prepend execution of the Closure before any project it applies to. If you try to access the tasks that aren’t created (lifecycle tasks are created by some base plugin) it won’t work.

Preemptively applying plugin may work for your case but it’s best practice to instead react to a plugin been applied in a project when using allprojects or subprojects. This gives you the ability to opt-out of a specific plugin for one or more project and it makes it more explicit on what is going on in each project. To react to a plugin, you would normally use the PluginContainer through Project.getPlugins(). From there you can use [PluginContainer.withId('c') {...}](https://docs.gradle.org/current/javadoc/org/gradle/api/plugins/PluginContainer.html#withId(java.lang.String, org.gradle.api.Action)) to react when the c plugin is applied.

I hope this helps,

Daniel