Skip to content

Instantly share code, notes, and snippets.

@simon04
Last active February 15, 2022 06:14
Show Gist options
  • Star 18 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save simon04/6865179 to your computer and use it in GitHub Desktop.
Save simon04/6865179 to your computer and use it in GitHub Desktop.
Gradle, Java plugin, Jar MANIFEST, Class-Path is empty

Gradle, Java plugin, Jar MANIFEST, Class-Path is empty

I struggled with with the jar MANIFEST file built with Gradle containing an empty Class-Path. I traced down the problem to the order of the dependencies and jar blocks in the build.gradle file:

Wrong (jar before dependencies):

jar {
    manifest.attributes(
            // Class-Path won't contain "guava-15.0.jar"
            'Class-Path': configurations.runtime.files.collect { it.name }.join(' ')
    )
}

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'com.google.guava', name: 'guava', version: '15.0'
}

Correct (jar after dependencies):

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'com.google.guava', name: 'guava', version: '15.0'
}

jar {
    manifest.attributes(
            // results in "Class-Path: guava-15.0.jar"
            'Class-Path': configurations.runtime.files.collect { it.name }.join(' ')
    )
}
@stefcl
Copy link

stefcl commented Jan 9, 2014

Thanks a lot for sharing this, I spent many hours on this problem

@asimihsan
Copy link

This also helped me a great deal.

@khurramcheema
Copy link

thanks it helped

@amitport
Copy link

amitport commented Sep 4, 2014

for multiproject builds on gradle 2+, use:

task addDependToManifest << {
    if (!configurations.runtime.isEmpty()) {
        jar.manifest.attributes('Class-Path': configurations.runtime.collect { it.name }.join(' '))
    }
}
jar.dependsOn += addDependToManifest 

This assures addDependToManifest is called after the configuration phase, when all dependencies are calculated. (it also avoids an empty classpath line).

@simlegate
Copy link

👍

@amitport
Copy link

Updating my last comment— it's better to use jar.doFirst instead of creating a new task. This will avoid performing redundant operations when the jar is up-to-date.

jar {
    doFirst {
        manifest {
            if (!configurations.runtime.isEmpty()) {
                attributes('Class-Path': 
                                configurations.runtime.collect{it.toURI().toString()}.join(' '))
            }
        }
    }
}

@ciez
Copy link

ciez commented Mar 7, 2016

Thank you very much!

@enyesFang
Copy link

谢谢。

@karthikpromontory
Copy link

Thank you very very much! The Gradle stack trace is not very useful :)

@IvanLuchkin
Copy link

For anyone still facing this issue, this way of generating a Class-Path is more relevant:
'Class-Path': configurations.runtimeClasspath.files.collect { it.getName() }.join(' ')

@anirtek
Copy link

anirtek commented May 4, 2021

I need to use Class-Path variable into resolve as follows:

plugins {
    id 'java'
    id "io.swagger.core.v3.swagger-gradle-plugin" version "2.1.9"
}

// I have sections in order: repo, dependencies, test after this and then - 
 
jar {
    manifest {
        attributes(
                "Main-Class": "com.cloudian.hfs.StartHFS",
                'Class-Path': configurations.runtime.files.collect { it.name }.join(' ')
        )
    }
}

resolve {
    outputFileName = 'HFS-API'
    outputFormat = 'YAML'
    prettyPrint = 'TRUE'
    buildclasspath = 'Class-Path'
    resourcePackages = ['io.test']
    outputDir = file('test')
}

But when I run this, I am getting - Caused by: groovy.lang.MissingPropertyException: Could not set unknown property 'buildclasspath' for task ':resolve' of type io.swagger.v3.plugins.gradle.tasks.ResolveTask error. Anyone has any idea how can I resolve it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment