Hello,
I am trying to build libxml2 with gradle, here is what I have so far:
task autoReconfigure(type : Exec) << {
executable "autoreconf"
args "-vif"
workingDir "."
}
task configureTask(type : Exec, dependsOn : autoReconfigure) << {
executable "./configure"
args "--without-zlib"
workingDir "."
}
task makeFileTask(type : Exec, dependsOn : configureTask) << {
executable "make"
args "-f", "Makefile"
workingDir "."
}
build.dependsOn(makeFileTask)
assemble.dependsOn(makeFileTask)
This works, however this would rebuild the library everytime I call build or assemble. Also there is a problem that the tasks are rather repetitive for libraries like libpng
or libfreetype
so I refactored them into custom tasks into the folder:
buildSrc/src/main/groovy/com/ulabs/gradle
package com.ulabs.gradle
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Optional
import org.gradle.api.Project
import org.gradle.api.tasks.incremental.IncrementalTaskInputs
class AutoConfigureTask extends DefaultTask {
@Input
@Optional
def extraArgs
@TaskAction
def execConfigure(IncrementalTaskInputs inputs) {
println "Launching AutoConfigureTask from: " + project.projectDir
if(!new File(project.projectDir, 'configure.ac').exists() &&
!new File(project.projectDir, 'configure.in').exists()) {
throw new FileNotFoundException(
'autoconfigure task should have either configure.in or configure.ac ')
}
boolean outDated = false
inputs.outOfDate { change ->
outDated = true
}
if(outDated) {
project.exec {
executable "autoreconf"
args "-ivf", hasProperty("extraArgs") ? extraArgs : ""
}
}
}
}
package com.ulabs.gradle
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Optional
import org.gradle.api.Project
import org.gradle.api.tasks.incremental.IncrementalTaskInputs
class ConfigureTask extends DefaultTask {
@Input
@Optional
def extraArgs
@TaskAction
def execConfigure(IncrementalTaskInputs inputs) {
if(!new File(project.projectDir, 'configure').exists()) {
throw new FileNotFoundException(
'configure task should have a configure script')
}
boolean outDated = false
inputs.outOfDate { change ->
outDated = true
}
if(outDated) {
project.exec {
executable "./configure"
args hasProperty("extraArgs") ? extraArgs : ""
}
}
}
}
package com.ulabs.gradle
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Optional
import org.gradle.api.Project
import org.gradle.api.tasks.incremental.IncrementalTaskInputs
class MakefileTask extends DefaultTask {
@Input
@Optional
def extraArgs
@Input
@Optional
def env
@TaskAction
def execConfigure(IncrementalTaskInputs inputs) {
if(!new File(project.projectDir, 'configure').exists()) {
throw new FileNotFoundException(
'makefile task should have a Makefile script')
}
boolean outDated = false
inputs.outOfDate { change ->
outDated = true
}
if(outDated) {
project.exec {
executable "make"
args hasProperty("extraArgs") ? extraArgs : "-f Makefile"
}
}
}
}
and in build.gradle:
apply plugin: 'c'
import com.ulabs.gradle.AutoConfigureTask
import com.ulabs.gradle.MakefileTask
import com.ulabs.gradle.ConfigureTask
gradle.allprojects {
ext.getLibXmlLibsPath = {
def distDir = new File(project(":libxml2").projectDir, "buildLibxml2")
return distDir.toString()
}
ext.getLibXmlHeaderPath = {
def hDir = new File(project(":libxml2").projectDir, "include")
return hDir.toString()
}
}
project(':libxml2') {
model {
toolChains {
visualCpp(VisualCpp)
gcc(Gcc)
clang(Clang)
}
platforms {
x86 {
architecture "x86"
}
x64 {
architecture "x86_64"
}
itanium {
architecture "ia-64"
}
}
components {
xml2(NativeLibrarySpec) {
sources {
c {
exportedHeaders {
srcDir "include"
include "libxml/*.h"
}
exportedHeaders {
srcDir "include"
include "win32config.h", "wsockcompat.h"
}
exportedHeaders {
srcDir "."
include "libxml.h"
}
}
}
}
}
repositories {
libs(PrebuiltLibraries) {
libxml2 {
headers.srcDir getLibXmlHeaderPath()
binaries.withType(StaticLibraryBinary) {
def baseDir = getLibXmlLibsPath()
staticLibraryFile = file("${baseDir}/libxml2.a")
}
binaries.withType(SharedLibraryBinary) {
def os = targetPlatform.operatingSystem
def baseDir = getLibXmlLibsPath()
if (os.windows) {
sharedLibraryFile = file("${baseDir}/libxml2.dll")
if (file("${baseDir}/util.lib").exists()) {
sharedLibraryLinkFile = file("${baseDir}/libxml2.lib")
}
} else if (os.macOsX) {
sharedLibraryFile = file("${baseDir}/libxml2.dylib")
} else {
sharedLibraryFile = file("${baseDir}/libxml2.so")
}
}
}
}
}
}
task autoConfigTask(type: AutoConfigureTask) {
println "Running configure Task ${project}"
}
task configureTask(type: ConfigureTask, dependsOn: autoConfigTask) {
println "Running configure Task ${project}"
}
task makeFileTask(type: MakefileTask, dependsOn: configureTask) {
println "Running makefile Task ${project}"
}
task make(dependsOn : makeFileTask) {
def distDir = new File(getLibXmlLibsPath())
doLast {
delete distDir.toString()
distDir.mkdirs()
def binDir = projectDir.toString() + "/.libs"
FileTree tree = fileTree(binDir.toString()) {
include 'libxml2*'
exclude '*.la*'
}
tree.each {File file ->
copy {
from file.toString()
into distDir.toString()
}
}
}
}
}
build.dependsOn(make)
assemble.dependsOn(make)
Question 1: Now the problem is that when I do gradle build
it says Cannot convert org.gradle.model.dsl.internal.NonTransformedModelDslBacking@1a256d80 to a task.
. Could you suggest what is wrong?
Running with a --stacktrace
gives me:
Caused by: org.gradle.internal.typeconversion.UnsupportedNotationException: Cannot convert org.gradle.model.dsl.internal.NonTransformedModelDslBacking@497d4c96 to a task.
Edit: So I’ve solved this one, I was just defining tasks inside the model
Question 2: Gradle now gives me that all tasks are up-to date. This probably has to do with inputs that I’ve set optional, but is there a way to achieve the following functionality:
I would like that:
- ./configure, autotools or make are not run unless their arguments change (extraArgs or env)
- when the arguments change, I’d like them all to run in a chain as specified by dependencies
- I would like libxml2 to act like a project that can be linked with others and be able to match platform/architecture of the dependant, with linkage
api
,shared
orstatic