bndtools / bnd

Bnd/Bndtools. Tooling to build OSGi bundles including Eclipse, Maven, and Gradle plugins.
https://bndtools.org
Other
532 stars 305 forks source link

Gradle plugin without Bnd Workspace: Classpath is empty #3177

Closed jmini closed 5 years ago

jmini commented 5 years ago

I am trying to use biz.aQute.bnd.builder to generate an OSGi manifest (the OSGi Plugin is now deprecated). I am following the Replacing use of Gradle's deprecated OSGi Plugin section.

The simple project can be found here: create-manifest-example

I have following source structure:

src/
├── main/java
│   └── fr/jmini/bnd/simple
│        ├── Library.java
│        └── internal
│            └── LibraryImpl.java
└── test/java
    └── fr/jmini/bnd/simple
         └── LibraryTest.java

And the build.gradle contains:

buildscript {
  repositories {
    mavenCentral()
  }
  dependencies {
    classpath 'biz.aQute.bnd:biz.aQute.bnd.gradle:4.2.0'
  }
}

plugins {
    id 'java'
    id 'biz.aQute.bnd.builder' version '4.2.0'
}

// ...

jar {
    bnd ('Bundle-Name': 'fr.jmini.bnd.simple',
         'Private-Package': 'fr.jmini.bnd.simple.internal',
         'Bundle-Vendor': 'Jmini',
         'Bundle-Description': 'Simple Experiment Bundle',
         'Bundle-DocURL': 'https://www.jmini.fr')
}

But when I run gradle I this this output:

> Task :jar
warning: Classpath is empty. Private-Package (-privatepackage) and Export-Package can only expand from the classpath when there is one
warning: Unused Private-Package instructions, no such package(s) on the class path: [fr.jmini.bnd.simple.internal]

And the "Private-Package" in the generated MANIFEST.MF is wrong:

Manifest-Version: 1.0
Bnd-LastModified: 1557380159597
Bundle-Description: Simple Experiment Bundle
Bundle-DocURL: https://www.jmini.fr
Bundle-ManifestVersion: 2
Bundle-Name: fr.jmini.bnd.simple
Bundle-SymbolicName: create-manifest-example
Bundle-Vendor: Jmini
Bundle-Version: 1.0.0.SNAPSHOT
Created-By: 1.8.0_161 (Oracle Corporation)
Private-Package: fr.jmini.bnd.simple,fr.jmini.bnd.simple.internal
Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))"
Tool: Bnd-4.2.0.201903051501

What did I miss?

bjhargrave commented 5 years ago

You do not need to (and should not) specify Package-Private here. The classes in the bundle will be the normal contents of the jar as built by the standard gradle jar task. The biz.aQute.bnd.builder plugin supplements the normal gradle jar task to build the manifest and process any bnd instructions. Since the jar task has already added all the packages in the project, Bnd cannot add it again.

jmini commented 5 years ago

Since the jar task has already added all the packages in the project

Where is this done?


Package-Private is just an example taken from the "Replacing use of Gradle's deprecated OSGi Plugin" section.


What I would like to try: Specify that package fr.jmini.bnd.simple is API (and should be exported from my bundle) and that package fr.jmini.bnd.simple.internal is not?

I am new to Bnd but I have done some OSGi development with Eclipse PDE back in the days.

Thank you in advance for your help.

bjhargrave commented 5 years ago

Where is this done?

By the normal operation of the Jar task. See https://docs.gradle.org/current/dsl/org.gradle.api.tasks.bundling.Jar.html.

Package-Private is just an example taken from the "Replacing use of Gradle's deprecated OSGi Plugin" section.

You are right. I will remove that from the example. It was to show a straight forward migration not what you should do.

What I would like to try: Specify that package fr.jmini.bnd.simple is API (and should be exported from my bundle) and that package fr.jmini.bnd.simple.internal is not?

The best thing is to add @Export and @Version annotations to fr/jmini/bnd/simple/package-info.java and then Bnd will automatically export the package while the other packages will not be exported.

jmini commented 5 years ago

Thank you a lot for your feedback!

With Export-Package in the gradle file:

jar {
    bnd ('Bundle-Name': 'fr.jmini.bnd.simple',
         'Export-Package': 'fr.jmini.bnd.simple',
         'Bundle-Vendor': 'Jmini',
         'Bundle-Description': 'Simple Experiment Bundle',
         'Bundle-DocURL': 'https://www.jmini.fr')
}

I have a warning in the log:

> Task :jar
warning: Classpath is empty. Private-Package (-privatepackage) and Export-Package can only expand from the classpath when there is one

But the Manifest looks as expected:

Bundle-Version: 1.0.0.SNAPSHOT
Created-By: 1.8.0_161 (Oracle Corporation)
Export-Package: fr.jmini.bnd.simple;version="1.0.0"
Private-Package: fr.jmini.bnd.simple.internal

I will try to work with @Export on package info.

Thank you a lot for your help!

bjhargrave commented 5 years ago

I have a warning in the log:

The Export-Package instruction tells Bnd to add the package to the bundle. But the package is already in the bundle and there is nowhere to find the package, hence the warning. You would use -exportcontents instead here since it assumes the packages are already in the bundle (which it is). But using the @Export annotation is even better!