Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cycle now detected in SDK build #1124

Closed
mickaelistria opened this issue Jul 11, 2022 · 41 comments · Fixed by #1134
Closed

Cycle now detected in SDK build #1124

mickaelistria opened this issue Jul 11, 2022 · 41 comments · Fixed by #1134
Assignees
Milestone

Comments

@mickaelistria
Copy link
Contributor

The eclipse.platform.releng.aggregator build is now failing with

[ERROR] [ERROR] The projects in the reactor contain a cyclic reference: Edge between 'Vertex{label='org.eclipse.e4:org.eclipse.e4.ui.workbench.renderers.swt.cocoa:0.12.600-SNAPSHOT'}' and 'Vertex{label='eclipse.platform.ui:org.eclipse.e4.ui.workbench.renderers.swt:0.15.500-SNAPSHOT'}' introduces to cycle in the graph eclipse.platform.ui:org.eclipse.e4.ui.workbench.renderers.swt:0.15.500-SNAPSHOT --> eclipse.platform.ui:org.eclipse.e4.ui.widgets:1.3.0-SNAPSHOT --> org.eclipse.e4:org.eclipse.e4.ui.workbench.renderers.swt.cocoa:0.12.600-SNAPSHOT --> eclipse.platform.ui:org.eclipse.e4.ui.workbench.renderers.swt:0.15.500-

I think it's a consequence of recent changes in the lifecycle.
The error seems actually correct. So we should first investigate whether this can be solved on Platform side.

@mickaelistria
Copy link
Contributor Author

See https://ci.eclipse.org/platform/job/eclipse.platform.releng.aggregator/job/PR-390/2/ for a full build showing the error.

@laeubi
Copy link
Member

laeubi commented Jul 11, 2022

I think it's a consequence of recent changes in the lifecycle.

Yes, if you think this is wrong, it would be great to have a minimal example to investigate on this, while development I saw similar problems with the existing integration-tests when fragments involved, but I think the itest only cover one fragment and one host, so maybe we have here a case with multiple fragments but different hosts?

Can the aggregator job be run locally as well? It seem requiring a lot of submodules and setup of PGP stuff...

@mickaelistria mickaelistria self-assigned this Jul 11, 2022
@laeubi
Copy link
Member

laeubi commented Jul 11, 2022

Just from the code, I think this might be because org.eclipse.e4:org.eclipse.e4.ui.workbench.renderers.swt.cocoa has

Fragment-Host: org.eclipse.e4.ui.workbench.renderers.swt;bundle-version="[0.10.0,1.0.0)"

and in the p2 inf additionally requires swt cocoa fragment

requires.0.namespace = org.eclipse.equinox.p2.iu
requires.0.name = org.eclipse.swt.cocoa.macosx.x86_64

so it depends on two fragments and thus pull in two hosts, but that is just a guess here.

@mickaelistria
Copy link
Contributor Author

You can run the aggregator locally with a plain mvn clean verify against eclipse.platform.releng.aggregator but it requires to fetch all submodules. I believe we can reduce the case to a particular set of modules. I'll report if I find a reduced case.

@laeubi
Copy link
Member

laeubi commented Jul 11, 2022

Alright, I think the issue really is that org.eclipse.e4:org.eclipse.e4.ui.workbench.renderers.swt.cocoa explicitly pulls in org.eclipse.swt.cocoa.macosx.x86_64 (not sure for what this is good for as SWT itself should pull the fragment already).

This references Bug 361901 but I can't find anything about e4 in there, so maybe the p2inf here is a leftover?

@mickaelistria
Copy link
Contributor Author

Another, maybe simpler, example is visible at https://ci.eclipse.org/platform/job/eclipse.platform.ui/job/master/97/console . It can be reproduced locally with mvn clean verify -Pbuild-individual-bundles on eclipse.platform.ui Git repo.

@mickaelistria
Copy link
Contributor Author

Note that the error on https://ci.eclipse.org/platform/job/eclipse.platform.ui/job/master/97/console is actually more surprising and unexpected and looks like a bug at 1st glance. I didn't (yet?) find a reason why org.eclipse.e4.ui.css.swt would depend on org.eclipse.ui.monitoring.

@mickaelistria
Copy link
Contributor Author

So the error is

11:54:09.885 [ERROR] [ERROR] The projects in the reactor contain a cyclic reference: Edge between 'Vertex{label='org.eclipse.ui:org.eclipse.ui.monitoring.tests:1.2.0-SNAPSHOT'}' and 'Vertex{label='eclipse.platform.ui:org.eclipse.e4.ui.css.swt:0.14.600-SNAPSHOT'}' introduces to cycle in the graph eclipse.platform.ui:org.eclipse.e4.ui.css.swt:0.14.600-SNAPSHOT --> org.eclipse.ui:org.eclipse.ui.monitoring.tests:1.2.0-SNAPSHOT --> eclipse.platform.ui:org.eclipse.e4.ui.css.swt:0.14.600-SNAPSHOT @
11:54:09.885 [ERROR] The projects in the reactor contain a cyclic reference: Edge between 'Vertex{label='org.eclipse.ui:org.eclipse.ui.monitoring.tests:1.2.0-SNAPSHOT'}' and 'Vertex{label='eclipse.platform.ui:org.eclipse.e4.ui.css.swt:0.14.600-SNAPSHOT'}' introduces to cycle in the graph eclipse.platform.ui:org.eclipse.e4.ui.css.swt:0.14.600-SNAPSHOT --> org.eclipse.ui:org.eclipse.ui.monitoring.tests:1.2.0-SNAPSHOT --> eclipse.platform.ui:org.eclipse.e4.ui.css.swt:0.14.600-SNAPSHOT -> [Help 1]

As mentioned, I don't get why the org.eclipse.e4.ui.css.swt bundle would reference org.eclipse.ui.monitoring.tests. I mvn dependency:tree on org.eclipse.e4.ui.css.swt lists:

INFO] --- maven-dependency-plugin:3.3.0:tree (default-cli) @ org.eclipse.e4.ui.css.swt ---
[INFO] eclipse.platform.ui:org.eclipse.e4.ui.css.swt:eclipse-plugin:0.14.600-SNAPSHOT
[INFO] +- p2.eclipse.plugin:org.eclipse.osgi:eclipse-plugin:3.18.100.v20220710-1223:system
[INFO] +- p2.eclipse.plugin:org.apache.batik.constants:eclipse-plugin:1.14.0.v20210324-0332:system
[INFO] +- p2.eclipse.plugin:org.apache.batik.css:eclipse-plugin:1.14.0.v20210324-0332:system
[INFO] +- p2.eclipse.plugin:org.apache.batik.util:eclipse-plugin:1.14.0.v20210324-0332:system
[INFO] +- p2.eclipse.plugin:org.apache.batik.i18n:eclipse-plugin:1.14.0.v20210324-0332:system
[INFO] +- p2.eclipse.plugin:org.apache.xmlgraphics:eclipse-plugin:2.6.0.v20210409-0748:system
[INFO] +- p2.eclipse.plugin:org.w3c.dom.svg:eclipse-plugin:1.1.0.v201011041433:system
[INFO] +- p2.eclipse.plugin:org.w3c.dom.events:eclipse-plugin:3.0.0.draft20060413_v201105210656:system
[INFO] +- p2.eclipse.plugin:org.w3c.css.sac:eclipse-plugin:1.3.1.v200903091627:system
[INFO] +- p2.eclipse.plugin:org.apache.commons.io:eclipse-plugin:2.8.0.v20210415-0900:system
[INFO] +- p2.eclipse.plugin:org.apache.commons.logging:eclipse-plugin:1.2.0.v20180409-1502:system
[INFO] +- p2.eclipse.plugin:org.eclipse.core.commands:eclipse-plugin:3.10.200.v20220512-0851:system
[INFO] +- p2.eclipse.plugin:org.eclipse.equinox.common:eclipse-plugin:3.16.200.v20220710-1223:system
[INFO] +- p2.eclipse.plugin:org.eclipse.core.contenttype:eclipse-plugin:3.8.200.v20220613-1008:system
[INFO] +- p2.eclipse.plugin:org.eclipse.equinox.preferences:eclipse-plugin:3.10.100.v20220710-1223:system
[INFO] +- p2.eclipse.plugin:org.eclipse.equinox.registry:eclipse-plugin:3.11.100.v20211021-1418:system
[INFO] +- p2.eclipse.plugin:org.eclipse.core.jobs:eclipse-plugin:3.13.100.v20220613-1008:system
[INFO] +- p2.eclipse.plugin:org.eclipse.core.runtime:eclipse-plugin:3.26.0.v20220622-0417:system
[INFO] +- p2.eclipse.plugin:org.eclipse.equinox.app:eclipse-plugin:1.6.200.v20220710-1223:system
[INFO] +- p2.eclipse.plugin:org.eclipse.e4.ui.css.core:eclipse-plugin:0.13.300.v20220620-1314:system
[INFO] +- p2.eclipse.plugin:org.eclipse.swt:eclipse-plugin:3.121.0.v20220701-1002:system
[INFO] +- p2.eclipse.plugin:org.eclipse.jface:eclipse-plugin:3.26.100.v20220704-1424:system
[INFO] +- org.osgi:org.osgi.service.prefs:jar:1.1.2:compile
[INFO] |  \- org.osgi:osgi.annotation:jar:8.0.1:compile
[INFO] +- p2.eclipse.plugin:org.eclipse.swt.gtk.linux.x86_64:eclipse-plugin:3.121.0.v20220701-1002:system
[INFO] +- p2.eclipse.plugin:org.w3c.dom.smil:eclipse-plugin:1.0.1.v200903091627:system
[INFO] +- p2.eclipse.plugin:org.eclipse.swt.gtk.linux.ppc64le:eclipse-plugin:3.121.0.v20220701-1002:system
[INFO] +- p2.eclipse.plugin:org.eclipse.swt.gtk.linux.aarch64:eclipse-plugin:3.121.0.v20220701-1002:system
[INFO] +- p2.eclipse.plugin:org.eclipse.swt.win32.win32.x86_64:eclipse-plugin:3.121.0.v20220701-1002:system
[INFO] +- p2.eclipse.plugin:org.eclipse.swt.cocoa.macosx.x86_64:eclipse-plugin:3.121.0.v20220701-1002:system
[INFO] \- p2.eclipse.plugin:org.eclipse.swt.cocoa.macosx.aarch64:eclipse-plugin:3.121.0.v20220701-1002:system

So -at least for this case- I believe the bug is more probably in Tycho.

@mickaelistria
Copy link
Contributor Author

This error doesn't happen if the case is reduced to the only 2 involved modules. mvn -U clean verify -Pbuild-individual-bundles -pl bundles/org.eclipse.e4.ui.css.swt,tests/org.eclipse.ui.monitoring.tests/ is successful.

@laeubi
Copy link
Member

laeubi commented Jul 11, 2022

The tricky part is that if you just look at one bundle (or only a few) you will get a much more limited set of items (e.g. here you see everything is resolved to system or maven deps) while when you look at the reactor there is the situation that some are resolved to reactor projects witch can reference others as well.

The tricky part is, that e.g. a fragment must depend on its host, but if you require the host (e.g. swt) this project can not be build before the host and all its fragments are build. For this, this project then depends on SWT and all its fragments what complicates the whole thing a lot ...

@laeubi

This comment was marked as outdated.

@mickaelistria
Copy link
Contributor Author

I can see the the org.eclipse.ui.monitoring.tests is added to model dependencies as a result of iteration on closure.getDependencyProjects(project) (TychoMavenLifecycleParticipant line 144).

@laeubi
Copy link
Member

laeubi commented Jul 11, 2022

I have not analyzed that in detail, but my current guess is that the Slicer is even to eager here and we would need something that I have planned for supporting a nice dependency-tree, that is only collect the direct requirements of a project... as the transitives are accounted by maven already, and when we compute the target platform for the project.

@mickaelistria
Copy link
Contributor Author

we would need something that I have planned for supporting a nice dependency-tree

That would be a very good enhancement, but I don't think we need it here. I believe there is first a bug somewhere (in Tycho or Platform) as there really should be no reason for this dependency to be added, even with all the greediness we can think of.

@laeubi
Copy link
Member

laeubi commented Jul 11, 2022

even with all the greediness we can think of

monitoring.tests pull in a lot of stuff, and is a fragment, so if it get into to greedy it transitively might pull in things that lead to a cycle and maven only complains about the shortest-path, so currently I think ui.monitoring is actually referenced somewhere (transitivly) and then everything explodes ... but still this is a bug of tycho then I think, it would just be good to find a reproducer, but actually if we can't find one I'll try to fix it by using the platform.ui job.

Beside that... it would even make the code simpler and fast here :-)

@laeubi
Copy link
Member

laeubi commented Jul 11, 2022

The problem seems to be with the additional attachment of fragment to projects requiring the host.
While this works well with the SWT samples we have as itest and also simple cases, it fails here because a test-fragment obviously has not only a requirement to the host, but to other items as well... I'll try to find a minimal fix for this, if someone can came up with a reproducer test case it would be great, it must something like:

  • Bundle A and B
  • A test fragment of A that require bundle/import package B in some way (maybe involving SWT...)

@cdietrich
Copy link
Contributor

cdietrich commented Jul 12, 2022

problem shows up in Xtext too
https://ci.eclipse.org/xtext/job/xtext-eclipse/job/cd_testTycho30/179/console
need to check if is this is a real cycle though.
but why was this no problem before

@iloveeclipse
Copy link

4.25 SDK nightly is now also failed: https://ci.eclipse.org/releng/job/I-build-4.25/79/console

@mickaelistria
Copy link
Contributor Author

I'm debugging MavenProjectDependencyProcessor.computeProjectDependencies and the slicer behaves as expected. What's to blame about the eclipse.platform.ui failure involving a very unrelated fragment are the following lines

for (IInstallableUnit unit : avaiableIUs.query(QueryUtil.ALL_UNITS, null)) {
	if (isFragment(unit) && !projectUnits.contains(unit)) {
		Set<IInstallableUnit> fragmentsResult = slicer
				.computeDependencies(Collections.singleton(unit), collectionResult).toSet();
		if (fragmentsResult.size() > 1) {
			// at least one of the resolved items depend on the fragment
			dependentFragments.add(unit);
		}
	}
}

I fail at understanding what's the goal of this code, it doesn't seem to check whether the fragment is even related to dependency resolution.
FWIW, fragments are not to be treated as requirements by default. when building a dependency graph. I think we should just remove all the code that treats fragments as a special case.

@laeubi
Copy link
Member

laeubi commented Jul 12, 2022

@mickaelistria see comment here #1128 (comment) fragments are important for build-order (most prominent example is SWT) as they can contribute additional classes to the host (as tested by DependencyComputerTest.testFragments).

@mickaelistria
Copy link
Contributor Author

fragments are important for build-order

Current dependency graph is wrong because of this. Fragments do depend on their host, not the other way round. It's how p2 works, it's how Equinox works. SWT is a strange case here and that's why is has the ExtensibleAPI flag. Only for this strange case, fragments may be treated as dependencies of their host and not the other way round. But it's 1 corner case, here the general case is broken.

@laeubi
Copy link
Member

laeubi commented Jul 12, 2022

Fragments do depend on their host, not the other way round.

Yes and that's how it currently is implemented. The problem is that if a third party (test-fragment in this case) depends on other stuff (as in contrast a swt fragment do not depend on anything than SWT)...

@mickaelistria
Copy link
Contributor Author

Yes and that's how it currently is implemented.

The fact that the code iterates over all existing reactor fragments and add them under certain conditions, independently of whether their host is involved and of whether ExtensibleAPI is set is way too greedy. In the case of eclipse.platform.ui, the host is not even part of the initial dependencies and yet the fragment is added! Basically, only fragments whose host is in the dependency tree and does declare extensibleAPI should (maybe) be added, all other ones should be ignored.

@laeubi
Copy link
Member

laeubi commented Jul 12, 2022

The fact that the code iterates over all existing reactor fragments and add them under certain conditions, independently of whether their host is involved and of whether ExtensibleAPI is set is way too greedy. In the case of eclipse.platform.ui, the host is not even part of the initial dependencies and yet the fragment is added!

Fragments of the host are removed, fragments of a dependency are added because that something that has to "happen before", but is something not good to be expressed in a maven-model.

@laeubi
Copy link
Member

laeubi commented Jul 12, 2022

Nerveless I'm currently working on this and we have a test-case now for the "not-swt-case" so I think we will have a solution soon that satisfies both cases.

@mickaelistria
Copy link
Contributor Author

fragments of a dependency are added because that something that has to "happen before",

It's not what happens for eclipse.platform.ui. org.eclipse.ui.monitoring is not a dependency of org.eclipse.e4.ui.css.swt. The code I pasted above doesn't seems to make a difference between whether the host is in the dependency set of not, and later rules to remove fragments do not apply.
I suggest you run mvnDebug verify -DskipTests on eclipse.platform.ui and see by yourself what's going on. Fragment computations has a bug, I imagine some missing condition, querying a wrong set or whatever.

@laeubi
Copy link
Member

laeubi commented Jul 12, 2022

The above code computes the dependencies of one unit (the fragment) against all resolved project dependencies (the collectionResult) and then checks if at least more than one (the unit itself) is a result, and thus something satisfies what this fragment requires and thus is a perquisite.

As mentioned before, this might be too much and as it includes transitive items as well, but omitting them is not enough as I already verified), but @pzi-dsa example can reproduce the issue with just two bundles and one fragment, and that's what I'm currently focus on :-)

@mickaelistria
Copy link
Contributor Author

Any ETA when you think it can be fixed?

@laeubi
Copy link
Member

laeubi commented Jul 12, 2022

I have now made some tests and at least for the P2-Solver the Eclipse-ExtensibleAPI is not anything that is considered (and I can't even find anything in the P2 meta-data), so for the DependencyComputerTest.testFragments test the result is always the same that jface bundle has a dependency to swt+swt.gtk...

@mickaelistria
Copy link
Contributor Author

p2 entirely ignores Eclipse-ExtensibleAPI, p2 does not add fragments when adding a bundle. Fragments are usually added because they're required by a feature.

@laeubi
Copy link
Member

laeubi commented Jul 12, 2022

p2 does not add fragments when adding a bundle

The P2 Planner does it as a fragment has a requirement to its host and thus is part of "resolve all including requirements", see DependencyComputerTest.testFragments where JFace gets a requirement on swt and the swt fragment. P2 maybe do not do it when it installs a bundle, but at the moment I get the feeling if the solver finds it can include the fragment it does, when it would introduce a cycle it "breaks" the cycle by excluding the fragment. Sadly maven is not happy, even if the dependency is marked as optional :-\

@mickaelistria
Copy link
Contributor Author

It's not the p2 planner that adds fragments for SWT. In the "official" repo, there are p2 metadata that make the SWT bundle optionally require the fragment and p2 just honors that requirement. If you want to verify that, you can run p2 director on an empty directory and install some Platform bundle: unless this bundle is SWT or use similar trick, the fragments (eg tests) for this bundle wouldn't be installed.
The DependencyComputerTest is not an integration test. It actually doesn't work if you run a mvn clean verify on it; exactly because the fragments are not included by default. It does test the OSGi resolution which is implemented by Tycho and which has extra support for fragments, but this is way after p2 kicked in.

@laeubi
Copy link
Member

laeubi commented Jul 12, 2022

It's not the p2 planner that adds fragments for SWT. In the "official" repo, there are p2 metadata that make the SWT bundle optionally require the fragment and p2 just honors that requirement.

The test do not use a P2 inf, it works with or without an p2.inf

If you want to verify that, you can run p2 director on an empty directory and install some Platform bundle: unless this bundle is SWT or use similar trick, the fragments (eg tests) for this bundle wouldn't be installed.

I dont talk about install time, thats something different.

The DependencyComputerTest is not an integration test. It actually doesn't work if you run a mvn clean verify

You can't really "compile" the code, but it calls all the code that is used to resolve and inject dependencies and I can see that it injects the swt-fragments into the jface bundle.

It does test the OSGi resolution which is implemented by Tycho and which has extra support for fragments, but this is way after p2 kicked in.

OSGI resolution is performed much later in the VerifyClassPath Mojo.

@mickaelistria
Copy link
Contributor Author

I dont talk about install time, thats something different.

Not so different. p2 director == p2 planner. p2 does not greedily adds fragments unless there is something that instructs it to do so.

You can't really "compile" the code, but it calls all the code that is used to resolve and inject dependencies and I can see that it injects the swt-fragments into the jface bundle.

With 2.7.3, I didn't see that: a mvn dependency:tree verify -Dtycho-version=2.7.3 does not show the fragment in the dependencies of the jface bundle, and the compilation fails because .class file that do originate from that fragment are not accessible.

@laeubi
Copy link
Member

laeubi commented Jul 12, 2022

Not so different. p2 director == p2 planner. p2 does not greedily adds fragments unless there is something that instructs it to do so.

The difference is that Tycho do not use the p2 director, but uses the Projector see org.eclipse.tycho.p2.util.resolution.ProjectorResolutionStrategy.resolve(Map<String, String>, IProgressMonitor)

@laeubi
Copy link
Member

laeubi commented Jul 12, 2022

and the compilation fails because .class file that do originate from that fragment are not accessible.

The testcase only executes mvn validate -Dtycho-version=.... as far as I can see and this works, and the topologically sorted projects return it in the desired order and that order is affected by the Tycho code so I have no clue why it does not compile, nerveless it asserts that specific order. So if you think the Test is actually wrong, we should remove it.

@mickaelistria
Copy link
Contributor Author

I think the test is correct and test what it's expected to test correctly. But I think your interpretation of the test and what it implies for p2 and related expectations regarding fragment additions is wrong.

@laeubi
Copy link
Member

laeubi commented Jul 12, 2022

But you are right running it from the command and running it from the tests yields different results, that's undesirable :-(

@mickaelistria
Copy link
Contributor Author

But you are right running it from the command and running it from the tests yields different results, that's undesirable :-(

This is a unit test, it's meant to give input to the (OSGi) DependencyResolver, it's not meant to be used or run by CLI.

@laeubi
Copy link
Member

laeubi commented Jul 12, 2022

This is a unit test, it's meant to give input to the (OSGi) DependencyResolver, it's not meant to be used or run by CLI.

Sure but the order is checked before the DependencyResolver is called! So somehow the test assumes something is already ordered before the DependencyResolver do its work:

https://github.com/eclipse/tycho/blob/818b258e32a281e352b261ef5c605a2b538ddd77/tycho-core/src/test/java/org/eclipse/tycho/core/test/DependencyComputerTest.java#L209-L210

I have created #1131 to further investigate this.

laeubi pushed a commit that referenced this issue Jul 12, 2022
@laeubi
Copy link
Member

laeubi commented Jul 12, 2022

As the DependecyComputerTest is now fixed, we have one more org.eclipse.tycho.core.test.TychoTest.testFragment() that makes assumptions about build order because of fragments. What should be noted is, that this test uses the StubP2 resolver here and most probably do not reflect what actually happens in Tycho, so should we disable the test for now if we say that fragments should not be part of build-order computation?

@laeubi laeubi linked a pull request Jul 13, 2022 that will close this issue
@laeubi laeubi added this to the 3.0 milestone Sep 21, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants