Skip to content

Commit

Permalink
Introduce aarch64 packaging (#53914) (#53926)
Browse files Browse the repository at this point in the history
This commit introduces aarch64 packaging, including bundling an aarch64
JDK distribution. We had to make some interesting choices here:
 - ML binaries are not compiled for aarch64, so for now we disable ML on
   aarch64
 - depending on underlying page sizes, we have to disable class data
   sharing
  • Loading branch information
jasontedor committed Mar 22, 2020
1 parent 076ba02 commit 27c8bcb
Show file tree
Hide file tree
Showing 26 changed files with 258 additions and 62 deletions.
2 changes: 2 additions & 0 deletions buildSrc/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,10 @@ if (project != rootProject) {
distribution project(':distribution:archives:oss-windows-zip')
distribution project(':distribution:archives:darwin-tar')
distribution project(':distribution:archives:oss-darwin-tar')
distribution project(':distribution:archives:linux-aarch64-tar')
distribution project(':distribution:archives:linux-tar')
distribution project(':distribution:archives:oss-linux-tar')
distribution project(':distribution:archives:oss-linux-aarch64-tar')
}

// for external projects we want to remove the marker file indicating we are running the Elasticsearch project
Expand Down
40 changes: 40 additions & 0 deletions buildSrc/src/main/java/org/elasticsearch/gradle/Architecture.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you 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
*
* http://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 org.elasticsearch.gradle;

public enum Architecture {

X64,
AARCH64;

public static Architecture current() {
final String architecture = System.getProperty("os.arch", "");
switch (architecture) {
case "amd64":
case "x86_64":
return X64;
case "aarch64":
return AARCH64;
default:
throw new IllegalArgumentException("can not determine architecture from [" + architecture + "]");
}
}

}
20 changes: 20 additions & 0 deletions buildSrc/src/main/java/org/elasticsearch/gradle/Jdk.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

public class Jdk implements Buildable, Iterable<File> {

private static final List<String> ALLOWED_ARCHITECTURES = Collections.unmodifiableList(Arrays.asList("aarch64", "x64"));
private static final List<String> ALLOWED_VENDORS = Collections.unmodifiableList(Arrays.asList("adoptopenjdk", "openjdk"));
private static final List<String> ALLOWED_PLATFORMS = Collections.unmodifiableList(Arrays.asList("darwin", "linux", "windows", "mac"));
private static final Pattern VERSION_PATTERN = Pattern.compile("(\\d+)(\\.\\d+\\.\\d+)?\\+(\\d+(?:\\.\\d+)?)(@([a-f0-9]{32}))?");
Expand All @@ -46,6 +47,7 @@ public class Jdk implements Buildable, Iterable<File> {
private final Property<String> vendor;
private final Property<String> version;
private final Property<String> platform;
private final Property<String> architecture;
private String baseVersion;
private String major;
private String build;
Expand All @@ -57,6 +59,7 @@ public class Jdk implements Buildable, Iterable<File> {
this.vendor = objectFactory.property(String.class);
this.version = objectFactory.property(String.class);
this.platform = objectFactory.property(String.class);
this.architecture = objectFactory.property(String.class);
}

public String getName() {
Expand Down Expand Up @@ -99,6 +102,19 @@ public void setPlatform(String platform) {
this.platform.set(platform);
}

public String getArchitecture() {
return architecture.get();
}

public void setArchitecture(final String architecture) {
if (ALLOWED_ARCHITECTURES.contains(architecture) == false) {
throw new IllegalArgumentException(
"unknown architecture [" + architecture + "] for jdk [" + name + "], must be one of " + ALLOWED_ARCHITECTURES
);
}
this.architecture.set(architecture);
}

public String getBaseVersion() {
return baseVersion;
}
Expand Down Expand Up @@ -167,9 +183,13 @@ void finalizeValues() {
if (vendor.isPresent() == false) {
throw new IllegalArgumentException("vendor not specified for jdk [" + name + "]");
}
if (architecture.isPresent() == false) {
throw new IllegalArgumentException("architecture not specified for jdk [" + name + "]");
}
version.finalizeValue();
platform.finalizeValue();
vendor.finalizeValue();
architecture.finalizeValue();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
import java.util.concurrent.Callable;
import java.util.stream.StreamSupport;

import static org.elasticsearch.gradle.Util.capitalize;
import static org.elasticsearch.gradle.tool.Boilerplate.findByName;
import static org.elasticsearch.gradle.tool.Boilerplate.maybeCreate;

Expand All @@ -72,7 +71,10 @@ public void apply(Project project) {
DependencyHandler dependencies = project.getDependencies();
Map<String, Object> depConfig = new HashMap<>();
depConfig.put("path", ":"); // root project
depConfig.put("configuration", configName("extracted_jdk", jdk.getVendor(), jdk.getVersion(), jdk.getPlatform()));
depConfig.put(
"configuration",
configName("extracted_jdk", jdk.getVendor(), jdk.getVersion(), jdk.getPlatform(), jdk.getArchitecture())
);
project.getDependencies().add(jdk.getConfigurationName(), dependencies.project(depConfig));

// ensure a root level jdk download task exists
Expand All @@ -87,7 +89,14 @@ public static NamedDomainObjectContainer<Jdk> getContainer(Project project) {
}

private static void setupRootJdkDownload(Project rootProject, Jdk jdk) {
String extractTaskName = "extract" + capitalize(jdk.getPlatform()) + "Jdk-" + jdk.getVendor() + "-" + jdk.getVersion();
String extractTaskName = String.format(
Locale.ROOT,
"extract-%s-%s-jdk-%s-%s",
jdk.getPlatform(),
jdk.getArchitecture(),
jdk.getVendor(),
jdk.getVersion()
);

// Skip setup if we've already configured a JDK for this platform, vendor and version
if (findByName(rootProject.getTasks(), extractTaskName) == null) {
Expand All @@ -107,7 +116,7 @@ private static void setupRootJdkDownload(Project rootProject, Jdk jdk) {
repoUrl = "https://artifactory.elstc.co/artifactory/oss-jdk-local/";
artifactPattern = String.format(
Locale.ROOT,
"adoptopenjdk/OpenJDK%sU-jdk_x64_[module]_hotspot_[revision]_%s.[ext]",
"adoptopenjdk/OpenJDK%sU-jdk_[classifier]_[module]_hotspot_[revision]_%s.[ext]",
jdk.getMajor(),
jdk.getBuild()
);
Expand All @@ -121,14 +130,14 @@ private static void setupRootJdkDownload(Project rootProject, Jdk jdk) {
+ jdk.getHash()
+ "/"
+ jdk.getBuild()
+ "/GPL/openjdk-[revision]_[module]-x64_bin.[ext]";
+ "/GPL/openjdk-[revision]_[module]-[classifier]_bin.[ext]";
} else {
// simpler legacy pattern from JDK 9 to JDK 12 that we are advocating to Oracle to bring back
artifactPattern = "java/GA/jdk"
+ jdk.getMajor()
+ "/"
+ jdk.getBuild()
+ "/GPL/openjdk-[revision]_[module]-x64_bin.[ext]";
+ "/GPL/openjdk-[revision]_[module]-[classifier]_bin.[ext]";
}
} else {
throw new GradleException("Unknown JDK vendor [" + jdk.getVendor() + "]");
Expand All @@ -150,14 +159,14 @@ private static void setupRootJdkDownload(Project rootProject, Jdk jdk) {

// Declare a configuration and dependency from which to download the remote JDK
final ConfigurationContainer configurations = rootProject.getConfigurations();
String downloadConfigName = configName(jdk.getVendor(), jdk.getVersion(), jdk.getPlatform());
String downloadConfigName = configName(jdk.getVendor(), jdk.getVersion(), jdk.getPlatform(), jdk.getArchitecture());
Configuration downloadConfiguration = maybeCreate(configurations, downloadConfigName);
rootProject.getDependencies().add(downloadConfigName, dependencyNotation(jdk));

// Create JDK extract task
final Provider<Directory> extractPath = rootProject.getLayout()
.getBuildDirectory()
.dir("jdks/" + jdk.getVendor() + "-" + jdk.getBaseVersion() + "_" + jdk.getPlatform());
.dir("jdks/" + jdk.getVendor() + "-" + jdk.getBaseVersion() + "_" + jdk.getPlatform() + "_" + jdk.getArchitecture());

TaskProvider<?> extractTask = createExtractTask(
extractTaskName,
Expand All @@ -168,7 +177,13 @@ private static void setupRootJdkDownload(Project rootProject, Jdk jdk) {
);

// Declare a configuration for the extracted JDK archive
String artifactConfigName = configName("extracted_jdk", jdk.getVendor(), jdk.getVersion(), jdk.getPlatform());
String artifactConfigName = configName(
"extracted_jdk",
jdk.getVendor(),
jdk.getVersion(),
jdk.getPlatform(),
jdk.getArchitecture()
);
maybeCreate(configurations, artifactConfigName);
rootProject.getArtifacts().add(artifactConfigName, extractPath, artifact -> artifact.builtBy(extractTask));
}
Expand Down Expand Up @@ -254,7 +269,7 @@ private static String dependencyNotation(Jdk jdk) {
: jdk.getPlatform();
String extension = jdk.getPlatform().equals("windows") ? "zip" : "tar.gz";

return groupName(jdk) + ":" + platformDep + ":" + jdk.getBaseVersion() + "@" + extension;
return groupName(jdk) + ":" + platformDep + ":" + jdk.getBaseVersion() + ":" + jdk.getArchitecture() + "@" + extension;
}

private static String groupName(Jdk jdk) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,12 +173,14 @@ private static Jdk createJdk(
String name,
String vendor,
String version,
String platform
String platform,
String architecture
) {
Jdk jdk = jdksContainer.create(name);
jdk.setVendor(vendor);
jdk.setVersion(version);
jdk.setPlatform(platform);
jdk.setArchitecture(architecture);
return jdk;
}

Expand Down Expand Up @@ -210,7 +212,7 @@ private static List<Object> configureVM(Project project) {

NamedDomainObjectContainer<Jdk> jdksContainer = JdkDownloadPlugin.getContainer(project);
String platform = box.contains("windows") ? "windows" : "linux";
Jdk gradleJdk = createJdk(jdksContainer, "gradle", GRADLE_JDK_VENDOR, GRADLE_JDK_VERSION, platform);
Jdk gradleJdk = createJdk(jdksContainer, "gradle", GRADLE_JDK_VENDOR, GRADLE_JDK_VERSION, platform, "x64");

// setup VM used by these tests
VagrantExtension vagrant = project.getExtensions().getByType(VagrantExtension.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
package org.elasticsearch.gradle.testclusters;

import org.elasticsearch.gradle.Architecture;
import org.elasticsearch.gradle.DistributionDownloadPlugin;
import org.elasticsearch.gradle.Jdk;
import org.elasticsearch.gradle.JdkDownloadPlugin;
Expand Down Expand Up @@ -65,6 +66,7 @@ public void apply(Project project) {
jdk.setVendor(LEGACY_JAVA_VENDOR);
jdk.setVersion(LEGACY_JAVA_VERSION);
jdk.setPlatform(OS.current().name().toLowerCase());
jdk.setArchitecture(Architecture.current().name().toLowerCase());
});

// enable the DSL to describe clusters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public static void setupRoot() {
}

public void testMissingVendor() {
assertJdkError(createProject(), "testjdk", null, "11.0.2+33", "linux", "vendor not specified for jdk [testjdk]");
assertJdkError(createProject(), "testjdk", null, "11.0.2+33", "linux", "x64", "vendor not specified for jdk [testjdk]");
}

public void testUnknownVendor() {
Expand All @@ -46,20 +46,29 @@ public void testUnknownVendor() {
"unknown",
"11.0.2+33",
"linux",
"x64",
"unknown vendor [unknown] for jdk [testjdk], must be one of [adoptopenjdk, openjdk]"
);
}

public void testMissingVersion() {
assertJdkError(createProject(), "testjdk", "openjdk", null, "linux", "version not specified for jdk [testjdk]");
assertJdkError(createProject(), "testjdk", "openjdk", null, "linux", "x64", "version not specified for jdk [testjdk]");
}

public void testBadVersionFormat() {
assertJdkError(createProject(), "testjdk", "openjdk", "badversion", "linux", "malformed version [badversion] for jdk [testjdk]");
assertJdkError(
createProject(),
"testjdk",
"openjdk",
"badversion",
"linux",
"x64",
"malformed version [badversion] for jdk [testjdk]"
);
}

public void testMissingPlatform() {
assertJdkError(createProject(), "testjdk", "openjdk", "11.0.2+33", null, "platform not specified for jdk [testjdk]");
assertJdkError(createProject(), "testjdk", "openjdk", "11.0.2+33", null, "x64", "platform not specified for jdk [testjdk]");
}

public void testUnknownPlatform() {
Expand All @@ -69,19 +78,44 @@ public void testUnknownPlatform() {
"openjdk",
"11.0.2+33",
"unknown",
"x64",
"unknown platform [unknown] for jdk [testjdk], must be one of [darwin, linux, windows, mac]"
);
}

private void assertJdkError(Project project, String name, String vendor, String version, String platform, String message) {
public void testMissingArchitecture() {
assertJdkError(createProject(), "testjdk", "openjdk", "11.0.2+33", "linux", null, "architecture not specified for jdk [testjdk]");
}

public void testUnknownArchitecture() {
assertJdkError(
createProject(),
"testjdk",
"openjdk",
"11.0.2+33",
"linux",
"unknown",
"unknown architecture [unknown] for jdk [testjdk], must be one of [aarch64, x64]"
);
}

private void assertJdkError(
final Project project,
final String name,
final String vendor,
final String version,
final String platform,
final String architecture,
final String message
) {
IllegalArgumentException e = expectThrows(
IllegalArgumentException.class,
() -> createJdk(project, name, vendor, version, platform)
() -> createJdk(project, name, vendor, version, platform, architecture)
);
assertThat(e.getMessage(), equalTo(message));
}

private void createJdk(Project project, String name, String vendor, String version, String platform) {
private void createJdk(Project project, String name, String vendor, String version, String platform, String architecture) {
@SuppressWarnings("unchecked")
NamedDomainObjectContainer<Jdk> jdks = (NamedDomainObjectContainer<Jdk>) project.getExtensions().getByName("jdks");
jdks.create(name, jdk -> {
Expand All @@ -94,6 +128,9 @@ private void createJdk(Project project, String name, String vendor, String versi
if (platform != null) {
jdk.setPlatform(platform);
}
if (architecture != null) {
jdk.setArchitecture(architecture);
}
}).finalizeValues();
}

Expand Down
1 change: 1 addition & 0 deletions buildSrc/src/testKit/jdk-download/reuse/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ jdks {
vendor = fakeJdkVendor
version = fakeJdkVersion
platform = "linux"
architeecture = "x64"
}
}
3 changes: 3 additions & 0 deletions buildSrc/src/testKit/jdk-download/subproj/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,19 @@ jdks {
vendor = fakeJdkVendor
version = fakeJdkVersion
platform = "linux"
architecture = "x64"
}
darwin {
vendor = fakeJdkVendor
version = fakeJdkVersion
platform = "darwin"
architecture = "x64"
}
windows {
vendor = fakeJdkVendor
version = fakeJdkVersion
platform = "windows"
architecture = "x64"
}
}

Expand Down
Loading

0 comments on commit 27c8bcb

Please sign in to comment.