From 62523f101b09d3d840eb90c2a17e056f3e54c7ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Sun, 17 Dec 2023 12:26:00 +0100 Subject: [PATCH] Add support for resolving target platform projects Currently target-platform projects do not have any resolved dependencies, this has a few disadvantages: - if one want to see the dependency tree it is empty - if one wants to mirror a target platform this can't be performed This adds support for target platform projects to resolve and have their dependencies injected to support such advanced use-cases. --- .../core/osgitools/TargetPlatformProject.java | 97 +++++++++++++++++++ .../p2resolver/P2DependencyResolver.java | 70 ++++++++----- 2 files changed, 142 insertions(+), 25 deletions(-) create mode 100644 tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/TargetPlatformProject.java diff --git a/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/TargetPlatformProject.java b/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/TargetPlatformProject.java new file mode 100644 index 0000000000..f9c2bba376 --- /dev/null +++ b/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/TargetPlatformProject.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 2023 Christoph Läubrich and others. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package org.eclipse.tycho.core.osgitools; + +import java.io.File; +import java.util.List; +import java.util.Set; + +import org.apache.maven.execution.MavenSession; +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.component.annotations.Component; +import org.eclipse.equinox.p2.metadata.IArtifactKey; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.tycho.ArtifactKey; +import org.eclipse.tycho.DefaultArtifactKey; +import org.eclipse.tycho.DependencyArtifacts; +import org.eclipse.tycho.PackagingType; +import org.eclipse.tycho.ReactorProject; +import org.eclipse.tycho.TargetPlatform; +import org.eclipse.tycho.TychoConstants; +import org.eclipse.tycho.core.ArtifactDependencyVisitor; +import org.eclipse.tycho.core.ArtifactDependencyWalker; +import org.eclipse.tycho.core.TychoProject; +import org.eclipse.tycho.core.osgitools.targetplatform.DefaultDependencyArtifacts; +import org.eclipse.tycho.core.resolver.target.ArtifactTypeHelper; +import org.eclipse.tycho.model.Feature; +import org.eclipse.tycho.model.ProductConfiguration; +import org.eclipse.tycho.model.UpdateSite; +import org.eclipse.tycho.targetplatform.P2TargetPlatform; + +@Component(role = TychoProject.class, hint = PackagingType.TYPE_ECLIPSE_TARGET_DEFINITION) +public class TargetPlatformProject extends AbstractTychoProject { + + @Override + public ArtifactDependencyWalker getDependencyWalker(ReactorProject project) { + return new ArtifactDependencyWalker() { + + @Override + public void walk(ArtifactDependencyVisitor visitor) { + + } + + @Override + public void traverseUpdateSite(UpdateSite site, ArtifactDependencyVisitor visitor) { + + } + + @Override + public void traverseProduct(ProductConfiguration productConfiguration, ArtifactDependencyVisitor visitor) { + + } + + @Override + public void traverseFeature(File location, Feature feature, ArtifactDependencyVisitor visitor) { + + } + }; + } + + @Override + public ArtifactKey getArtifactKey(ReactorProject project) { + return new DefaultArtifactKey("target", project.getArtifactId(), project.getVersion()); + } + + @Override + public DependencyArtifacts getDependencyArtifacts(ReactorProject reactorProject) { + return reactorProject.computeContextValue(TychoConstants.CTX_DEPENDENCY_ARTIFACTS, () -> { + DefaultDependencyArtifacts artifacts = new DefaultDependencyArtifacts(reactorProject); + MavenSession mavenSession = getMavenSession(reactorProject); + MavenProject mavenProject = getMavenProject(reactorProject); + TargetPlatform targetPlatform = dependencyResolver.computePreliminaryTargetPlatform(mavenSession, + mavenProject); + if (targetPlatform instanceof P2TargetPlatform p2) { + Set installableUnits = p2.getInstallableUnits(); + for (IInstallableUnit iu : installableUnits) { + for (IArtifactKey key : iu.getArtifacts()) { + ArtifactKey artifactKey = ArtifactTypeHelper.toTychoArtifactKey(iu, key); + artifacts.addArtifactFile(artifactKey, () -> targetPlatform.getArtifactLocation(artifactKey), + List.of(iu)); + } + } + } + return artifacts; + }); + } + +} diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/P2DependencyResolver.java b/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/P2DependencyResolver.java index 87b6c64097..cab618fc58 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/P2DependencyResolver.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/P2DependencyResolver.java @@ -62,6 +62,7 @@ import org.eclipse.tycho.MavenDependencyDescriptor; import org.eclipse.tycho.MavenRepositoryLocation; import org.eclipse.tycho.OptionalResolutionAction; +import org.eclipse.tycho.PackagingType; import org.eclipse.tycho.ReactorProject; import org.eclipse.tycho.TargetEnvironment; import org.eclipse.tycho.TargetPlatform; @@ -83,6 +84,7 @@ import org.eclipse.tycho.core.resolver.P2ResolutionResult; import org.eclipse.tycho.core.resolver.P2Resolver; import org.eclipse.tycho.core.resolver.P2ResolverFactory; +import org.eclipse.tycho.core.resolver.shared.IncludeSourceMode; import org.eclipse.tycho.core.resolver.shared.PomDependencies; import org.eclipse.tycho.helper.PluginRealmHelper; import org.eclipse.tycho.p2.metadata.DependencyMetadataGenerator; @@ -95,6 +97,8 @@ import org.eclipse.tycho.repository.registry.facade.ReactorRepositoryManager; import org.eclipse.tycho.resolver.P2MetadataProvider; import org.eclipse.tycho.targetplatform.TargetDefinitionFile; +import org.eclipse.tycho.targetplatform.TargetPlatformArtifactResolver; +import org.eclipse.tycho.targetplatform.TargetResolveException; @Component(role = DependencyResolver.class, hint = P2DependencyResolver.ROLE_HINT, instantiationStrategy = "per-lookup") public class P2DependencyResolver implements DependencyResolver, Initializable { @@ -149,22 +153,26 @@ public class P2DependencyResolver implements DependencyResolver, Initializable { @Override public void setupProjects(final MavenSession session, final MavenProject project, final ReactorProject reactorProject) { - TargetPlatformConfiguration configuration = projectManager.getTargetPlatformConfiguration(project); - List environments = configuration.getEnvironments(); - Collection metadataMap = getDependencyMetadata(session, project, environments, - OptionalResolutionAction.OPTIONAL); - Map> typeMap = new TreeMap<>(); - for (DependencyMetadataType type : DependencyMetadataType.values()) { - typeMap.put(type, new LinkedHashSet<>()); - } - for (IDependencyMetadata metadata : metadataMap) { - typeMap.forEach((key, value) -> value.addAll(metadata.getDependencyMetadata(key))); - } Set initial = new HashSet<>(); - typeMap.forEach((key, value) -> { - reactorProject.setDependencyMetadata(key, value); - initial.addAll(value); - }); + if (PackagingType.TYPE_ECLIPSE_TARGET_DEFINITION.equals(project.getPackaging())) { + //Target projects do not have any (initial) dependency metadata + } else { + TargetPlatformConfiguration configuration = projectManager.getTargetPlatformConfiguration(project); + List environments = configuration.getEnvironments(); + Collection metadataMap = getDependencyMetadata(session, project, environments, + OptionalResolutionAction.OPTIONAL); + Map> typeMap = new TreeMap<>(); + for (DependencyMetadataType type : DependencyMetadataType.values()) { + typeMap.put(type, new LinkedHashSet<>()); + } + for (IDependencyMetadata metadata : metadataMap) { + typeMap.forEach((key, value) -> value.addAll(metadata.getDependencyMetadata(key))); + } + typeMap.forEach((key, value) -> { + reactorProject.setDependencyMetadata(key, value); + initial.addAll(value); + }); + } reactorProject.setDependencyMetadata(DependencyMetadataType.INITIAL, initial); } @@ -202,23 +210,35 @@ public TargetPlatform computePreliminaryTargetPlatform(MavenSession mavenSession logger.debug("Computing preliminary target platform for " + mavenProject); List reactorProjects = DefaultReactorProject.adapt(mavenSession); TargetPlatformConfiguration configuration = projectManager.getTargetPlatformConfiguration(mavenProject); - ExecutionEnvironmentConfiguration ee = projectManager.getExecutionEnvironmentConfiguration(mavenProject); - TargetPlatformConfigurationStub tpConfiguration = new TargetPlatformConfigurationStub(); + ExecutionEnvironmentConfiguration ee = projectManager.getExecutionEnvironmentConfiguration(mavenProject); for (ArtifactRepository repository : mavenProject.getRemoteArtifactRepositories()) { addEntireP2RepositoryToTargetPlatform(repository, tpConfiguration); } - tpConfiguration.setEnvironments(configuration.getEnvironments()); - for (TargetDefinitionFile target : configuration.getTargets()) { - tpConfiguration.addTargetDefinition(target); - } - tpConfiguration.addFilters(configuration.getFilters()); - tpConfiguration.setIncludeSourceMode(configuration.getTargetDefinitionIncludeSourceMode()); - tpConfiguration - .setIgnoreLocalArtifacts(configuration.getIgnoreLocalArtifacts() == LocalArtifactHandling.ignore); tpConfiguration.setReferencedRepositoryMode(configuration.getReferencedRepositoryMode()); + if (PackagingType.TYPE_ECLIPSE_TARGET_DEFINITION.equals(mavenProject.getPackaging())) { + //for target definition project itself we only want the main target to be considered + try { + File targetFile = TargetPlatformArtifactResolver.getMainTargetFile(mavenProject); + TargetDefinitionFile targetDefinitionFile = TargetDefinitionFile.read(targetFile); + tpConfiguration.addTargetDefinition(targetDefinitionFile); + } catch (TargetResolveException e) { + logger.warn("Can't read main target definition file from project " + mavenProject.getId(), e); + } + //also we always want to ignore sources + tpConfiguration.setIncludeSourceMode(IncludeSourceMode.ignore); + //and local artifacts + tpConfiguration.setIgnoreLocalArtifacts(true); + } else { + for (TargetDefinitionFile target : configuration.getTargets()) { + tpConfiguration.addTargetDefinition(target); + } + tpConfiguration.setIncludeSourceMode(configuration.getTargetDefinitionIncludeSourceMode()); + tpConfiguration.setIgnoreLocalArtifacts( + configuration.getIgnoreLocalArtifacts() == LocalArtifactHandling.ignore); + } return tpFactory.createTargetPlatform(tpConfiguration, ee, reactorProjects, reactorProject); }); }