Fix eclipse for build tools (#73699) (7.x backport) (#73904)

apply common eclipse config to all projects across the elasticsearch workspace
including build tools projects
This commit is contained in:
Rene Groeschke 2021-06-08 16:35:04 +02:00 committed by GitHub
parent 78d3addbc7
commit 3799abc912
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 182 additions and 64 deletions

View file

@ -6,9 +6,12 @@
* Side Public License, v 1.
*/
import org.gradle.plugins.ide.eclipse.model.SourceFolder;
plugins {
id 'java-gradle-plugin'
id 'java-test-fixtures'
id 'eclipse'
}
group = "org.elasticsearch"
@ -25,6 +28,10 @@ gradlePlugin {
id = 'elasticsearch.internal-licenseheaders'
implementationClass = 'org.elasticsearch.gradle.internal.conventions.precommit.LicenseHeadersPrecommitPlugin'
}
eclipse {
id = 'elasticsearch.eclipse'
implementationClass = 'org.elasticsearch.gradle.internal.conventions.EclipseConventionPlugin'
}
publish {
id = 'elasticsearch.publish'
implementationClass = 'org.elasticsearch.gradle.internal.conventions.PublishPlugin'
@ -50,3 +57,19 @@ dependencies {
api 'gradle.plugin.com.github.jengelman.gradle.plugins:shadow:7.0.0'
api 'org.apache.rat:apache-rat:0.11'
}
project.getPlugins().withType(JavaBasePlugin.class, javaBasePlugin -> {
java.getModularity().getInferModulePath().set(false);
eclipse.getClasspath().getFile().whenMerged { classpath ->
/*
* give each source folder a unique corresponding output folder
* outside of the usual `build` folder. We can't put the build
* in the usual build folder because eclipse becomes *very* sad
* if we delete it. Which `gradlew clean` does all the time.
*/
int i = 0;
classpath.getEntries().stream().filter(e -> e instanceof SourceFolder).forEachOrdered(s ->
s.setOutput("out/eclipse"+i++)
)
}
})

View file

@ -0,0 +1,138 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
package org.elasticsearch.gradle.internal.conventions;
import org.apache.tools.ant.taskdefs.condition.Os;
import org.gradle.api.Action;
import org.gradle.api.GradleException;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Transformer;
import org.gradle.api.plugins.JavaBasePlugin;
import org.gradle.api.plugins.JavaPluginExtension;
import org.gradle.api.tasks.Copy;
import org.gradle.api.tasks.Delete;
import org.gradle.plugins.ide.eclipse.EclipsePlugin;
import org.gradle.plugins.ide.eclipse.model.Classpath;
import org.gradle.plugins.ide.eclipse.model.EclipseModel;
import org.gradle.plugins.ide.eclipse.model.EclipseProject;
import org.gradle.plugins.ide.eclipse.model.ProjectDependency;
import org.gradle.plugins.ide.eclipse.model.SourceFolder;
import org.gradle.plugins.ide.eclipse.model.ClasspathEntry;
import java.io.File;
import java.util.List;
import java.io.IOException;
import static java.util.stream.Collectors.toList;
import static org.apache.commons.io.FileUtils.readFileToString;
public class EclipseConventionPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getPlugins().apply(EclipsePlugin.class);
EclipseModel eclipseModel = project.getExtensions().getByType(EclipseModel.class);
EclipseProject eclipseProject = eclipseModel.getProject();
// Name all the non-root projects after their path so that paths get grouped together when imported into eclipse.
if (project.getPath().equals(":") == false) {
eclipseProject.setName(project.getPath());
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
eclipseProject.setName(eclipseProject.getName().replace(':', '_'));
}
}
File licenseHeaderFile;
String prefix = ":x-pack";
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
prefix = prefix.replace(':', '_');
}
File root = root(project);
if (eclipseProject.getName().startsWith(prefix)) {
licenseHeaderFile = new File(root, "build-tools-internal/src/main/resources/license-headers/elastic-license-2.0-header.txt");
} else {
licenseHeaderFile = new File(root, "build-tools-internal/src/main/resources/license-headers/sspl+elastic-license-header.txt");
}
String lineSeparator = Os.isFamily(Os.FAMILY_WINDOWS) ? "\\\\r\\\\n" : "\\\\n";
String licenseHeader = null;
try {
licenseHeader = readFileToString(licenseHeaderFile, "UTF-8").replace(System.lineSeparator(), lineSeparator);
} catch (IOException e) {
throw new GradleException("Cannot configure eclipse", e);
}
String finalLicenseHeader = licenseHeader;
project.getTasks().register("copyEclipseSettings", Copy.class, copy -> {
copy.mustRunAfter("wipeEclipseSettings");
// TODO: "package this up" for external builds
copy.from(new File(root, "build-tools-internal/src/main/resources/eclipse.settings"));
copy.into(".settings");
copy.filter(new Transformer<String, String>() {
@Override
public String transform(String s) {
return s.replaceAll("@@LICENSE_HEADER_TEXT@@", finalLicenseHeader);
}
});
});
// otherwise .settings is not nuked entirely
project.getTasks().register("wipeEclipseSettings", Delete.class, new Action<Delete>() {
@Override
public void execute(Delete delete) {
delete.delete(".settings");
}
});
project.getTasks().named("cleanEclipse").configure(t -> t.dependsOn("wipeEclipseSettings"));
// otherwise the eclipse merging is *super confusing*
project.getTasks().named("eclipse").configure(t -> t.dependsOn("cleanEclipse", "copyEclipseSettings"));
project.getPlugins().withType(JavaBasePlugin.class, javaBasePlugin -> {
JavaPluginExtension java = project.getExtensions().getByType(JavaPluginExtension.class);
java.getModularity().getInferModulePath().set(false);
eclipseModel.getClasspath().getFile().whenMerged(c -> {
Classpath classpath = (Classpath) c;
/*
* give each source folder a unique corresponding output folder
* outside of the usual `build` folder. We can't put the build
* in the usual build folder because eclipse becomes *very* sad
* if we delete it. Which `gradlew clean` does all the time.
*/
int i = 0;
List<ClasspathEntry> sourceFolderList = classpath.getEntries().stream().filter(e -> e instanceof SourceFolder).collect(toList());
for (ClasspathEntry sourceFolder : sourceFolderList) {
((SourceFolder)sourceFolder).setOutput("out/eclipse/" + i++);
}
// Starting with Gradle 6.7 test dependencies are not exposed by eclipse
// projects by default. This breaks project dependencies using the `java-test-fixtures` plugin
// or dependencies on other projects manually declared testArtifacts configurations
// This issue is tracked in gradle issue tracker.
// See https://github.com/gradle/gradle/issues/14932 for further details
classpath.getEntries().stream().filter(e -> e instanceof ProjectDependency).forEach(it ->
((ProjectDependency) it).getEntryAttributes().remove("without_test_code")
);
});
project.getTasks().named("eclipseJdt").configure(t -> t.dependsOn("copyEclipseSettings"));
});
}
private File root(Project project) {
return project.getGradle().getParent() == null ?
project.getRootDir() :
root(project.getGradle().getParent().getRootProject());
}
}

View file

@ -9,6 +9,10 @@
import org.gradle.internal.jvm.Jvm
import org.gradle.util.GradleVersion
import org.elasticsearch.gradle.internal.conventions.VersionPropertiesLoader
import org.apache.tools.ant.taskdefs.condition.Os
import org.gradle.plugins.ide.eclipse.model.AccessRule
import org.gradle.plugins.ide.eclipse.model.SourceFolder
import org.gradle.plugins.ide.eclipse.model.ProjectDependency
plugins {
id 'java-gradle-plugin'
@ -16,6 +20,7 @@ plugins {
id 'groovy'
id 'elasticsearch.internal-licenseheaders'
id 'elasticsearch.basic-build-tool-conventions'
id 'elasticsearch.eclipse'
}
group = 'org.elasticsearch.gradle'

View file

@ -22,11 +22,13 @@ description = "The elasticsearch build tools"
// we write this back out below to load it in the Build.java which will be shown in rest main action
// to indicate this being a snapshot build or a release build.
Properties props = VersionPropertiesLoader.loadBuildSrcVersion(project.file('../build-tools-internal/version.properties'))
allprojects {
group = "org.elasticsearch"
version = props.getProperty("elasticsearch")
apply plugin: 'java'
apply plugin: 'elasticsearch.eclipse'
targetCompatibility = 11
sourceCompatibility = 11
}
@ -217,4 +219,4 @@ tasks.named("check").configure { dependsOn("integTest") }
// baseClass 'spock.lang.Specification'
// }
// }
// }
// }

View file

@ -314,42 +314,8 @@ gradle.projectsEvaluated {
// eclipse configuration
allprojects {
apply plugin: 'eclipse'
// Name all the non-root projects after their path so that paths get grouped together when imported into eclipse.
if (path != ':') {
eclipse.project.name = path
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
eclipse.project.name = eclipse.project.name.replace(':', '_')
}
}
apply plugin: 'elasticsearch.eclipse'
plugins.withType(JavaBasePlugin) {
java.modularity.inferModulePath.set(false)
eclipse.classpath.file.whenMerged { classpath ->
/*
* give each source folder a unique corresponding output folder
* outside of the usual `build` folder. We can't put the build
* in the usual build folder because eclipse becomes *very* sad
* if we delete it. Which `gradlew clean` does all the time.
*/
int i = 0;
classpath.entries.findAll { it instanceof SourceFolder }.each { folder ->
i++;
folder.output = 'out/eclipse/' + i
}
// Starting with Gradle 6.7 test dependencies are not exposed by eclipse
// projects by default. This breaks project dependencies using the `java-test-fixtures` plugin
// or dependencies on other projects manually declared testArtifacts configurations
// This issue is tracked in gradle issue tracker.
// See https://github.com/gradle/gradle/issues/14932 for further details
classpath.entries.findAll {
it instanceof ProjectDependency
}.each {
it.entryAttributes.remove('without_test_code')
}
}
}
/*
* Allow accessing com/sun/net/httpserver in projects that have
* configured forbidden apis to allow it.
@ -365,34 +331,6 @@ allprojects {
}
}
}
File licenseHeaderFile
String prefix = ':x-pack'
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
prefix = prefix.replace(':', '_')
}
if (eclipse.project.name.startsWith(prefix)) {
licenseHeaderFile = new File(project.rootDir, 'build-tools-internal/src/main/resources/license-headers/elastic-license-2.0-header.txt')
} else {
licenseHeaderFile = new File(project.rootDir, 'build-tools-internal/src/main/resources/license-headers/sspl+elastic-license-header.txt')
}
String lineSeparator = Os.isFamily(Os.FAMILY_WINDOWS) ? '\\\\r\\\\n' : '\\\\n'
String licenseHeader = licenseHeaderFile.getText('UTF-8').replace(System.lineSeparator(), lineSeparator)
tasks.register('copyEclipseSettings', Copy) {
mustRunAfter 'wipeEclipseSettings'
// TODO: "package this up" for external builds
from new File(project.rootDir, 'build-tools-internal/src/main/resources/eclipse.settings')
into '.settings'
filter { it.replaceAll('@@LICENSE_HEADER_TEXT@@', licenseHeader) }
}
// otherwise .settings is not nuked entirely
tasks.register('wipeEclipseSettings', Delete) {
delete '.settings'
}
tasks.named('cleanEclipse') { dependsOn 'wipeEclipseSettings' }
// otherwise the eclipse merging is *super confusing*
tasks.named('eclipse') { dependsOn 'cleanEclipse', 'copyEclipseSettings' }
}
tasks.named("wrapper").configure {
@ -501,6 +439,18 @@ tasks.named("assemble").configure {
dependsOn gradle.includedBuild('build-tools').task(':assemble')
}
tasks.named("cleanEclipse").configure {
dependsOn gradle.includedBuild('build-conventions').task(':cleanEclipse')
dependsOn gradle.includedBuild('build-tools').task(':cleanEclipse')
dependsOn gradle.includedBuild('build-tools-internal').task(':cleanEclipse')
}
tasks.named("eclipse").configure {
dependsOn gradle.includedBuild('build-conventions').task(':eclipse')
dependsOn gradle.includedBuild('build-tools').task(':eclipse')
dependsOn gradle.includedBuild('build-tools-internal').task(':eclipse')
}
subprojects {
project.ext.disableTasks = { String... tasknames ->
for (String taskname : tasknames) {