eclipse / buildship

The Eclipse Plug-ins for Gradle project.
528 stars 167 forks source link

Project Module Dependencies Are not Correctly Used #1266

Closed DaGeRe closed 9 months ago

DaGeRe commented 11 months ago

When importing Kieker (https://github.com/kieker-monitoring/kieker) on Fedora 38, eclipse keeps displaying compile errors. The project compiles fine with pure Gradle (e.g., ./gradlew assemble).

Expected Behavior

I expect a multi module project to be importable and to recognize dependencies between modules. That means, if one build.gradle contains

dependencies {
    implementation project(':kieker-common')

the kieker-common project should be recognized as a dependency and it should be possible to use classes from this project.

Current Behavior

The dependency is not fully recognized. The dependencies are marked as errorneous: grafik but at the same time, the build path seems to contain the project dependency: grafik Surprisingly, if I go to configuration and hit F3, the correct class is opened - so at some level, the dependency seems to be recognized.

Cleaning, refreshing, closing the project and opening it again, deleting .metadata, ~/.gradle and .settings and importing again all did not solve the problem. Furthermore, this also occurs on a minimized version of the project, including only the two modules kieker-common and kieker-monitoring.

Context

I am trying to run main classes in the Kieker project. This worked a few versions ago.

Steps to Reproduce

Your Environment

Fedora 38, eclipse Version: 2023-09 (4.29.0) Build id: 20230907-1323, buildship 3.1.7.v20230428-1350

I've also tried 2022-03 and 2021-09, but both did not fix the problem.

oleosterhagen commented 10 months ago

In /kieker-monitoring/build.gradle the dependency to kieker-common is included two times:

dependencies {
    implementation project(':kieker-common')
    // ...
    testImplementation project (path: ':kieker-common', configuration: 'testArchives')
    // ...
}

This is no problem when dependencies are included as libraries. (When you close the project kieker-common, Gradle builds the two JAR files which then can be properly referenced by Eclipse.)

But as a project dependency Eclipse supports only one reference to the same project. You could remove the additional test dependency from the classpath when kieker-common is included as a project dependency by adding this to /kieker-monitoring/build.gradle:

plugins {
    id 'java'
    id 'java-library'
    id 'eclipse'
}
//...
eclipse {
    classpath {
        file {
            whenMerged { classpath ->
                classpath.entries.removeAll { entry ->
                    entry instanceof org.gradle.plugins.ide.eclipse.model.ProjectDependency
                        && entry.path == '/kieker-common'
                        && entry.entryAttributes['test']
                }
            }
        }   
    }
}

Now, non-test dependencies from project kieker-monitoring to kieker-common are resolved.

By default, test sources from one Eclipse project are not exposed to other projects (visualized by without test code in the project explorer). To expose the test classes, add this to /kieker-common/build.gradle:

plugins {
    id 'java'
    id 'eclipse'
}
// ...
eclipse {
    classpath {
        containsTestFixtures = true
    }
}

See also https://github.com/eclipse/buildship/issues/1206

DaGeRe commented 10 months ago

Thanks for the hint. For kieker-common and kieker-monitoring, it works to include the whenMerged definition to the classpath.

Just closing the project unfortunately does not work:

grafik

Unfortunately, Kieker contains more modules, and for kieker-analysis, it does not work (I've uploaded the partial fix in https://github.com/kieker-monitoring/kieker/tree/KIEKER-1966-2). Here, we have the same situation with two references to kieker-common, one of them being its testArchives: https://github.com/kieker-monitoring/kieker/blob/bcb811d0cd8a58d2baa4e5d684c35f5f6e0ca6f7/kieker-analysis/build.gradle#L58 This is not recognized correctly, even with the containsTextFixture in /kieker-common/build.gradle and the whenMerged both in /kieker-monitoring/build.gradle and /kieker-analysis/build.gradle: grafik

Additionally, it seems like the teetime dependencies are not correctly identified: https://github.com/kieker-monitoring/kieker/blob/bcb811d0cd8a58d2baa4e5d684c35f5f6e0ca6f7/kieker-analysis/build.gradle#L62 which results in test classes of teetime being missing: grafik

This suprises me, since compiling Kieker works fine with just Gradle, but in eclipse, its not possible to build (and I'm sure it worked a year ago - but since I've updated eclipse, it neither works with the currenct nor with older eclipse versions).

oleosterhagen commented 10 months ago

With your changes I can see no more problems in kieker-analysis.

With commit https://github.com/oleosterhagen/kieker/commit/48be0261cf4edb247fc736d5c4cd2801e87cb0a9 I have completed the configuration. The Gradle project should now import without compile errors. (Unfortunately the Java builder picks some files in /kieker-monitoring/test-resources. But this a different issue.)

In some places two project dependencies must be taken into account:

[...]
classpath.entries.removeAll { entry ->
    entry instanceof org.gradle.plugins.ide.eclipse.model.ProjectDependency
        && ['/kieker-common', '/kieker-tools'].contains(entry.path) 
        && entry.entryAttributes['test']
}

When you still have problems and the invocation of Gradle > Refresh Gradle Project does not help, you can try these steps:

  1. Remove the projects from the Eclipse workspace
  2. Delete all .classpath and .project files and all .settings folders
  3. Import the Gradle project again in Eclipse
DaGeRe commented 9 months ago

Thanks a lot for the fix! The described problem is fixed by your commit, and we additionally fixed the test-resources problem, so with https://github.com/kieker-monitoring/kieker/pull/419, Kieker is fully buildable with eclipse again.

oleosterhagen commented 9 months ago

@DaGeRe Thank you for your feedback and closing the issue.

When I have some more time, I will try to improve Gradle so that this case is better supported and does not need a manual adjustment of the classpath.