123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- /*
- * Copyright 2002-2015 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package io.spring.gradle.convention
- import org.gradle.api.*
- import org.gradle.api.artifacts.Configuration
- import org.gradle.api.artifacts.ProjectDependency;
- import org.gradle.api.artifacts.maven.Conf2ScopeMapping
- import org.gradle.api.plugins.MavenPlugin
- import org.gradle.plugins.ide.eclipse.EclipsePlugin
- import org.gradle.plugins.ide.idea.IdeaPlugin
- import org.gradle.api.invocation.*
- /**
- * Gradle plugin that allows projects to merged together. Primarily developed to
- * allow Spring to support multiple incompatible versions of third-party
- * dependencies (for example Hibernate v3 and v4).
- * <p>
- * The 'merge' extension should be used to define how projects are merged, for example:
- * <pre class="code">
- * configure(subprojects) {
- * apply plugin: MergePlugin
- * }
- *
- * project("myproject") {
- * }
- *
- * project("myproject-extra") {
- * merge.into = project("myproject")
- * }
- * </pre>
- * <p>
- * This plugin adds two new configurations:
- * <ul>
- * <li>merging - Contains the projects being merged into this project<li>
- * <li>runtimeMerge - Contains all dependencies that are merge projects. These are used
- * to allow an IDE to reference merge projects.</li>
- * <ul>
- *
- * @author Rob Winch
- * @author Phillip Webb
- */
- class MergePlugin implements Plugin<Project> {
- private static boolean attachedProjectsEvaluated;
- public void apply(Project project) {
- project.plugins.apply(MavenPlugin)
- project.plugins.apply(EclipsePlugin)
- project.plugins.apply(IdeaPlugin)
- MergeModel model = project.extensions.create("merge", MergeModel)
- model.project = project
- project.configurations.create("merging")
- Configuration runtimeMerge = project.configurations.create("runtimeMerge")
- // Ensure the IDE can reference merged projects
- project.eclipse.classpath.plusConfigurations += [ runtimeMerge ]
- project.idea.module.scopes.PROVIDED.plus += [ runtimeMerge ]
- // Hook to perform the actual merge logic
- project.afterEvaluate{
- if (it.merge.into != null) {
- setup(it)
- }
- setupIdeDependencies(it)
- }
- // Hook to build runtimeMerge dependencies
- if (!attachedProjectsEvaluated) {
- project.gradle.projectsEvaluated{
- postProcessProjects(it)
- }
- attachedProjectsEvaluated = true;
- }
- }
- private void setup(Project project) {
- project.merge.into.dependencies.add("merging", project)
- project.dependencies.add("provided", project.merge.into.sourceSets.main.output)
- project.dependencies.add("runtimeMerge", project.merge.into)
- setupTaskDependencies(project)
- setupMaven(project)
- }
- private void setupTaskDependencies(Project project) {
- // invoking a task will invoke the task with the same name on 'into' project
- ["sourcesJar", "jar", "javadocJar", "javadoc", "install", "artifactoryPublish", "signArchives", "uploadArchives"].each {
- def task = project.tasks.findByPath(it)
- if (task) {
- task.enabled = false
- task.dependsOn(project.merge.into.tasks.findByPath(it))
- }
- }
- // update 'into' project artifacts to contain the source artifact contents
- project.merge.into.sourcesJar.from(project.sourcesJar.source)
- project.merge.into.jar.from(project.sourceSets.main.output)
- project.merge.into.javadoc {
- source += project.javadoc.source
- classpath += project.javadoc.classpath
- }
- }
- private void setupIdeDependencies(Project project) {
- project.configurations.each { c ->
- c.dependencies.findAll( { it instanceof org.gradle.api.artifacts.ProjectDependency } ).each { d ->
- if(d.dependencyProject.hasProperty("merge")) {
- d.dependencyProject.merge.from.each { from ->
- project.dependencies.add("runtimeMerge", from)
- }
- }
- }
- }
- }
- private void setupMaven(Project project) {
- project.configurations.each { configuration ->
- Conf2ScopeMapping mapping = project.conf2ScopeMappings.getMapping([configuration])
- if (mapping.scope) {
- Configuration intoConfiguration = project.merge.into.configurations.create(
- project.name + "-" + configuration.name)
- configuration.excludeRules.each {
- configuration.exclude([
- (ExcludeRule.GROUP_KEY) : it.group,
- (ExcludeRule.MODULE_KEY) : it.module])
- }
- configuration.dependencies.each {
- def intoCompile = project.merge.into.configurations.getByName("compile")
- // Protect against changing a compile scope dependency (SPR-10218)
- if (!intoCompile.dependencies.contains(it)) {
- intoConfiguration.dependencies.add(it)
- }
- }
- def index = project.parent.childProjects.findIndexOf {p -> p.getValue() == project}
- project.merge.into.install.repositories.mavenInstaller.pom.scopeMappings.addMapping(
- mapping.priority + 100 + index, intoConfiguration, mapping.scope)
- }
- }
- }
- private postProcessProjects(Gradle gradle) {
- gradle.allprojects(new Action<Project>() {
- public void execute(Project project) {
- if(!project.hasProperty("merge")) {
- return
- }
- project.configurations.getByName("runtime")?.allDependencies?.withType(ProjectDependency)?.each{
- Configuration dependsOnMergedFrom = it.dependencyProject.configurations.getByName("merging");
- dependsOnMergedFrom.dependencies.each{ dep ->
- project.dependencies.add("runtimeMerge", dep.dependencyProject)
- }
- }
- }
- });
- }
- }
- class MergeModel {
- Project project;
- Project into;
- List<Project> from = [];
- public void setInto(Project into) {
- this.into = into;
- into.merge.from.add(project);
- }
- }
|