Skip to content

Question regarding build classpath resolution problem with Tycho 4 #4653

@zladdi

Description

@zladdi

Hello,

Context

At the company I work for, we have a long-standing Tycho project (> 10 years) that has some peculiarities. And before I ask the development team (which I am not part of) to address certain issues with the project setup, I wanted to ask here to get some clarifications.

The project consists of many (we are talking 100-eds of) Eclipse plugins, some of which may reference (via manifest entry Require-Bundle) each other. In some cases, the dependee plugin exports packages from an embedded JAR (whose relative path is specified in the Bundle-Classpath entry of its manifest) which are then imported and classes from which are referenced in the dependent's bundle.

The problem

Up until Tycho 3.0.5, the above setup built without problems and worked during runtime, too. But we now how to upgrade to Tycho 4 (at least 4.0.8, but we plan on getting the latest, which is 4.0.10 at time of writing). However, we cannot do this, as we run into build classpath problems - i.e. the packages/classes referenced by a plugin that reside in JARs embedded in a required bundle cannot be resolved anymore (i.e. errors of the form The import x.y.z cannot be resolved and The type x.y.z.T1 cannot be resolved. It is indirectly referenced from required type u.v.w.T2).

Small reproducible example

To demonstrate the exact problem and error messages we get, I have created a quite small (but not minimal) reproducible example here: https://github.com/zladdi/tycho-4-classpath-issue/

The setup is as follows:

  • Plugin dependee uses classes from commons-lang3-3.17.0.jar, which is embedded in the plugin under lib/ (i.e. Bundle-ClassPath: lib/commons-lang3-3.17.0.jar), and exports the package org.apache.commons.lang3 (via Export-Package entry in the plugin's manifest)
  • Plugin dependent requires the plugin dependee (manifest entry Require-Bundle: dependee) and imports the package org.apache.commons.lang3 (manifest entry Import-Package: org.apache.commons.lang3)
  • Within the dependent plugin there is some code referencing directly and indirectly (via return type of a class from plugin dependee) classes from package org.apache.commons.lang3
  • There is a parent/aggregator POM that contains the Tycho configuration and is used to build both plugins in one Reactor build

Attempting to build the the parent/aggregator project with the following command:

mvn -B clean verify -DskipTests -Dtycho.localArtifacts=ignore

fails with Tycho 4 (but succeeds with Tycho 3.0.5 and e.g. 2.7.5, for that matter) with the following errors, where <parent-of-repo> is the folder containing this repository/the aggregator/parent project:

[ERROR] Failed to execute goal org.eclipse.tycho:tycho-compiler-plugin:4.0.10:compile (default-compile) on project dependent: Compilation failure: Compilation failure:
[ERROR] <parent-of-repo>/tycho-4-classpath-issue/dependent/src/DependentExample.java:[1]
[ERROR]         import org.apache.commons.lang3.StringUtils;
[ERROR]                ^^^^^^^^^^
[ERROR] The import org.apache cannot be resolved
[ERROR] <parent-of-repo>/tycho-4-classpath-issue/dependent/src/DependentExample.java:[9]
[ERROR]         boolean sIsBlank = StringUtils.isBlank(s);
[ERROR]                            ^^^^^^^^^^^
[ERROR] StringUtils cannot be resolved
[ERROR] <parent-of-repo>/tycho-4-classpath-issue/dependent/src/DependentExample.java:[12]
[ERROR]         System.out.println("bitfield is: " + dependeeEx.getBitField());
[ERROR]                                              ^^^^^^^^^^^^^^^^^^^^^^^^
[ERROR] The type org.apache.commons.lang3.BitField cannot be resolved. It is indirectly referenced from required type dependee.DependeeExample
[ERROR] <parent-of-repo>/tycho-4-classpath-issue/dependent/src/DependentExample.java:[12]
[ERROR]         System.out.println("bitfield is: " + dependeeEx.getBitField());
[ERROR]                                                         ^^^^^^^^^^^
[ERROR] The method getBitField() from the type DependeeExample refers to the missing type BitField
[ERROR] 4 problems (4 errors)
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
[ERROR]
[ERROR] After correcting the problems, you can resume the build with the command
[ERROR]   mvn <args> -rf :dependent

A few notes:

  • As in the example, we are using the eager resolver, i.e.
<plugin>
    <groupId>org.eclipse.tycho</groupId>
    <artifactId>target-platform-configuration</artifactId>
    <version>${tycho-version}</version>
    <configuration>
        <requireEagerResolve>true</requireEagerResolve>
    ...

While the example project would build successfully when omitting this configuration option, the actual project won't. The reason for this is that with Tycho 4 we get an error of the form The projects in the reactor contain a cyclic reference: ... when using the default resolver. We will address this problem separately with the development team, but it could take quite some time until they will actually address this. That is why we switched to using <requireEagerResolve>true</requireEagerResolve>, which does not report that problem, in the first place

  • As mentioned above, this is a long-standing project, and the approach taken back in the day was a manifest-first approach. We want to keep it that way, as this would require quite some rework on the project, which, as mentioned before, is rather big in terms of number of plugins.

Some more info acquired during build debugging

I noticed the following log output when running the above Maven command with the -X switch

[DEBUG] Cannot fetch artifact info for dependee and location <parent-of-repo>/tycho-4-classpath-issue/ependee/target/dependee-0.0.1-SNAPSHOT.jar, using raw jar item for classpath

This message is logged at tycho-core-4.0.10.jar:org.eclipse.tycho.core.osgitools.OsgiBundleProject line 234. I stepped through the build in the debugger to find out why this happens. At OsgiBundleProject line 217, there is the code that fetches the artifact descriptor for a given dependency:

ArtifactDescriptor otherArtifact = getArtifact(artifacts, location, entry.getSymbolicName());

When building dependent and the entry in above code corresponds to dependee, the return value of getArtifact is null, which leads to above debug-level log message. Digging deeper into getArtifact, the key under which dependee is stored in a (linked hash) map that holds all artifacts is <parent-of-repo>/tycho-4-classpath-issue/dependee, i.e. the Maven project's base directory, while the lookup key is <parent-of-repo>/tycho-4-classpath-issue/dependee/target/dependee-0.0.1-SNAPSHOT.jar, i.e. the path to the Maven project's target artifact. As such, the lookup in getArtifact will not find the location of dependee and return null.

Question

Could someone please explain if the change in build classpath resolution behavior from Tycho 3 to 4 for above use case is intentional or a bug?

  • And if it is intentional: is there a way to get the constellation of class/package references working in Tycho 4 with the eager resolver, besides the obvious solutions of refactoring to not reference classes within an embedded JAR of one plugin by another plugin or fixing the circular-dependency problem encountered by the new default resolver?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions