Merge pull request #998 from Glavo/aarch64

支持在更多平台上自动补全 JavaFX
This commit is contained in:
Yuhui Huang
2021-09-08 15:05:45 +08:00
committed by GitHub
12 changed files with 212 additions and 104 deletions

View File

@@ -450,7 +450,7 @@ public final class LauncherHelper {
// First find if same java version but whose platform is 64-bit installed. // First find if same java version but whose platform is 64-bit installed.
Optional<JavaVersion> java64 = JavaVersion.getJavas().stream() Optional<JavaVersion> java64 = JavaVersion.getJavas().stream()
.filter(javaVersion -> javaVersion.getPlatform() == org.jackhuang.hmcl.util.platform.Platform.PLATFORM) .filter(javaVersion -> javaVersion.getPlatform() == org.jackhuang.hmcl.util.platform.Platform.getPlatform())
.filter(javaVersion -> javaVersion.getParsedVersion() == java32.getParsedVersion()) .filter(javaVersion -> javaVersion.getParsedVersion() == java32.getParsedVersion())
.max(Comparator.comparing(JavaVersion::getVersionNumber)); .max(Comparator.comparing(JavaVersion::getVersionNumber));
@@ -459,7 +459,7 @@ public final class LauncherHelper {
// Then find if other java version which satisfies requirements installed. // Then find if other java version which satisfies requirements installed.
java64 = JavaVersion.getJavas().stream() java64 = JavaVersion.getJavas().stream()
.filter(javaVersion -> javaVersion.getPlatform() == org.jackhuang.hmcl.util.platform.Platform.PLATFORM) .filter(javaVersion -> javaVersion.getPlatform() == org.jackhuang.hmcl.util.platform.Platform.getPlatform())
.filter(javaVersion -> { .filter(javaVersion -> {
if (java8requiredFinal) return javaVersion.getParsedVersion() == JavaVersion.JAVA_8; if (java8requiredFinal) return javaVersion.getParsedVersion() == JavaVersion.JAVA_8;
if (newJavaRequiredFinal) return javaVersion.getParsedVersion() >= JavaVersion.JAVA_8; if (newJavaRequiredFinal) return javaVersion.getParsedVersion() >= JavaVersion.JAVA_8;

View File

@@ -567,7 +567,7 @@ public final class VersionSetting implements Cloneable {
if (checkJava) if (checkJava)
return JavaVersion.fromExecutable(Paths.get(getJavaDir())); return JavaVersion.fromExecutable(Paths.get(getJavaDir()));
else else
return new JavaVersion(Paths.get(getJavaDir()), "", Platform.PLATFORM); return new JavaVersion(Paths.get(getJavaDir()), "", Platform.getPlatform());
} catch (IOException | InvalidPathException e) { } catch (IOException | InvalidPathException e) {
return null; // Custom Java Directory not found, return null; // Custom Java Directory not found,
} }

View File

@@ -79,18 +79,35 @@ public final class SelfDependencyPatcher {
static class DependencyDescriptor { static class DependencyDescriptor {
// private static final String REPOSITORY_URL = System.getProperty("hmcl.openjfx.repo", "https://maven.aliyun.com/repository/central/");
private static final Path DEPENDENCIES_DIR_PATH = HMCL_DIRECTORY.resolve("dependencies"); private static final Path DEPENDENCIES_DIR_PATH = HMCL_DIRECTORY.resolve("dependencies");
public static final String CURRENT_ARCH_CLASSIFIER = currentArchClassifier();
private static String currentArchClassifier() { private static String currentArchClassifier() {
switch (OperatingSystem.CURRENT_OS) { if (OperatingSystem.CURRENT_OS == OperatingSystem.LINUX) {
case LINUX: switch (Architecture.CURRENT) {
return "linux"; case X86_64:
case OSX: return "linux";
return "mac"; case ARM:
default: return "linux-arm32-monocle";
return "win"; case ARM64:
return "linux-aarch64";
}
} else if (OperatingSystem.CURRENT_OS == OperatingSystem.OSX) {
switch (Architecture.CURRENT) {
case X86_64:
return "mac";
case ARM64:
return "mac-aarch64";
}
} else if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS) {
switch (Architecture.CURRENT) {
case X86_64:
return "win";
case X86:
return "win-x86";
}
} }
return null;
} }
public String module; public String module;
@@ -100,16 +117,29 @@ public final class SelfDependencyPatcher {
public Map<String, String> sha1; public Map<String, String> sha1;
public String filename() { public String filename() {
return artifactId + "-" + version + "-" + currentArchClassifier() + ".jar"; if (CURRENT_ARCH_CLASSIFIER == null) {
return null;
}
return artifactId + "-" + version + "-" + CURRENT_ARCH_CLASSIFIER + ".jar";
} }
public String sha1() { public String sha1() {
return sha1.get(currentArchClassifier()); if (CURRENT_ARCH_CLASSIFIER == null) {
return null;
}
return sha1.get(CURRENT_ARCH_CLASSIFIER);
} }
public Path localPath() { public Path localPath() {
if (CURRENT_ARCH_CLASSIFIER == null) {
return null;
}
return DEPENDENCIES_DIR_PATH.resolve(filename()); return DEPENDENCIES_DIR_PATH.resolve(filename());
} }
public boolean isSupported() {
return CURRENT_ARCH_CLASSIFIER != null && sha1.containsKey(CURRENT_ARCH_CLASSIFIER);
}
} }
static final class Repository { static final class Repository {
@@ -192,9 +222,8 @@ public final class SelfDependencyPatcher {
throw new IncompatibleVersionException(); throw new IncompatibleVersionException();
} }
// We can only self-patch JavaFX on x86-64 platform. // We can only self-patch JavaFX on specific platform.
// For ARM support, user's manual patch is required. if (DependencyDescriptor.CURRENT_ARCH_CLASSIFIER == null) {
if (Architecture.CURRENT != Architecture.X86_64) {
throw new IncompatibleVersionException(); throw new IncompatibleVersionException();
} }
@@ -228,7 +257,14 @@ public final class SelfDependencyPatcher {
final JPanel panel = new JPanel(); final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
for (String line : i18n("repositories.chooser").split("\n")) { final String chooserText;
if (OperatingSystem.CURRENT_OS == OperatingSystem.LINUX && Architecture.CURRENT == Architecture.ARM) {
chooserText = i18n("repositories.chooser.linux_arm32");
} else {
chooserText = i18n("repositories.chooser");
}
for (String line : chooserText.split("\n")) {
panel.add(new JLabel(line)); panel.add(new JLabel(line));
} }
@@ -271,10 +307,12 @@ public final class SelfDependencyPatcher {
LOG.info(" - Loading dependencies..."); LOG.info(" - Loading dependencies...");
Set<String> modules = JFX_DEPENDENCIES.stream() Set<String> modules = JFX_DEPENDENCIES.stream()
.filter(DependencyDescriptor::isSupported)
.map(it -> it.module) .map(it -> it.module)
.collect(toSet()); .collect(toSet());
Path[] jars = JFX_DEPENDENCIES.stream() Path[] jars = JFX_DEPENDENCIES.stream()
.filter(DependencyDescriptor::isSupported)
.map(DependencyDescriptor::localPath) .map(DependencyDescriptor::localPath)
.toArray(Path[]::new); .toArray(Path[]::new);
@@ -296,7 +334,7 @@ public final class SelfDependencyPatcher {
final String url = repository.resolveDependencyURL(dependency); final String url = repository.resolveDependencyURL(dependency);
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
dialog.setStatus(url); dialog.setStatus(url);
dialog.setProgress(currentProgress, dependencies.size()); dialog.setProgress(currentProgress, dependencies.size() + 1);
}); });
LOG.info("Downloading " + url); LOG.info("Downloading " + url);
@@ -314,6 +352,9 @@ public final class SelfDependencyPatcher {
List<DependencyDescriptor> missing = new ArrayList<>(); List<DependencyDescriptor> missing = new ArrayList<>();
for (DependencyDescriptor dependency : JFX_DEPENDENCIES) { for (DependencyDescriptor dependency : JFX_DEPENDENCIES) {
if (!dependency.isSupported()) {
continue;
}
if (!Files.exists(dependency.localPath())) { if (!Files.exists(dependency.localPath())) {
missing.add(dependency); missing.add(dependency);
continue; continue;
@@ -367,10 +408,10 @@ public final class SelfDependencyPatcher {
setLocationRelativeTo(null); setLocationRelativeTo(null);
GridBagLayout gridBagLayout = new GridBagLayout(); GridBagLayout gridBagLayout = new GridBagLayout();
gridBagLayout.columnWidths = new int[] { 600, 0 }; gridBagLayout.columnWidths = new int[]{600, 0};
gridBagLayout.rowHeights = new int[] { 0, 0, 0, 200 }; gridBagLayout.rowHeights = new int[]{0, 0, 0, 200};
gridBagLayout.columnWeights = new double[] { 1.0, Double.MIN_VALUE }; gridBagLayout.columnWeights = new double[]{1.0, Double.MIN_VALUE};
gridBagLayout.rowWeights = new double[] { 0.0, 0.0, 0.0, 1.0 }; gridBagLayout.rowWeights = new double[]{0.0, 0.0, 0.0, 1.0};
panel.setLayout(gridBagLayout); panel.setLayout(gridBagLayout);
progressText = new JLabel(""); progressText = new JLabel("");

View File

@@ -521,9 +521,10 @@ profile.selected=Selected
profile.use_relative_path=Use relative path for game directory if possible profile.use_relative_path=Use relative path for game directory if possible
repositories.custom=Custom Maven Repository (%s) repositories.custom=Custom Maven Repository (%s)
repositories.maven_central=Maven Central (General) repositories.maven_central=Universal (Maven Central)
repositories.aliyun_mirror=Maven mirror for Aliyun (Chinese mainland) repositories.aliyun_mirror=Chinese mainland (Aliyun Maven Repository)
repositories.chooser=JavaFX is missing. Do you want to automatically download and load OpenJFX from web?\nSelect download source: repositories.chooser=JavaFX is missing. Do you want to automatically download and load JavaFX runtime components from web?\nSelect 'Yes' to download the JavaFX runtime components from the specified download source and start the HMCL, or select 'No' to exit the program.\nDownload Source:
repositories.chooser.linux_arm32=JavaFX is missing. Do you want to automatically download and load JavaFX runtime components from web?\nSelect 'Yes' to download the JavaFX runtime components from the specified download source and start the HMCL, or select 'No' to exit the program.\nNote: Some components cannot be downloaded temporarily on Linux ARM32 platform, so HMCL may crash at runtime.\nDownload Source:
repositories.chooser.title=Do you want to download JavaFX? repositories.chooser.title=Do you want to download JavaFX?
resourcepack=Resource Pack resourcepack=Resource Pack

View File

@@ -496,10 +496,11 @@ profile.title=遊戲目錄
profile.selected=已選取 profile.selected=已選取
profile.use_relative_path=如可行,則在遊戲目錄使用相對路徑 profile.use_relative_path=如可行,則在遊戲目錄使用相對路徑
repositories.custom= Maven 倉庫(%s repositories.custom=定義 Maven 倉庫(%s
repositories.maven_central=Maven Central(通用 repositories.maven_central=全球(Maven Central
repositories.aliyun_mirror=阿里雲 Maven 鏡像源(中國大陸 repositories.aliyun_mirror=中國大陸(阿里雲 Maven 倉庫
repositories.chooser=JavaFX 缺失。是否需要從網下載並載入 OpenJFX\n請選擇下載源: repositories.chooser=缺少 JavaFX 運行環境。是否需要從網下載並加載 JavaFX 運行時組件?\n選擇“是”從指定下載源下載 JavaFX 運行時組件並啟動HMCL選擇“否”退出程式。\n下載源:
repositories.chooser.linux_arm32=缺少 JavaFX 運行環境。是否需要從網絡下載並加載 JavaFX 運行時組件?\n選擇“是”從指定下載源下載 JavaFX 運行時組件並啟動HMCL選擇“否”退出程式。\n注意Linux ARM32 平臺下暫時無法下載部分組件運行時可能造成HMCL崩潰。\n下載源
repositories.chooser.title=是否下載 JavaFX repositories.chooser.title=是否下載 JavaFX
resourcepack=資源包 resourcepack=資源包

View File

@@ -529,9 +529,10 @@ profile.selected=已选中
profile.use_relative_path=若可能,游戏目录使用相对路径 profile.use_relative_path=若可能,游戏目录使用相对路径
repositories.custom=自定义 Maven 仓库(%s repositories.custom=自定义 Maven 仓库(%s
repositories.maven_central=Maven Central(通用 repositories.maven_central=全球(Maven Central
repositories.aliyun_mirror=阿里云 Maven 镜像源(中国大陆 repositories.aliyun_mirror=中国大陆(阿里云 Maven 仓库
repositories.chooser=JavaFX 缺失。是否需要从网络下载并加载 OpenJFX\n选择下载源: repositories.chooser=缺少 JavaFX 运行环境,是否需要从网络下载并加载 JavaFX 运行时组件\n选择“是”从指定下载源下载 JavaFX 运行时组件并启动 HMCL选择“否”退出程序。\n下载源:
repositories.chooser.linux_arm32=缺少 JavaFX 运行环境,是否需要从网络下载并加载 JavaFX 运行时组件?\n选择“是”从指定下载源下载 JavaFX 运行时组件并启动 HMCL选择“否”退出程序。\n注意Linux ARM32 平台下暂时无法下载部分组件,运行时可能造成 HMCL 崩溃。\n下载源
repositories.chooser.title=是否下载 JavaFX repositories.chooser.title=是否下载 JavaFX
resourcepack=资源包 resourcepack=资源包

View File

@@ -3,66 +3,88 @@
"module": "javafx.base", "module": "javafx.base",
"groupId": "org.openjfx", "groupId": "org.openjfx",
"artifactId": "javafx-base", "artifactId": "javafx-base",
"version": "16", "version": "17",
"sha1": { "sha1": {
"linux": "7d6b85ec89e99ea40c2a63bb1f23d43e05cd2557", "linux": "476c7640c2320244d3156edbbc19a7eda275c1ed",
"mac": "ea97d8a5ab95d070df86de1215f29f08378c98c8", "linux-arm32-monocle": "1dad2b0479066fc65ce83ae276632b0be4a648f7",
"win": "e0564fea3f27dd3a10fa62e5005612333fc244bc" "linux-aarch64": "b62b6cae95847fda1dce4a8a29edcf8a31b85333",
} "mac": "61d52392b063be78f7cc1b0fbfc04dda7a835a15",
}, "mac-aarch64": "d77b645fa3e1a6270783178541944e4b4a457cd2",
{ "win": "b63b9696f73009ca5002f49ec4db73576e2de168",
"module": "javafx.controls", "win-x86": "d35c89f5cb5f9dd8c54c69b4a153a94377e60931"
"groupId": "org.openjfx",
"artifactId": "javafx-controls",
"version": "16",
"sha1": {
"linux": "116b127e512d23ddb84c62017c256e7f67f5b9eb",
"mac": "8df933b095bdd8203dc937e39e3a9f199654e47e",
"win": "65cdeae29c67d25932dcc66ca4f7d269923631ba"
}
},
{
"module": "javafx.fxml",
"groupId": "org.openjfx",
"artifactId": "javafx-fxml",
"version": "16",
"sha1": {
"linux": "c7147c450773c3d4fd038ac9d1a6fdebbc3c11e0",
"mac": "7e4f07a331991485560673a398d6988cc805b67f",
"win": "369f646fc29d2223cc98cfc3c059f2409b3e8fcb"
} }
}, },
{ {
"module": "javafx.graphics", "module": "javafx.graphics",
"groupId": "org.openjfx", "groupId": "org.openjfx",
"artifactId": "javafx-graphics", "artifactId": "javafx-graphics",
"version": "16", "version": "17",
"sha1": { "sha1": {
"linux": "01bf2fd9f083daa2f492c4c58c4f7d5acb6f4b7d", "linux": "88dc59568c14ec37ea1c42b3ba472d78b4b1030a",
"mac": "a45de3d40e217f7ba22cecf54abc281d13a172f6", "linux-arm32-monocle": "44284bba939b1249fcc3f5502a70bd48e88e1fa9",
"win": "0cd18f8477818b40cfdbcfec7e2fc15f632f0a2f" "linux-aarch64": "40bd7094b8f43d4637a8a274b4b199835d6cfd5c",
"mac": "8b1d1124ce83e874db390016913fba7708f3592d",
"mac-aarch64": "b6326f61f7e0effbf733d62e83b8317eb8e768b4",
"win": "2c56d252b97eba8b42f049c6ce145172d744ce08",
"win-x86": "c4d74a11a7ffb182fb43803756e678c87876a0a4"
}
},
{
"module": "javafx.controls",
"groupId": "org.openjfx",
"artifactId": "javafx-controls",
"version": "17",
"sha1": {
"linux": "851a1896fbd8548fb3671aa689b305b2cfad956a",
"linux-arm32-monocle": "9add14fda362a1a2d1cd3a84de60d67da2d7a5ae",
"linux-aarch64": "eb4116ebad81183980dde74b072a15b0f6c795ef",
"mac": "e73acf695ffccb4f904ff7b76de8999eefb547c2",
"mac-aarch64": "2254b351c1e6ce2ac9adcd3480fed883cebbb08b",
"win": "efc0f4edde079c22987064922530c67fa1350a9b",
"win-x86": "c9997e885f2dd71d8a4a7b89bc510923d2d412d6"
}
},
{
"module": "javafx.fxml",
"groupId": "org.openjfx",
"artifactId": "javafx-fxml",
"version": "17",
"sha1": {
"linux": "0a6f029f4fab0f01f00a838de1e65e20c6a92f02",
"linux-arm32-monocle": "922b73ca1813dfa87e66613d2904286bdd06e7f1",
"linux-aarch64": "7cd2f92f399f48acedc85636c9f07f6634d29669",
"mac": "54026a476bb95426e2e159bcf25bbf0832d2b7bf",
"mac-aarch64": "09ba33b0d9c19e9dcfd76fe7d95748a933e09b3b",
"win": "08d79ed85fa9dde644d4b37d93a02a2ef2818769",
"win-x86": "3bde4e98cee0a464f327b9e983aded3017fddbc0"
} }
}, },
{ {
"module": "javafx.media", "module": "javafx.media",
"groupId": "org.openjfx", "groupId": "org.openjfx",
"artifactId": "javafx-media", "artifactId": "javafx-media",
"version": "16", "version": "17",
"sha1": { "sha1": {
"linux": "10edb5fd8eb64b3312b31225c396e1850b9d178b", "linux": "e3bb829ce1447a37a8b0b669a446e0414e54e5c7",
"mac": "9e0248083267cdc22b2b698f0b0b62b7399ad32d", "linux-aarch64": "7e7a50e66e44b902c624680601d5336d7fd16614",
"win": "6d776658906fc25051734bc6b03f214cc72c808e" "mac": "ef463caf627c4c97b8e5c6a5ae16050c56aed966",
"mac-aarch64": "970178b32e17650591698bae9f23bf5ce1295bb6",
"win": "6012cc30ced1539f167b64959cb9d6a4283f7aa7",
"win-x86": "8568e1edcfc803a75349124b21a27c0d609b3870"
} }
}, },
{ {
"module": "javafx.web", "module": "javafx.web",
"groupId": "org.openjfx", "groupId": "org.openjfx",
"artifactId": "javafx-web", "artifactId": "javafx-web",
"version": "16", "version": "17",
"sha1": { "sha1": {
"linux": "522f626e1798a7d589d9b187ca5c74c5c2f8a0ee", "linux": "bbd71beaf561b72f0d3eb6268d3114573b7799c3",
"mac": "32b0e13b649ea828e7d185187f178680cc04e564", "linux-aarch64": "3cd86d9593e63ce7cbd5f9b5a09f8dcc0bbd7fdb",
"win": "d2f80089a4ae1629a5ec14637abf4f6d70b96dab" "mac": "bf188c003e54ffb4cff6a9be7ce437fa269964fe",
"mac-aarch64": "a9408d443fa95cd3e2b1f170a3abeaace33d3af5",
"win": "be4a308dbcc947af2a9d9c42a72fd7f6d0ba77b9",
"win-x86": "3d93e1801c720747d4551de26ef5869ff9eacabc"
} }
} }
] ]

View File

@@ -94,7 +94,7 @@ public class Library implements Comparable<Library>, Validation {
public String getClassifier() { public String getClassifier() {
if (artifact.getClassifier() == null) if (artifact.getClassifier() == null)
if (natives != null && natives.containsKey(OperatingSystem.CURRENT_OS)) if (natives != null && natives.containsKey(OperatingSystem.CURRENT_OS))
return natives.get(OperatingSystem.CURRENT_OS).replace("${arch}", Platform.PLATFORM.getBit()); return natives.get(OperatingSystem.CURRENT_OS).replace("${arch}", Platform.getPlatform().getBit());
else else
return null; return null;
else else

View File

@@ -165,7 +165,7 @@ public final class JavaVersion {
CURRENT_JAVA = new JavaVersion( CURRENT_JAVA = new JavaVersion(
currentExecutable, currentExecutable,
System.getProperty("java.version"), System.getProperty("java.version"),
Platform.PLATFORM); Platform.getPlatform());
} }
private static Collection<JavaVersion> JAVAS; private static Collection<JavaVersion> JAVAS;

View File

@@ -47,7 +47,9 @@ public enum Platform {
/** /**
* The platform of current Java Environment. * The platform of current Java Environment.
*/ */
public static final Platform PLATFORM = Architecture.CURRENT.getPlatform(); public static Platform getPlatform() {
return Architecture.CURRENT.getPlatform();
}
/** /**
* The json serializer to {@link Platform}. * The json serializer to {@link Platform}.

View File

@@ -3,6 +3,9 @@ buildscript {
mavenCentral() mavenCentral()
maven { url 'https://plugins.gradle.org/m2/' } maven { url 'https://plugins.gradle.org/m2/' }
} }
dependencies {
classpath group: 'com.google.code.gson', name: 'gson', version: '2.8.1'
}
} }
plugins { plugins {
@@ -53,3 +56,70 @@ subprojects {
} }
defaultTasks 'clean', 'build' defaultTasks 'clean', 'build'
var jfxModules = ['base', 'graphics', 'controls', 'fxml', 'media', 'web']
var jfxArches = ['linux', 'linux-arm32-monocle', 'linux-aarch64', 'mac', 'mac-aarch64', 'win', 'win-x86']
var jfxVersion = "17"
var jfxRepos = ['https://repo1.maven.org/maven2', 'https://maven.aliyun.com/repository/central']
var jfxDependenciesFile = file('HMCL/src/main/resources/assets/openjfx-dependencies.json')
var jfxUnsupported = [
'linux-arm32-monocle': ['media', 'web']
]
import com.google.gson.*
task 'generateOpenJFXDependencies' {
doLast {
var jfxDependencies = new JsonArray()
jfxModules.forEach { module ->
JsonObject m = new JsonObject()
m.addProperty("module", "javafx.$module")
m.addProperty("groupId", "org.openjfx")
m.addProperty("artifactId", "javafx-$module")
m.addProperty("version", jfxVersion)
var sha1 = new JsonObject()
jfxArches.forEach { arch ->
if (jfxUnsupported.getOrDefault(arch, []).contains(module)) {
return
}
sha1.addProperty(
arch,
new URL("${jfxRepos.head()}/org/openjfx/javafx-$module/$jfxVersion/javafx-$module-$jfxVersion-${arch}.jar.sha1").getText("UTF-8")
)
}
m.add("sha1", sha1)
jfxDependencies.add(m)
}
jfxDependenciesFile.text = new GsonBuilder().setPrettyPrinting().create().toJson(jfxDependencies)
}
}
// Ensure that the mirror repository caches files
task 'preTouchOpenJFXDependencies' {
doLast {
jfxRepos.tail().forEach { repo ->
jfxModules.forEach { module ->
jfxArches.forEach { arch ->
if (jfxUnsupported.getOrDefault(arch, []).contains(module)) {
return
}
var jarUrl = "$repo/org/openjfx/javafx-$module/$jfxVersion/javafx-$module-$jfxVersion-${arch}.jar"
[jarUrl, jarUrl + ".sha1"].forEach { url ->
try {
new URL(url).getBytes()
System.out.println(url)
} catch (Throwable ignored) {
ignored.printStackTrace()
}
}
}
}
}
}
}

View File

@@ -1,30 +0,0 @@
#!/bin/bash
set -e
modules=(base controls fxml graphics media web)
arches=(linux mac win)
version=16
echo '['
for module in ${modules[@]}; do
if [[ ! "$module" == "${modules[0]}" ]]; then
echo ','
fi
echo ' {'
echo ' "module": "javafx.'$module'",'
echo ' "groupId": "org.openjfx",'
echo ' "artifactId": "javafx-'$module'",'
echo ' "version": "'$version'",'
echo ' "sha1": {'
for arch in ${arches[@]}; do
if [[ ! "$arch" == "${arches[0]}" ]]; then
echo ','
fi
echo -n ' "'$arch'": "'$(curl -Ss "https://repo1.maven.org/maven2/org/openjfx/javafx-$module/$version/javafx-$module-$version-$arch.jar.sha1")'"'
done
echo
echo ' }'
echo -n ' }'
done
echo
echo ']'