Skip to content

Commit 6ff0b1b

Browse files
authored
Fix eclipse for build tools (#73699)
apply common eclipse config to all projects across the elasticsearch workspace including build tools projects
1 parent 902adac commit 6ff0b1b

File tree

5 files changed

+180
-63
lines changed

5 files changed

+180
-63
lines changed

build-conventions/build.gradle

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@
66
* Side Public License, v 1.
77
*/
88

9+
import org.gradle.plugins.ide.eclipse.model.SourceFolder;
10+
911
plugins {
1012
id 'java-gradle-plugin'
1113
id 'java-test-fixtures'
14+
id 'eclipse'
1215
}
1316

1417
group = "org.elasticsearch"
@@ -26,6 +29,10 @@ gradlePlugin {
2629
id = 'elasticsearch.internal-licenseheaders'
2730
implementationClass = 'org.elasticsearch.gradle.internal.conventions.precommit.LicenseHeadersPrecommitPlugin'
2831
}
32+
eclipse {
33+
id = 'elasticsearch.eclipse'
34+
implementationClass = 'org.elasticsearch.gradle.internal.conventions.EclipseConventionPlugin'
35+
}
2936
publish {
3037
id = 'elasticsearch.publish'
3138
implementationClass = 'org.elasticsearch.gradle.internal.conventions.PublishPlugin'
@@ -51,3 +58,19 @@ dependencies {
5158
api 'gradle.plugin.com.github.jengelman.gradle.plugins:shadow:7.0.0'
5259
api 'org.apache.rat:apache-rat:0.11'
5360
}
61+
62+
project.getPlugins().withType(JavaBasePlugin.class, javaBasePlugin -> {
63+
java.getModularity().getInferModulePath().set(false);
64+
eclipse.getClasspath().getFile().whenMerged { classpath ->
65+
/*
66+
* give each source folder a unique corresponding output folder
67+
* outside of the usual `build` folder. We can't put the build
68+
* in the usual build folder because eclipse becomes *very* sad
69+
* if we delete it. Which `gradlew clean` does all the time.
70+
*/
71+
int i = 0;
72+
classpath.getEntries().stream().filter(e -> e instanceof SourceFolder).forEachOrdered(s ->
73+
s.setOutput("out/eclipse"+i++)
74+
)
75+
}
76+
})
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
7+
*/
8+
9+
package org.elasticsearch.gradle.internal.conventions;
10+
11+
import org.apache.tools.ant.taskdefs.condition.Os;
12+
import org.gradle.api.Action;
13+
import org.gradle.api.GradleException;
14+
import org.gradle.api.Plugin;
15+
import org.gradle.api.Project;
16+
import org.gradle.api.Transformer;
17+
import org.gradle.api.plugins.JavaBasePlugin;
18+
import org.gradle.api.plugins.JavaPluginExtension;
19+
import org.gradle.api.tasks.Copy;
20+
import org.gradle.api.tasks.Delete;
21+
import org.gradle.plugins.ide.eclipse.EclipsePlugin;
22+
import org.gradle.plugins.ide.eclipse.model.Classpath;
23+
import org.gradle.plugins.ide.eclipse.model.EclipseModel;
24+
import org.gradle.plugins.ide.eclipse.model.EclipseProject;
25+
import org.gradle.plugins.ide.eclipse.model.ProjectDependency;
26+
import org.gradle.plugins.ide.eclipse.model.SourceFolder;
27+
import org.gradle.plugins.ide.eclipse.model.ClasspathEntry;
28+
29+
import java.io.File;
30+
import java.util.List;
31+
import java.io.IOException;
32+
import static java.util.stream.Collectors.toList;
33+
34+
import static org.apache.commons.io.FileUtils.readFileToString;
35+
36+
public class EclipseConventionPlugin implements Plugin<Project> {
37+
@Override
38+
public void apply(Project project) {
39+
project.getPlugins().apply(EclipsePlugin.class);
40+
EclipseModel eclipseModel = project.getExtensions().getByType(EclipseModel.class);
41+
EclipseProject eclipseProject = eclipseModel.getProject();
42+
43+
// Name all the non-root projects after their path so that paths get grouped together when imported into eclipse.
44+
if (project.getPath().equals(":") == false) {
45+
eclipseProject.setName(project.getPath());
46+
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
47+
eclipseProject.setName(eclipseProject.getName().replace(':', '_'));
48+
}
49+
}
50+
51+
52+
File licenseHeaderFile;
53+
String prefix = ":x-pack";
54+
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
55+
prefix = prefix.replace(':', '_');
56+
}
57+
File root = root(project);
58+
if (eclipseProject.getName().startsWith(prefix)) {
59+
licenseHeaderFile = new File(root, "build-tools-internal/src/main/resources/license-headers/elastic-license-2.0-header.txt");
60+
} else {
61+
licenseHeaderFile = new File(root, "build-tools-internal/src/main/resources/license-headers/sspl+elastic-license-header.txt");
62+
}
63+
64+
String lineSeparator = Os.isFamily(Os.FAMILY_WINDOWS) ? "\\\\r\\\\n" : "\\\\n";
65+
String licenseHeader = null;
66+
try {
67+
licenseHeader = readFileToString(licenseHeaderFile, "UTF-8").replace(System.lineSeparator(), lineSeparator);
68+
} catch (IOException e) {
69+
throw new GradleException("Cannot configure eclipse", e);
70+
}
71+
72+
String finalLicenseHeader = licenseHeader;
73+
project.getTasks().register("copyEclipseSettings", Copy.class, copy -> {
74+
copy.mustRunAfter("wipeEclipseSettings");
75+
// TODO: "package this up" for external builds
76+
copy.from(new File(root, "build-tools-internal/src/main/resources/eclipse.settings"));
77+
copy.into(".settings");
78+
copy.filter(new Transformer<String, String>() {
79+
@Override
80+
public String transform(String s) {
81+
return s.replaceAll("@@LICENSE_HEADER_TEXT@@", finalLicenseHeader);
82+
}
83+
});
84+
});
85+
// otherwise .settings is not nuked entirely
86+
project.getTasks().register("wipeEclipseSettings", Delete.class, new Action<Delete>() {
87+
@Override
88+
public void execute(Delete delete) {
89+
delete.delete(".settings");
90+
}
91+
});
92+
93+
project.getTasks().named("cleanEclipse").configure(t -> t.dependsOn("wipeEclipseSettings"));
94+
95+
// otherwise the eclipse merging is *super confusing*
96+
project.getTasks().named("eclipse").configure(t -> t.dependsOn("cleanEclipse", "copyEclipseSettings"));
97+
98+
project.getPlugins().withType(JavaBasePlugin.class, javaBasePlugin -> {
99+
JavaPluginExtension java = project.getExtensions().getByType(JavaPluginExtension.class);
100+
java.getModularity().getInferModulePath().set(false);
101+
102+
eclipseModel.getClasspath().getFile().whenMerged(c -> {
103+
Classpath classpath = (Classpath) c;
104+
105+
/*
106+
* give each source folder a unique corresponding output folder
107+
* outside of the usual `build` folder. We can't put the build
108+
* in the usual build folder because eclipse becomes *very* sad
109+
* if we delete it. Which `gradlew clean` does all the time.
110+
*/
111+
int i = 0;
112+
List<ClasspathEntry> sourceFolderList = classpath.getEntries().stream().filter(e -> e instanceof SourceFolder).collect(toList());
113+
for (ClasspathEntry sourceFolder : sourceFolderList) {
114+
((SourceFolder)sourceFolder).setOutput("out/eclipse/" + i++);
115+
}
116+
117+
// Starting with Gradle 6.7 test dependencies are not exposed by eclipse
118+
// projects by default. This breaks project dependencies using the `java-test-fixtures` plugin
119+
// or dependencies on other projects manually declared testArtifacts configurations
120+
// This issue is tracked in gradle issue tracker.
121+
// See https://github.com/gradle/gradle/issues/14932 for further details
122+
123+
classpath.getEntries().stream().filter(e -> e instanceof ProjectDependency).forEach(it ->
124+
((ProjectDependency) it).getEntryAttributes().remove("without_test_code")
125+
);
126+
127+
});
128+
129+
project.getTasks().named("eclipseJdt").configure(t -> t.dependsOn("copyEclipseSettings"));
130+
});
131+
}
132+
133+
private File root(Project project) {
134+
return project.getGradle().getParent() == null ?
135+
project.getRootDir() :
136+
root(project.getGradle().getParent().getRootProject());
137+
}
138+
}

build-tools-internal/build.gradle

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,18 @@
88

99

1010
import org.elasticsearch.gradle.internal.conventions.VersionPropertiesLoader
11+
import org.apache.tools.ant.taskdefs.condition.Os
12+
import org.gradle.plugins.ide.eclipse.model.AccessRule
13+
import org.gradle.plugins.ide.eclipse.model.SourceFolder
14+
import org.gradle.plugins.ide.eclipse.model.ProjectDependency
1115

1216
plugins {
1317
id 'java-gradle-plugin'
1418
id 'groovy-gradle-plugin'
1519
id 'groovy'
1620
id 'elasticsearch.internal-licenseheaders'
1721
id 'elasticsearch.basic-build-tool-conventions'
22+
id 'elasticsearch.eclipse'
1823
}
1924

2025
group = 'org.elasticsearch.gradle'

build-tools/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ allprojects {
2929
version = props.getProperty("elasticsearch")
3030

3131
apply plugin: 'java'
32+
apply plugin: 'elasticsearch.eclipse'
3233
targetCompatibility = minRuntimeJava
3334
sourceCompatibility = minRuntimeJava
3435
}

build.gradle

Lines changed: 13 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -314,42 +314,8 @@ gradle.projectsEvaluated {
314314

315315
// eclipse configuration
316316
allprojects {
317-
apply plugin: 'eclipse'
318-
// Name all the non-root projects after their path so that paths get grouped together when imported into eclipse.
319-
if (path != ':') {
320-
eclipse.project.name = path
321-
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
322-
eclipse.project.name = eclipse.project.name.replace(':', '_')
323-
}
324-
}
325-
326-
plugins.withType(JavaBasePlugin) {
327-
java.modularity.inferModulePath.set(false)
328-
eclipse.classpath.file.whenMerged { classpath ->
329-
/*
330-
* give each source folder a unique corresponding output folder
331-
* outside of the usual `build` folder. We can't put the build
332-
* in the usual build folder because eclipse becomes *very* sad
333-
* if we delete it. Which `gradlew clean` does all the time.
334-
*/
335-
int i = 0;
336-
classpath.entries.findAll { it instanceof SourceFolder }.each { folder ->
337-
i++;
338-
folder.output = 'out/eclipse/' + i
339-
}
317+
apply plugin: 'elasticsearch.eclipse'
340318

341-
// Starting with Gradle 6.7 test dependencies are not exposed by eclipse
342-
// projects by default. This breaks project dependencies using the `java-test-fixtures` plugin
343-
// or dependencies on other projects manually declared testArtifacts configurations
344-
// This issue is tracked in gradle issue tracker.
345-
// See https://github.com/gradle/gradle/issues/14932 for further details
346-
classpath.entries.findAll {
347-
it instanceof ProjectDependency
348-
}.each {
349-
it.entryAttributes.remove('without_test_code')
350-
}
351-
}
352-
}
353319
/*
354320
* Allow accessing com/sun/net/httpserver in projects that have
355321
* configured forbidden apis to allow it.
@@ -365,34 +331,6 @@ allprojects {
365331
}
366332
}
367333
}
368-
369-
File licenseHeaderFile
370-
String prefix = ':x-pack'
371-
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
372-
prefix = prefix.replace(':', '_')
373-
}
374-
if (eclipse.project.name.startsWith(prefix)) {
375-
licenseHeaderFile = new File(project.rootDir, 'build-tools-internal/src/main/resources/license-headers/elastic-license-2.0-header.txt')
376-
} else {
377-
licenseHeaderFile = new File(project.rootDir, 'build-tools-internal/src/main/resources/license-headers/sspl+elastic-license-header.txt')
378-
}
379-
380-
String lineSeparator = Os.isFamily(Os.FAMILY_WINDOWS) ? '\\\\r\\\\n' : '\\\\n'
381-
String licenseHeader = licenseHeaderFile.getText('UTF-8').replace(System.lineSeparator(), lineSeparator)
382-
tasks.register('copyEclipseSettings', Copy) {
383-
mustRunAfter 'wipeEclipseSettings'
384-
// TODO: "package this up" for external builds
385-
from new File(project.rootDir, 'build-tools-internal/src/main/resources/eclipse.settings')
386-
into '.settings'
387-
filter { it.replaceAll('@@LICENSE_HEADER_TEXT@@', licenseHeader) }
388-
}
389-
// otherwise .settings is not nuked entirely
390-
tasks.register('wipeEclipseSettings', Delete) {
391-
delete '.settings'
392-
}
393-
tasks.named('cleanEclipse') { dependsOn 'wipeEclipseSettings' }
394-
// otherwise the eclipse merging is *super confusing*
395-
tasks.named('eclipse') { dependsOn 'cleanEclipse', 'copyEclipseSettings' }
396334
}
397335

398336
tasks.named("wrapper").configure {
@@ -504,6 +442,18 @@ tasks.named("assemble").configure {
504442
dependsOn gradle.includedBuild('build-tools').task(':assemble')
505443
}
506444

445+
tasks.named("cleanEclipse").configure {
446+
dependsOn gradle.includedBuild('build-conventions').task(':cleanEclipse')
447+
dependsOn gradle.includedBuild('build-tools').task(':cleanEclipse')
448+
dependsOn gradle.includedBuild('build-tools-internal').task(':cleanEclipse')
449+
}
450+
451+
tasks.named("eclipse").configure {
452+
dependsOn gradle.includedBuild('build-conventions').task(':eclipse')
453+
dependsOn gradle.includedBuild('build-tools').task(':eclipse')
454+
dependsOn gradle.includedBuild('build-tools-internal').task(':eclipse')
455+
}
456+
507457
subprojects {
508458
project.ext.disableTasks = { String... tasknames ->
509459
for (String taskname : tasknames) {

0 commit comments

Comments
 (0)