Copy Task after Linking - gradle

I am trying to perform a copy of the build artifacts after performing the linking for Native Executables. Attached is an excerpt from my build.gradle
components {
all {
binaries.withType(SharedLibraryBinarySpec) {
buildable = false
}
binaries.withType(NativeExecutableBinarySpec) {
tasks.withType(LinkExecutable) {
doFirst {
outputFile = file("$buildDir/exe/${baseName}/${baseName}.o")
}
doLast {
copy {
from (file("$buildDir/exe/${baseName}/"))
into "./objs_exe/exe/"
include "*.o"
}
}
}
}
}
}
I would like to rename my linked executable and then copy it to another location. However, I get the error as
Attempt to modify a closed view of model element 'components' of type 'ComponentSpecContainer' given to rule model.components
This is a multi-project build and the above code is part of the root project's build.gradle. The doFirst closure works without any issues. Also, I have applied the c plugin

Related

setting properties for Gradle subproject

I have a multi-project Gradle build. In each subproject I have a properties.gradle file like the following:
def usefulMethod() {
return 'foo'
}
ext {
foo = 'bar'
usefulMethod = this.&usefulMethod
}
And then I import it into the subproject build.gradle using apply from: './properties.gradle'.
However, if two subprojects import a variable with the same name, I get this error:
Cannot add extension with name 'foo', as there is an extension already registered with that name.
It seems that adding to ext affects the entire project instead of just the subproject like I wanted. What is the correct way to import properties and variables from an external file in a subproject without leaking them into the entire project build?
The plain ext is the extension for ENTIRE project, the root project and all subprojects. To avoid polluting the root namespace whenever you include a file via apply from..., you should instead use project.ext. project refers to the current project or subproject being built. For example, the below file could be apply from'd to add a downloadFile function to the current project:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'de.undercouch:gradle-download-task:3.4.3'
}
}
project.ext {
apply plugin: de.undercouch.gradle.tasks.download.DownloadTaskPlugin
downloadFile = { String url, File destination ->
if (destination.exists()) {
println "Skipping download because ${destination} already exists"
} else {
download {
src url
dest destination
}
}
}
}

How to include headers for C compilation in Gradle?

I am a newbie to Gradle. I am trying to compile a set of source files which contain headers which are distributed across the project directory. My source directory structure does not comply with the Gradle convention. How do I add the header locations needed for compilation in my build.gradle? Attached here is my build.gradle file.
// build.gradle
apply plugin: 'c'
model {
components {
my_project (NativeExecutableSpec){
sources {
c {
source {
srcDir "my_proj_src/a/a1.1"
include "**/*.c"
}
exportedHeaders {
srcDir "my_proj_src/a/a1.1", "fsw/b/b1.2"
}
}
}
}
}
}
This does not work. And additionally, is there a possibility to do partial linking using Gradle?
EDIT: Additionally, I would like to also know how to make Gradle search recursively for headers within the source hierarchy.
exportedHeaders` are for exporting headers from the component itself, not for adding headers. So this would not work.
You would need to create a library and add it as the api linkage so that those headers will be added to headers your component is compiled against:
model {
repositories {
libs(PrebuiltLibraries) {
ffmpegHeaders {
headers.srcDirs "$ffmpegDir/include"
}
}
}
components {
libUsingHeaders(NativeLibrarySpec) {
sources {
c {
lib library: 'ffmpegHeaders', linkage: 'api'
}
}
}
}
}

Gradle - "apply from" a ZIP dependency

In my Gradle build script I want to import a ZIP dependency that contains static analysis configuration (CheckStyle, PMD etc.) and then "apply from" the files in that ZIP. When anyone runs the "check" task, my custom static analysis configuration should be used then.
I've tried the somewhat convoluted solution below, but I can't get it to work. The files are retrieved and unpacked into the "config" directory, but "apply from" does not work - Gradle complains it cannot find the files; I assume this is due to "apply from" being run during the build configuration phase.
Is there a simpler way to do this?
repositories {
maven { url MY_MAVEN_REPO }
}
configurations {
staticAnalysis {
description = "Static analysis configuration"
}
}
dependencies {
staticAnalysis group:'my-group', name:'gradle-static-analysis-conf', version:'+', ext:'zip'
}
// Unzip static analysis conf files to "config" in root project dir.
// This is the Gradle default location.
task prepareStaticAnalysisConf(type: Copy) {
def confDir = new File(rootProject.projectDir, "config")
if (!confDir.exists()) {
confDir.mkdirs()
}
from {
configurations.staticAnalysis.collect { zipTree(it) }
}
into confDir
apply from: 'config/quality.gradle'
}
check.dependsOn('prepareStaticAnalysisConf')
You are perfectly right: Gradle runs apply during evaluation phase, but the prepareStaticAnalysisConf was not executed yet and the archive is not unpacked.
Instead of a task, just write some top-level code. It should do the trick. Also, you'd better use the buildscript level dependency, so that it is resolved before script is executed.
Here is the full script
buildScript {
repositories {
maven { url MY_MAVEN_REPO }
}
dependencies {
classpath group:'my-group', name:'gradle-static-analysis-conf', version:'+', ext:'zip'
}
}
def zipFile = buildscript.configurations.classpath.singleFile
copy {
from zipTree(it)
into 'config'
}
apply from: 'config/quality.gradle'

How to keep Java code and Junit tests together building with Gradle

I have a project in which the main source and the test cases for that source are kept in the same package/directory. Each test class is the name of the class which it is testing with "Test" appended on the end. So if I have a Foo.java there will be a FooTest.java right next to it.
My question is, how do I build this project with Gradle? I'd still like to keep the class files separate, i.e. a folder for main classes and a folder for test classes.
This should do the trick:
sourceSets {
main {
java {
srcDirs = ["some/path"]
exclude "**/*Test.java"
}
}
test {
java {
srcDirs = ["some/path"]
include "**/*Test.java"
}
}
}
For reference, here is the code I used to try to get around the Eclipse plugin's classpath issue. Using this in combination with Peter's answer above seems to work.
// The following ensures that Eclipse uses only one src directory
eclipse {
classpath {
file {
//closure executed after .classpath content is loaded from existing file
//and after gradle build information is merged
whenMerged { classpath ->
classpath.entries.removeAll { entry -> entry.kind == 'src'}
def srcEntry = new org.gradle.plugins.ide.eclipse.model.SourceFolder('src', null)
srcEntry.dir = file("$projectDir/src")
classpath.entries.add( srcEntry )
}
}
}
}
this work for me:
eclipse {
classpath {
file {
withXml {
process(it.asNode())
}
}
}
}
def process(node) {
if (node.attribute('path') == 'src/test/java' || node.attribute('path') == 'src/test/resources')
node.attributes().put('output', "build/test-classes")
else
node.children().each {
process(it)
}}

Extract specific JARs from dependencies

I am new to gradle but learning quickly. I need to get some specific JARs from logback into a new directory in my release task. The dependencies are resolving OK, but I can't figure out how, in the release task, to extract just logback-core-1.0.6.jar and logback-access-1.0.6.jar into a directory called 'lib/ext'. Here are the relevant excerpts from my build.gradle.
dependencies {
...
compile 'org.slf4j:slf4j-api:1.6.4'
compile 'ch.qos.logback:logback-core:1.0.6'
compile 'ch.qos.logback:logback-classic:1.0.6'
runtime 'ch.qos.logback:logback-access:1.0.6'
...
}
...
task release(type: Tar, dependsOn: war) {
extension = "tar.gz"
classifier = project.classifier
compression = Compression.GZIP
into('lib') {
from configurations.release.files
from configurations.providedCompile.files
}
into('lib/ext') {
// TODO: Right here I want to extract just logback-core-1.0.6.jar and logback-access-1.0.6.jar
}
...
}
How do I iterated over the dependencies to locate those specific files and drop them in the lib/ext directory created by into('lib/ext')?
Configurations are just (lazy) collections. You can iterate over them, filter them, etc. Note that you typically only want to do this in the execution phase of the build, not in the configuration phase. The code below achieves this by using the lazy FileCollection.filter() method. Another approach would have been to pass a closure to the Tar.from() method.
task release(type: Tar, dependsOn: war) {
...
into('lib/ext') {
from findJar('logback-core')
from findJar('logback-access')
}
}
def findJar(prefix) {
configurations.runtime.filter { it.name.startsWith(prefix) }
}
It is worth nothing that the accepted answer filters the Configuration as a FileCollection so within the collection you can only access the attributes of a file. If you want to filter on the dependency itself (on group, name, or version) rather than its filename in the cache then you can use something like:
task copyToLib(type: Copy) {
from findJarsByGroup(configurations.compile, 'org.apache.avro')
into "$buildSrc/lib"
}
def findJarsByGroup(Configuration config, groupName) {
configurations.compile.files { it.group.equals(groupName) }
}
files takes a dependencySpecClosure which is just a filter function on a Dependency, see: https://gradle.org/docs/current/javadoc/org/gradle/api/artifacts/Dependency.html

Resources