1

I have a gradle script in which I configure a plugin (in my case ospackage but I guess the same would apply to another plugin) using a variable as per:

ospackage {
...
version project.ext.my_version 
...
}

This variable is first initialized and then is updated using a task that I call first in my build script:

  ext {
        ...
        my_version = "XXX"
        ...
    }

task init{
    group 'ho'
    description 'get HO Version'
    doLast {
        ...
        project.ext.my_version = getParameter("VERSION")
        ...
            }
     }

the problem is that the plugin (in my case ospackage) always consider the initial value "XXX" and not the correct one that was set by executing the init task. I know it has something to do with configuration and execution phase but still I cannot find a workaround to do what I want.

For info, I also tried to create a task like the one below but it also fail as it seems that buildDeb task does not overwrite ospackage version parameter

buildDeb {
    doLast {
        ...
        version project.ext.my_version
        link('/usr/bin/aa', '/usr/bin/aa.sh')
        ...
    }
}

I also tried to put at the end of my file something like:

ospackage.dependsOn("init")

but the problem is that ospackage is not recognized as a task

Thank you in advance for your help.

sschuberth
  • 28,386
  • 6
  • 101
  • 146
akasolace
  • 572
  • 1
  • 5
  • 17
  • I have the same issue. The only solution I can see is doing everything in the config phase. (this makes me scream internally as gradle has gone to great lengths to split config and execution) Try commenting out your doLast blocks to stop forcing it to execution phase. I'll add a proper answer if I find it. – Calvin Taylor Jun 24 '20 at 04:21
  • @CalvinTaylor this is what I ended up doing set everything in the config phase. My experience with the config vs execution phases has always been painful ... – akasolace Jun 24 '20 at 09:47
  • @akasolace It looks to me like the essence of your question revolves on-demand values. I'll add another answer. I had a similar issue and got to the root on the problem differently. – Jonathan Komar Jun 25 '20 at 08:13

3 Answers3

1

It looks to me like the essence of your question revolves around on-demand values. My understanding is that you would like to set a version number during the configuration phase and use that value during the execution phase to set a package version using the ospackage plugin.

The issue is that the ospackage documentation only provides examples (to date) that setup the package constants during the configuration phase. Obviously that won't work because it is the same time you are setting your version (something that must be able to be done in parallel). You have the right idea with doLast. I found that some things from the ospackage cannot go in "doLast" blocks like packageName (if you have more than one of the same package/task type), so I just put the things that require on-demand evaluation in that block (the version, because we need its evaluation delayed until the execution phase).

My solution was to create a variable that holds the function that resolves the version.

def versionForRpm = { -> project.version }

Create a configuration block

configurations.ext {
  version = versionForRpm
  ...
}

This is an example of an on-demand value (aka lazily-evaluated value).

task someRpmBuild(type: Rpm) {
    // all package configs that require evaluation during execution phase (lazy)
    doLast {
        version = configurations.ext.version
        requires("someotherpackageinthisbuild", configurations.ext.version(), 0)
    }
    // all package configs that may be evaluated during the configuration phase
    release = configurations.ext.release
    packageGroup = configurations.ext.packageGroup
    license = configurations.ext.license
    packager = configurations.ext.packager
    user = configurations.ext.user
    distribution = configurations.ext.distribution
    vendor = configurations.ext.vendor
    url = configurations.ext.url
    os = configurations.ext.os
    buildHost = configurations.ext.buildHost
    epoch = configurations.ext.epoch
    arch = configurations.ext.arch
}

Note that configurations.ext.version will be "called" automatically in the execution phase. I needed to explicitly call it when used as an argument in requires, however.

Jonathan Komar
  • 2,678
  • 4
  • 32
  • 43
  • 1
    yes looks like that was the way to go ... Unfortunately, I will not test this as I recently move the project to install4J for the artifacts building. But thank you very much for taking the time to answer and to teach me something ! – akasolace Jun 25 '20 at 12:05
0

according to the documentation, the task type is Deb:

task fooDeb(type: Deb) {
    packageName          // Default to project.name
    packageDescription   // Defaults to project.description
    version              // Version field, defaults to project.version
    arch                 // Architecture, defaults to "all". E.g. "amd64", "all"
    multiArch            // Configure multi-arch behavior: NONE (default), SAME, FOREIGN, ALLOWED (see: https://wiki.ubuntu.com/MultiarchSpec )
    release              // DEB Release
    epoch                // Epoch, defaults to 0
    user                 // Default user to permission files to
    permissionGroup      // Default group to permission files to, "group" is used by Gradle for the display of tasks
    packageGroup
    buildHost   
    license 
    packager    
    distribution    
    vendor  
    url 
    signingKeyId    
    signingKeyPassphrase    
    signingKeyRingFile  
    sourcePackage   
    provides
    uid                  // Default uid of files
    gid                  // Default gid of files
    createDirectoryEntry // [Boolean]   
    maintainer           // Defaults to packager
    uploaders            // Defaults to packager
    priority    
    summary 
    conflicts   
    recommends  
    suggests    
    enhances    
    preDepends  
    breaks  
    replaces
}

where:

version Version field, defaults to project.version

might give the RPM plugin a try.

Martin Zeitler
  • 1
  • 19
  • 155
  • 216
  • I think I tried this, but project.ext.my_version was still defaulting to the initial value. I am not sure if I included this in the doLast section though, unfortunately I can't give it a new try until tonight. – akasolace Nov 01 '18 at 08:17
  • @akasolace what means `getParameter("VERSION")`?? when just setting `project.version` accordingly, the package version would not even have to be passed. – Martin Zeitler Nov 01 '18 at 08:21
  • to add a task dependency: `task fooDeb(dependsOn: init)` – Martin Zeitler Nov 01 '18 at 08:31
  • getParameter("VERSION") is a function that return the version as a string like : 1.0 or 1.2_BETA defined in one of my java class. I wanted to ensure the project.version was equals to the version set in my java class so dynamically set at run time. I could also hardcode the version both in java class and gradle.build but it does not look very clean and is subject to error. Maybe I could set project.version instead of ext.project.version but I don't see how it will solve the issue considering that project.version will be set at execution time. – akasolace Nov 01 '18 at 08:41
  • no, in task fooDeb if I put a println(project.ext.my_version) just before version project.ext.my_version, it prints the correct version, but the version of the debpackage remains equals to the default value 'XXX'. It is like the fooDeb does not overwrite values set by ospackage configuration. – akasolace Nov 01 '18 at 08:58
  • @akasolace that function might possibly fail. output a java class with the version info, before building. classes ordinary do not have versions, hence the package info has this information in `META-INF\MANIFEST.MF`. https://stackoverflow.com/questions/21724145/get-jar-version-in-runtime – Martin Zeitler Nov 01 '18 at 08:59
  • you can set it with `project.version` and it should be picked up from there. gradle tasks "work differently" and have a limited scope, what kind of task they may perform and which variables they can access. – Martin Zeitler Nov 01 '18 at 09:01
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/182924/discussion-between-akasolace-and-martin-zeitler). – akasolace Nov 01 '18 at 09:10
  • so what I will try next is 1) set the project version in gradle (instead of my java class) 2) use gradle to pass that information to the manifest file 3) change my java get_version function to read from the manifest file for step 2 and 3, I will use https://stackoverflow.com/questions/37642837/gradle-make-build-version-available-to-java – akasolace Nov 01 '18 at 14:18
0

I was able to solve the issue i had, setting the destination for the ospackage copy destination to a calculated value by using

configurations.ext{
   mydestdir = ""
   rpmVersion = "1"
   releaseNumber = "1"
}

task init{
    group 'ho'
    description 'get HO Version'
    doLast {
        ...
        configurations.ext.mydestdir = "/store/tmp/+getSubDir()"
        configurations.ext.rpmVersion = "123"
        configurations.ext.releaseNumber = "456"
        ...
    }
}

task fooRpm(type: Rpm) {
    dependsOn init
    ...
    doLast(){
        version = configurations.rpmVersion
        release = configurations.releaseNumber
    }
    from(project.tempDir) {
        into configurations.mydestdir 
        fileMode = 0644
        user = "nobody"
        permissionGroup = "nobody"
    }
}    

I think you'll have use type Deb, and make some changes, but this should speed up your build, and you can verify results by adding --scan before and after making these changes.

Calvin Taylor
  • 664
  • 4
  • 15