How to copy output of binary task

While working with the Native plugins, I’m searching for ways to copy the output of a native task, but can’t seem to get it working. It looks as if the native tasks are created too late.

Assume we have native (cpp) component ‘x’. There will be a lifecycle task ‘xStaticLibrary’. I would expect I can do this:

task zipX(type:Zip) {
  from project.tasks['xStaticLibrary']
  into '.'
}

Unfortunately this will not configure successful, claiming that task with name ‘xStaticLibrary’ cannot be found. Yet, when I execute ‘./gradlew components’, I do see the component and it’s corresponding tasks. How would I get this working?

UPDATE:
I similarly tried this, but it failed saying that the BinarySpec with name ‘:x’ cannot be found:

task zipX(type:Zip) {
  from project.binaries['x'].staticLibraryFile
  into '.'
}

This is correct. In general, you have to get at these tasks through the binaries container. You could do something like this:

binaries.withType(StaticLibraryBinarySpec) {
    task "${name}Zip"(type: Zip) {
        from staticLibraryFile
        dependsOn tasks
    }
}

Ah cool, that should work. In my case, I want to put multiple binaries in one zip, but then it’s look like this, right?

task 'zipAllNativeSOs'(type:Zip)
binaries.withType(StaticLibraryBinarySpec) {
    // Attach them all
    task 'zipAllNativeSOs' << {
        from staticLibraryFile
        dependsOn tasks
    }
}

The left-shift operator (<<) is an alias to doLast which isn’t what you want. You’ll just want something like this:

task 'zipAllNativeSOs'(type:Zip) {
    binaries.withType(StaticLibraryBinarySpec) {
        // Attach them all
        from staticLibraryFile
        dependsOn tasks
    }
}

Thanks @mark_vieira , this did indeed work, back when you posted it (on Gradle 2.6). However, when running the same code on 2.10, it fails during configuration:
Could not find property 'binaries' on task ':acllib:nativeZip'.

From release notes, I can’t figure out what I should change to get it back working. Mind help me out?

Yes the syntax has changed in recent versions. You’ll have to do something like this:

model {
    tasks {
        zipAllNativeSOs(Zip) {
            $.binaries.withType(StaticLibraryBinarySpec).each {
                // Attach them all
                from it.staticLibraryFile
                dependsOn it.tasks
            }
        }
    }
}

That results in a compilation error: Invalid variable name. Must include a letter but only found: $

That sounds like either the code block is not inside a model { } block or you are not using Gradle 2.10.

I am using Gradle 2.10 and it is in a model block, but it’s not the same model block as where I define the native components. Would that pose a problem?

It should not. Can you share your build script? Perhaps there is something else going on.

My build script is over 2100 lines long. I posted fragments of it on this Gist, but can’t show the entire file (as it’s IP of my employer). I’m afraid you won’t be able to run it…

Try something like

model {
  task zipAllNativeSOs(type: Zip) {
    def staticLibraryBinaries = []
    binaries {
      withType(StaticLibraryBinarySpec) {
        dependsOn it.tasks
        staticLibraryBinaries << it
      }
    }
    doLast {
      staticLibraryBinaries.each { bin ->
        from bin.staticLibraryFile
      }
      into '.'
    }
  }
}

Maybe it can help.

Or if you just want to copy the output files, alternatively try

model {
  task copyAllNativeSOs {
    def staticLibraryBinaries = []
    binaries {
      withType(StaticLibraryBinarySpec) {
        dependsOn it.tasks
        staticLibraryBinaries << it
      }
    }
    doLast {
      staticLibraryBinaries.each { bin ->
        copy {
          from bin.staticLibraryFile
          into '.'
        }
      }
    }
  }
}

It results in a compilation error with regards to the line that says binaries {:

Exception thrown while executing model rule: model.tasks > create(nativeZip)
Attempt to mutate closed view of model of type ‘java.lang.Object’ given to rule ‘model.tasks’

Just double checked. The copyAllNativeSOs task works on my side with gradle 2.10.

I assume you call it in subprojects? That should work as well.

Indeed, it’s called from subprojects, see the Gist linked above.

Am I facing the same issue as How to "read" component model information in a Copy task??