Now what if you need to integrate the generation of DLLs as part of your Gradle multi project ? A little while back I was on a project that had this particular need so I thought I'd share some harvested knowledge.
I ended up solving this in a gradle script, but it would probably benefit from being packaged as a plugin. Anyways here goes:
I added the following to a ikvm.gradle
ext.executeIkvm = {ikvmDll, args ->
def ikvmExec = new File(System.getenv()['IKVM_HOME'] , 'bin/ikvmc.exe')
assert ikvmExec.exists(), "You must install Ikvm and set IKVM_HOME env variable"
def commandLineArgs = [ikvmExec] + args
println commandLineArgs
exec {
commandLine = commandLineArgs
}
}
ext.addIkvmTask = {ikvmProject->
if(ikvmProject.getTasksByName("ikvm", false)) return
ikvmProject.task("ikvm", dependsOn: ikvmProject.jar) {
description = "Generates Ikvm dll for given project"
ext.ikvmOutDir = file("${ikvmProject.buildDir}/ikvm")
ext.ikvmDll = new File(ikvmOutDir, "${ikvmProject.name}.dll")
ext.referencedDlls = [] as Set
inputs.files ikvmProject.jar.archivePath
outputs.files ikvmOutDir
doFirst {
if (!ikvmOutDir.exists()) ikvmOutDir.mkdir()
}
doLast {
def commandLineArgs = [
"-out:$ikvmDll", "-version:$version",
ikvmProject.jar.archivePath] + referencedDlls.collect{"-reference:$it"}
executeIkvm(ikvmDll, commandLineArgs)
}
}
ikvmProject.build.dependsOn ikvmProject.ikvm
}
ext.configureIkvmProject = {ikvmProject ->
addIkvmTask(ikvmProject)
def runtimeDeps = ikvmProject.configurations.runtime.allDependencies
def referencedSubDlls = runtimeDeps.collect {dependency ->
if (dependency instanceof ProjectDependency) {
def ikvmSubProject = project(":${dependency.name}")
addIkvmTask(ikvmSubProject)
ikvmProject.ikvm.dependsOn ikvmSubProject.ikvm
return [ikvmSubProject.ikvm.ikvmDll] + configureIkvmProject(ikvmSubProject)
} else {
throw new RuntimeException("Sorry not supporting third party deeps")
}
}.flatten()
ikvmProject.ikvm.referencedDlls += referencedSubDlls
}
(actually I added some more stuff to deal with the outputstream from exec, but it just muddles the implementation example above)In my root build.gradle I added the following:
subprojects{
//...
apply from: "$rootDir/ikvm.gradle"
afterEvaluate { project ->
configureIkvmProject project
}
//...
}
Now you basically have the ability to generate a 1-1 mapping between your jar projects and .Net dlls. As far as I know there is no such thing as transitive dependencies in .Net, so we opted to add any transitives into the linking metainfo for the dlls.
Not shown, but we also added the ability to
- generate dll's for transitive 3.rd party jar files
- the ability to generate .net debug info (pdb files)
- checking in generated dlls to VCS to trigger .Net build on TeamCity
- convenience tasks for copying generated artifacts to lib folder in .Net project(s)