diff --git a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/InstallableUnitSlicer.java b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/InstallableUnitSlicer.java index 30f2cd09c5..c73fb2f559 100644 --- a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/InstallableUnitSlicer.java +++ b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/InstallableUnitSlicer.java @@ -16,6 +16,7 @@ import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import org.codehaus.plexus.component.annotations.Component; import org.codehaus.plexus.component.annotations.Requirement; @@ -27,6 +28,7 @@ import org.eclipse.equinox.internal.p2.metadata.InstallableUnit; import org.eclipse.equinox.p2.metadata.IInstallableUnit; import org.eclipse.equinox.p2.metadata.IRequirement; +import org.eclipse.equinox.p2.metadata.expression.IMatchExpression; import org.eclipse.equinox.p2.query.CollectionResult; import org.eclipse.equinox.p2.query.IQueryResult; import org.eclipse.equinox.p2.query.IQueryable; @@ -73,15 +75,20 @@ public IQueryResult computeDependencies(Collection computeDirectDependencies(Collection rootIus, - IQueryable avaiableIUs) throws CoreException { + IQueryable avaiableIUs, Map profileProperties) throws CoreException { Collection result = new LinkedHashSet<>(); + IInstallableUnit selectionContext = InstallableUnit.contextIU(profileProperties); List collect = rootIus.stream().flatMap(iu -> iu.getRequirements().stream()).filter(req -> { for (IInstallableUnit unit : rootIus) { if (unit.satisfies(req)) { @@ -91,13 +98,16 @@ public IQueryResult computeDirectDependencies(Collection 0; for (IInstallableUnit iu : avaiableIUs.query(QueryUtil.ALL_UNITS, new NullProgressMonitor()).toSet()) { for (IRequirement requirement : collect) { - // Negative requirements should not create a dependency. - // If there is a filter, we need more context, e.g, see - // org.eclipse.equinox.internal.p2.director.Slicer.isApplicable(IRequirement) - // Failing that, we need to assume the filter isn't applicable. - if (requirement.getMax() != 0 && requirement.getFilter() == null && iu.satisfies(requirement)) { + IMatchExpression filter = requirement.getFilter(); + // If there is a filter, we need to evaluate + if (considerFilter && filter != null && !filter.isMatch(selectionContext)) { + // filter does not match... + continue; + } + if (iu.satisfies(requirement)) { result.add(iu); // TODO remove the requirement from the set so we only collect exactly one // provider for a requirement? diff --git a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/MavenProjectDependencyProcessor.java b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/MavenProjectDependencyProcessor.java index efa970ec09..a9cd8501cf 100644 --- a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/MavenProjectDependencyProcessor.java +++ b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/MavenProjectDependencyProcessor.java @@ -29,6 +29,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -72,19 +73,23 @@ public class MavenProjectDependencyProcessor { * Computes the {@link ProjectDependencyClosure} of the given collection of * projects. * - * @param projects the projects to include in the closure - * @param session the maven session for this request + * @param projects the projects to include in the closure + * @param session the maven session for this request + * @param profileProperties the profile properties to consider when evaluating + * filters, can be empty in which case a filter is + * always considered a match * @return the computed {@link ProjectDependencyClosure} * @throws CoreException if computation failed */ public ProjectDependencyClosure computeProjectDependencyClosure(Collection projects, - MavenSession session) throws CoreException { + MavenSession session, Function> profilePropertiesSupplier) + throws CoreException { Objects.requireNonNull(session); Map> projectIUMap = generator.getInstallableUnits(projects, session); Collection availableIUs = projectIUMap.values().stream().flatMap(Collection::stream) .collect(Collectors.toSet()); Map projectDependenciesMap = computeProjectDependencies(projects, - new CollectionResult<>(availableIUs), projectIUMap); + new CollectionResult<>(availableIUs), projectIUMap, profilePropertiesSupplier); Map iuProjectMap = new HashMap<>(); for (var entry : projectIUMap.entrySet()) { MavenProject mavenProject = entry.getKey(); @@ -138,14 +143,15 @@ public Collection getProjectUnits(MavenProject mavenProject) { * @throws CoreException if computation failed */ private Map computeProjectDependencies(Collection projects, - IQueryable avaiableIUs, Map> projectIUMap) + IQueryable avaiableIUs, Map> projectIUMap, + Function> profilePropertiesSupplier) throws CoreException { List errors = new CopyOnWriteArrayList<>(); Map result = new ConcurrentHashMap<>(); projects.parallelStream().unordered().takeWhile(nil -> errors.isEmpty()).forEach(project -> { try { ProjectDependencies projectDependencies = computeProjectDependencies(projectIUMap.get(project), - avaiableIUs); + avaiableIUs, profilePropertiesSupplier.apply(project)); result.put(project, projectDependencies); if (DUMP_DATA) { File file = new File(project.getBasedir(), "project-dependencies.xml"); @@ -182,12 +188,12 @@ private Map computeProjectDependencies(Collec * @throws CoreException if computation failed */ private ProjectDependencies computeProjectDependencies(Collection projectUnits, - IQueryable avaiableIUs) throws CoreException { + IQueryable avaiableIUs, Map profileProperties) throws CoreException { if (projectUnits.isEmpty()) { return EMPTY_DEPENDENCIES; } Set resolved = new LinkedHashSet<>( - slicer.computeDirectDependencies(projectUnits, avaiableIUs).toSet()); + slicer.computeDirectDependencies(projectUnits, avaiableIUs, profileProperties).toSet()); resolved.removeAll(projectUnits); // now we need to filter all fragments that we are a host! // for example SWT creates an explicit requirement to its fragments and we don't diff --git a/tycho-api/src/main/java/org/eclipse/tycho/TargetEnvironment.java b/tycho-api/src/main/java/org/eclipse/tycho/TargetEnvironment.java index 5e642f37b1..d5e2a81384 100644 --- a/tycho-api/src/main/java/org/eclipse/tycho/TargetEnvironment.java +++ b/tycho-api/src/main/java/org/eclipse/tycho/TargetEnvironment.java @@ -13,7 +13,6 @@ package org.eclipse.tycho; import java.util.ArrayList; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; @@ -88,7 +87,7 @@ public boolean isWindows() { * Returns the target environment as map. The keys are "osgi.ws", "osgi.os", and "osgi.arch". * This format is used by the p2 slicer to filter installable units by environments. * - * @return a new instance of {@link HashMap} with the target environment set + * @return a new instance of {@link LinkedHashMap} with the target environment set */ public Map toFilterProperties() { //for nicer debug output, use an ordered map here diff --git a/tycho-build/src/main/java/org/eclipse/tycho/build/TychoGraphBuilder.java b/tycho-build/src/main/java/org/eclipse/tycho/build/TychoGraphBuilder.java index 2b2ac745af..845f7eb96a 100644 --- a/tycho-build/src/main/java/org/eclipse/tycho/build/TychoGraphBuilder.java +++ b/tycho-build/src/main/java/org/eclipse/tycho/build/TychoGraphBuilder.java @@ -152,7 +152,10 @@ public Result build(MavenSession session) { try { ProjectDependencyClosure dependencyClosure; try { - dependencyClosure = dependencyProcessor.computeProjectDependencyClosure(projects, session); + // here we don't use filters, the worst that can happen is that we get more + // projects to consider... + dependencyClosure = dependencyProcessor.computeProjectDependencyClosure(projects, session, + always -> Map.of()); } catch (CoreException e) { log.error("Cannot resolve projects", e); return Result.error(graph, toProblems(e.getStatus(), new ArrayList<>())); diff --git a/tycho-core/src/main/java/org/eclipse/tycho/core/TychoProjectManager.java b/tycho-core/src/main/java/org/eclipse/tycho/core/TychoProjectManager.java index 1627792620..7b018482e9 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/core/TychoProjectManager.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/core/TychoProjectManager.java @@ -43,6 +43,7 @@ import org.eclipse.tycho.ExecutionEnvironmentConfiguration; import org.eclipse.tycho.ReactorProject; import org.eclipse.tycho.ResolvedArtifactKey; +import org.eclipse.tycho.TargetEnvironment; import org.eclipse.tycho.TargetPlatform; import org.eclipse.tycho.TargetPlatformService; import org.eclipse.tycho.TychoConstants; @@ -143,6 +144,18 @@ public void readExecutionEnvironmentConfiguration(ReactorProject project, Execut } } + public Map getProfileProperties(MavenProject project) { + return getProfileProperties(project, TargetEnvironment.getRunningEnvironment()); + } + + public Map getProfileProperties(MavenProject project, TargetEnvironment environment) { + TargetPlatformConfiguration configuration = getTargetPlatformConfiguration(project); + Map properties = environment.toFilterProperties(); + properties.put("org.eclipse.update.install.features", "true"); + properties.putAll(configuration.getProfileProperties()); + return properties; + } + public TargetPlatformConfiguration getTargetPlatformConfiguration(MavenProject project) { ReactorProject reactorProject = DefaultReactorProject.adapt(project); return reactorProject.computeContextValue(CTX_TARGET_PLATFORM_CONFIGURATION, diff --git a/tycho-core/src/main/java/org/eclipse/tycho/core/maven/TychoMavenLifecycleParticipant.java b/tycho-core/src/main/java/org/eclipse/tycho/core/maven/TychoMavenLifecycleParticipant.java index 2c0377b850..e6dbe4089f 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/core/maven/TychoMavenLifecycleParticipant.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/core/maven/TychoMavenLifecycleParticipant.java @@ -148,7 +148,7 @@ public void afterProjectsRead(MavenSession session) throws MavenExecutionExcepti if (lazyProjects.size() > 0) { try { ProjectDependencyClosure closure = dependencyProcessor.computeProjectDependencyClosure(projects, - session); + session, projectManager::getProfileProperties); for (MavenProject project : lazyProjects) { if (projectManager.getTychoProject(project).isEmpty()) { //do not inject additional dependencies for non Tycho managed projects! diff --git a/tycho-its/src/test/java/org/eclipse/tycho/test/justjCycle/JustJCycleTest.java b/tycho-its/src/test/java/org/eclipse/tycho/test/justjCycle/JustJCycleTest.java index bed781a3e4..0817ef9b44 100644 --- a/tycho-its/src/test/java/org/eclipse/tycho/test/justjCycle/JustJCycleTest.java +++ b/tycho-its/src/test/java/org/eclipse/tycho/test/justjCycle/JustJCycleTest.java @@ -21,9 +21,7 @@ public class JustJCycleTest extends AbstractTychoIntegrationTest { @Test public void testCustomBundleParent() throws Exception { Verifier verifier = getVerifier("justj-cycle"); - verifier.setForkJvm(false); - verifier.setSystemProperty("user.home", System.getProperty("user.home")); - verifier.executeGoal("verify"); + verifier.executeGoal("initialize"); verifier.verifyErrorFreeLog(); } }