Multiplatform build deployment- what is good practice


(Bronislav Gabrhelik) #1

We have a multi-platform JNI project (win & mac). We have to compile each platform separately as there is no cross-platform compiler for C/C++ code. My plan is to separate classes into three jars: e.g main jar is sysutils.jar and platform jars sysutils-win.jar & sysutils-mac.jar. I need to bundle the platform JNI binary into resources of the platform jar. I currently have a specific souceSet and configuration for given platform. There is compile dependency of platform classes on main classes, but runtime dependency is opposite as main jar needs to load JNI native library.

The problem here is with publishing into repository in two separate steps. I started with usage of classifiers to distinguish platforms builds. But I am not able to create dependency of main jar on them, so they are automatically downloaded. And how to distinguish between different platforms? I can have custom maven scopes/ ivy configurations in maven/ivy repo like macRuntime and winRuntime? But would it work? There is just one pom/ivy file, so I have to create the fake artifacts for counterpart platform, so all records are present. Mode deeply I am getting into problem the build.gradle file is less and less readable and full of ugly conditional code. I feel that classifiers is not a good way, so I am thinking about other solutions. I tried to use MavenPublish addFilter to generate separate platform pom, but ivy.xml is still one file and build.gradle is not very nice even if I have implemented like 4 plugins.

My thought is to create a virtual project for platform part, so publishing of platform jar is absolutely separated. Luckily the buildscript works also in settings, so I can do something like

buildscript {
...
}
  rootProject.name = 'sysutils'
  import com.company.tools.build.xdgradle.utils.Platform;
  include 'main'
include 'version'
include "main/jni/${Platform.name}"
  // rename main project
project(':main').name = 'client.utils.sysutils'

The simplest solution is to change basename according to the platform, so it is published into different locations on different platform, but I would like to have common code shared and published once. Do you have any recommendations or some great idea how to deal with this problem.

Thanks, Bronislav


(Peter Niederwieser) #2

The new, incubating ‘maven-publish’ and ‘ivy-publish’ plugins make it easy to publish multiple modules per project. WIth Ivy, you can alternatively have a single module that exposes multiple configurations, each of which contains multiple artifacts. Projects that depend on the module can then select the appropriate configuration. Seems like a good fit here.


(Bronislav Gabrhelik) #3

Peter, I am afraid the single module with multiple configurations is not solution for me as the build on each platform would overwrite the same module descriptor.

Looking into ivy-publish DSL, it seems that I cannot alter module name in publications, so I cannot publish more modules.

thanks for the help, Bronislav


(Bronislav Gabrhelik) #4

I have figured out how to generate more ivy descriptors by looking into IvyPublish plugin object model. I am leaving the code snippet for those who would like to generate more Ivy descriptors.

apply plugin: 'ivy-publish'
  group = 'org.gradle.sample'
version = '1.0'
  publishing {
    publications {
        ivyCustom(IvyPublication) {
         identity.module = "custom-name"
            descriptor.withXml {
                asNode().info[0].appendNode('description', 'A demonstration of ivy descriptor customization')
            }
        }
        ivyCustom2(IvyPublication) {
         identity.module = "custom-name2"
            descriptor.withXml {
                asNode().info[0].appendNode('description', 'A 2. demonstration of ivy descriptor customization')
            }
        }
    }
    repositories {
        ivy {
            url "file://$buildDir/repo" // change to point to your repo, e.g. http://my.org/repo
        }
    }
}

(Bronislav Gabrhelik) #5

Here is an example how to generate more pom files.

apply plugin: 'maven-publish'
  group = 'org.gradle.sample'
version = '1.0'
  publishing {
    publications {
        mavenCustom(MavenPublication) {
         mavenProjectIdentity.artifactId = "custom-name"
         pom.withXml {
                asNode().appendNode('description', 'A demonstration of maven pom customisation')
            }
        }
        mavenCustom2(MavenPublication) {
         mavenProjectIdentity.artifactId = "custom-name2"
         pom.withXml {
                asNode().appendNode('description', 'A 2nd demonstration of maven pom customisation')
            }
        }
    }
    repositories {
        maven {
            url "file://$buildDir/repo" // change to point to your repo, e.g. http://my.org/repo
        }
    }
}