Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: gluonhq/substrate
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 0.0.64
Choose a base ref
...
head repository: gluonhq/substrate
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 0.0.65
Choose a head ref
  • 8 commits
  • 11 files changed
  • 2 contributors

Commits on Sep 18, 2024

  1. Prepare development of 0.0.65

    abhinayagarwal committed Sep 18, 2024
    Copy the full SHA
    6ee1f25 View commit details

Commits on Oct 21, 2024

  1. Add new path for provisioning profiles starting Xcode 16 (#1292)

    * Add new path for provisioning profiles starting Xcode 16
    
    * log path
    jperedadnr authored Oct 21, 2024

    Verified

    This commit was signed with the committer’s verified signature.
    AnaisUrlichs Anais Urlichs
    Copy the full SHA
    5ad754b View commit details

Commits on Oct 24, 2024

  1. Bump JDK version (#1293)

    jperedadnr authored Oct 24, 2024
    Copy the full SHA
    f6c9687 View commit details

Commits on Nov 15, 2024

  1. Bump gradle wrapper version (#1299)

    jperedadnr authored Nov 15, 2024
    Copy the full SHA
    0515389 View commit details

Commits on Jan 16, 2025

  1. Increase timeout for codesign process (#1303)

    jperedadnr authored Jan 16, 2025
    Copy the full SHA
    20a0fbb View commit details
  2. add zip extension (#1305)

    jperedadnr authored Jan 16, 2025
    Copy the full SHA
    a4dfa98 View commit details

Commits on Jan 17, 2025

  1. Add filter check to macOS (#1301)

    * Add filter check to macOS
    
    * Use lipo for macOS
    
    * remove import
    jperedadnr authored Jan 17, 2025
    Copy the full SHA
    88d1ee3 View commit details
  2. New release: 0.0.65

    abhinayagarwal committed Jan 17, 2025
    Copy the full SHA
    93edd93 View commit details
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Substrate Version
version = 0.0.64
version = 0.0.65

jUnitVersion = 5.3.1

2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
2 changes: 1 addition & 1 deletion src/main/java/com/gluonhq/substrate/Constants.java
Original file line number Diff line number Diff line change
@@ -134,7 +134,7 @@ public static VMONE_TARGET fromTriplet(String triplet) {
public static final String PROFILE_LINUX_AARCH64 = "linux-aarch64";
public static final String PROFILE_WEB = "web";

public static final String DEFAULT_JAVA_STATIC_SDK_VERSION = "24-2";
public static final String DEFAULT_JAVA_STATIC_SDK_VERSION = "24-2.1";
public static final String DEFAULT_JAVAFX_STATIC_SDK_VERSION = "24-ea+7.1";
public static final String DEFAULT_JAVAFX_JS_SDK_VERSION = "18-internal+0-2021-09-02-165800";
public static final String DEFAULT_SYSROOT_VERSION = "20210424";
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2024, Gluon
* Copyright (c) 2019, 2025, Gluon
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -73,7 +73,7 @@ public abstract class AbstractTargetConfiguration implements TargetConfiguration
private static final List<String> RESOURCES_BY_EXTENSION = Arrays.asList(
"png", "jpg", "jpeg", "gif", "bmp", "ttf", "raw",
"xml", "fxml", "css", "gls", "json", "dat",
"license", "frag", "vert", "obj", "mtl", "js");
"license", "frag", "vert", "obj", "mtl", "js", "zip");
/**
* Manual registration of the HomeFinderFeature required until GraalVM for JDK 21.
*/
@@ -721,6 +721,7 @@ private void extractNativeLibs(String classPath) throws IOException {

List<String> jars = new ClassPath(classPath).filter(s -> s.endsWith(".jar") && !s.contains("javafx-"));
for (String jar : jars) {
Logger.logDebug("Extracting native libs from jar: " + jar);
FileOps.extractFilesFromJar("." + getStaticLibraryFileExtension(), Path.of(jar),
libPath, getTargetSpecificNativeLibsFilter());
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2022, Gluon
* Copyright (c) 2020, 2025, Gluon
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -29,10 +29,12 @@

import com.gluonhq.substrate.model.InternalProjectConfiguration;
import com.gluonhq.substrate.model.ProcessPaths;
import com.gluonhq.substrate.util.Logger;
import com.gluonhq.substrate.util.ProcessRunner;

import java.io.IOException;
import java.nio.file.Path;
import java.util.function.Predicate;

abstract class DarwinTargetConfiguration extends PosixTargetConfiguration {

@@ -50,4 +52,25 @@ public boolean createSharedLib() throws IOException, InterruptedException {
ProcessRunner process = new ProcessRunner("install_name_tool", "-id", "@rpath/" + libName, libName);
return process.runProcess("install name", lib.getParent().toFile()) == 0;
}

@Override
Predicate<Path> getTargetSpecificNativeLibsFilter() {
return this::checkFileArchitecture;
}

private boolean checkFileArchitecture(Path path) {
try {
ProcessRunner pr = new ProcessRunner("lipo", "-info", path.toFile().getAbsolutePath());
pr.showSevereMessage(false);
int op = pr.runProcess("lipo");
if (op == 0) {
return true;
}
} catch (IOException | InterruptedException e) {
Logger.logSevere("Unrecoverable error checking file " + path + ": " + e);
}
Logger.logDebug("Ignore file " + path + " since lipo failed on it");
return false;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2024, Gluon
* Copyright (c) 2019, 2025, Gluon
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -152,11 +152,6 @@ List<String> getTargetSpecificAOTCompileFlags() throws IOException {
return flags;
}

@Override
Predicate<Path> getTargetSpecificNativeLibsFilter() {
return this::lipoMatch;
}

@Override
public String getAdditionalSourceFileLocation() {
return "/native/ios/";
@@ -375,21 +370,6 @@ private Path getAndValidateAppPath() throws IOException, InterruptedException {
return app;
}

private boolean lipoMatch(Path path) {
try {
String lp = lipoInfo(path);
if (lp == null) return false;
return lp.indexOf(getTargetArch()) > 0;
} catch (IOException | InterruptedException e) {
Logger.logSevere("Error processing lipo for " + path);
}
return false;
}

private String lipoInfo(Path path) throws IOException, InterruptedException {
return ProcessRunner.runProcessForSingleOutput("lipo", "lipo", "-info", path.toFile().getAbsolutePath());
}

/*
* Copies the .cap files from the jar resource and store them in
* a directory. Return that directory
49 changes: 31 additions & 18 deletions src/main/java/com/gluonhq/substrate/util/FileOps.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2024, Gluon
* Copyright (c) 2019, 2025, Gluon
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -535,29 +535,42 @@ public static void extractFilesFromJar(List<String> extensions, Path sourceJar,
if (!Files.exists(target)) {
Files.createDirectories(target);
}
ZipFile zf = new ZipFile(sourceJar.toFile());
List<? extends ZipEntry> entries = zf.stream()
.filter(ze -> extensions.stream().anyMatch(ext -> ze.getName().endsWith(ext)))
.collect(Collectors.toList());
if (entries.isEmpty()) {
return;

List<String> uniqueObjectFileNames = new ArrayList<>();
try (Stream<Path> list = Files.list(target)) {
uniqueObjectFileNames.addAll(list
.map(p -> p.getFileName().toString())
.collect(Collectors.toList()));
} catch (Exception ex) {
Logger.logSevere("Error listing files from " + target + ": " + ex.getMessage());
}

List<String> uniqueObjectFileNames = Files.list(target)
.map(p -> p.getFileName().toString())
.collect(Collectors.toList());
try (ZipFile zf = new ZipFile(sourceJar.toFile())) {
List<? extends ZipEntry> entries = zf.stream()
.filter(ze -> extensions.stream().anyMatch(ext -> ze.getName().endsWith(ext)))
.collect(Collectors.toList());
if (entries.isEmpty()) {
return;
}

for (ZipEntry ze : entries) {
String uniqueName = new File(ze.getName()).getName();
if (!uniqueObjectFileNames.contains(uniqueName)) {
Path filePath = FileOps.copyStream(zf.getInputStream(ze), target.resolve(uniqueName));
if (filter == null || filter.test(filePath)) {
uniqueObjectFileNames.add(uniqueName);
for (ZipEntry ze : entries) {
String uniqueName = new File(ze.getName()).getName();
if (!uniqueObjectFileNames.contains(uniqueName)) {
Logger.logDebug("Testing file " + ze.getName());
Path filePath = FileOps.copyStream(zf.getInputStream(ze), target.resolve(uniqueName));
if (filter == null || filter.test(filePath)) {
Logger.logDebug("File copied, it passes the filter: " + uniqueName);
uniqueObjectFileNames.add(uniqueName);
} else {
Logger.logDebug("File not copied, doesn't pass filter: " + uniqueName);
Files.delete(filePath);
}
} else {
Logger.logDebug("File not copied, doesn't pass filter: " + uniqueName);
Files.delete(filePath);
Logger.logDebug("File " + ze.getName() + " not tested, a file with the same name already exists");
}
}
} catch (Exception ex) {
Logger.logSevere("Error extracting files from zip: " + ex.getMessage());
}
}

21 changes: 15 additions & 6 deletions src/main/java/com/gluonhq/substrate/util/ios/CodeSigning.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2024, Gluon
* Copyright (c) 2019, 2025, Gluon
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -144,7 +144,7 @@ private MobileProvision getProvisioningProfile() throws IOException {
if (providedMobileProvision == null
|| providedMobileProvision.equals(mobileProvision.getName())) {
this.identity = identity;
Logger.logDebug("Got provisioning profile: " + mobileProvision.getName());
Logger.logDebug("Got provisioning profile: " + mobileProvision.getName() + " from " + mobileProvision.getProvisioningPath());
return mobileProvision;
}
}
@@ -206,7 +206,7 @@ private MobileProvision tryModifiedBundleId(Identity identity, String bundleId,
private List<MobileProvision> retrieveValidMobileProvisions() {
final LocalDate now = LocalDate.now();
if (mobileProvisions == null) {
mobileProvisions = retrieveAllMobileProvisions();
mobileProvisions = getProvisioningProfiles();
}
return mobileProvisions.stream()
.filter(provision -> {
@@ -216,8 +216,17 @@ private List<MobileProvision> retrieveValidMobileProvisions() {
.collect(Collectors.toList());
}

public static List<MobileProvision> retrieveAllMobileProvisions() {
Path provisionPath = Paths.get(System.getProperty("user.home"), "Library", "MobileDevice", "Provisioning Profiles");
public static List<MobileProvision> getProvisioningProfiles() {
// Starting Xcode 16+:
Path provisionPath = Paths.get(System.getProperty("user.home"), "Library", "Developer", "Xcode", "UserData", "Provisioning Profiles");
List<MobileProvision> provisions = new ArrayList<>(retrieveAllMobileProvisionsFromPath(provisionPath));
// Before Xcode 16:
provisionPath = Paths.get(System.getProperty("user.home"), "Library", "MobileDevice", "Provisioning Profiles");
provisions.addAll(retrieveAllMobileProvisionsFromPath(provisionPath));
return provisions;
}

private static List<MobileProvision> retrieveAllMobileProvisionsFromPath(Path provisionPath) {
if (!Files.exists(provisionPath) || !Files.isDirectory(provisionPath)) {
Logger.logSevere("Invalid provisioning profiles folder at " + provisionPath.toString());
return Collections.emptyList();
@@ -313,7 +322,7 @@ private boolean unlockKeychain() throws IOException, InterruptedException {
public static boolean verifyCodesign(Path target) throws IOException, InterruptedException {
Logger.logDebug("Validating codesign...");
ProcessRunner runner = new ProcessRunner("codesign", "--verify", "-vvvv", target.toAbsolutePath().toString());
if (runner.runTimedProcess("verify", 5)) {
if (runner.runTimedProcess("verify", 30)) {
return runner.getResponses().stream()
.anyMatch(line -> line.contains(CODESIGN_OK_1) ||
line.contains(CODESIGN_OK_2) || line.contains(CODESIGN_OK_3));
26 changes: 18 additions & 8 deletions src/main/java/com/gluonhq/substrate/util/macos/CodeSigning.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2021, Gluon
* Copyright (c) 2019, 2025, Gluon
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -270,7 +270,7 @@ private boolean unlockKeychain() throws IOException, InterruptedException {
private boolean verifyCodesign(Path target) throws IOException, InterruptedException {
Logger.logDebug("Validating codesign...");
ProcessRunner runner = new ProcessRunner("codesign", "--verify", "-vvvv", target.toAbsolutePath().toString());
if (runner.runTimedProcess("verify", 5)) {
if (runner.runTimedProcess("verify", 30)) {
return runner.getResponses().stream()
.anyMatch(line -> line.contains(CODESIGN_OK_1) ||
line.contains(CODESIGN_OK_2) || line.contains(CODESIGN_OK_3));
@@ -377,7 +377,8 @@ private ProvisionProfile getProvisioningProfile() {
.findFirst()
.orElse(null);
}
Logger.logDebug("Provisioning profile: " + (provisionProfile != null ? provisionProfile.getName() : null));
Logger.logDebug("Got provisioning profile: " + (provisionProfile != null ?
provisionProfile.getName() + " from " + provisionProfile.getProvisioningPath() : null));
return provisionProfile;
}

@@ -393,18 +394,27 @@ private ProvisionProfile findProvisionProfile(Identity identity, String bundleId
private List<ProvisionProfile> retrieveValidProvisionProfiles() {
final LocalDate now = LocalDate.now();
if (provisionProfiles == null) {
provisionProfiles = retrieveAllProvisionProfiles().stream()
provisionProfiles = getProvisioningProfiles();
}
return provisionProfiles.stream()
.filter(provision -> {
LocalDate expirationDate = provision.getExpirationDate();
return expirationDate != null && !expirationDate.isBefore(now);
})
.collect(Collectors.toList());
}
return provisionProfiles;
}

private static List<ProvisionProfile> retrieveAllProvisionProfiles() {
Path provisionPath = Paths.get(System.getProperty("user.home"), "Library", "MobileDevice", "Provisioning Profiles");
private static List<ProvisionProfile> getProvisioningProfiles() {
// Starting Xcode 16+:
Path provisionPath = Paths.get(System.getProperty("user.home"), "Library", "Developer", "Xcode", "UserData", "Provisioning Profiles");
List<ProvisionProfile> provisions = new ArrayList<>(retrieveAllProvisionProfilesFromPath(provisionPath));
// Before Xcode 16:
provisionPath = Paths.get(System.getProperty("user.home"), "Library", "MobileDevice", "Provisioning Profiles");
provisions.addAll(retrieveAllProvisionProfilesFromPath(provisionPath));
return provisions;
}

private static List<ProvisionProfile> retrieveAllProvisionProfilesFromPath(Path provisionPath) {
if (!Files.exists(provisionPath) || !Files.isDirectory(provisionPath)) {
Logger.logSevere("Invalid provisioning profiles folder at " + provisionPath.toString());
return Collections.emptyList();
Original file line number Diff line number Diff line change
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
4 changes: 2 additions & 2 deletions src/test/java/com/gluonhq/substrate/IOSTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2021, Gluon
* Copyright (c) 2019, 2024, Gluon
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -97,7 +97,7 @@ void testSigning() {
@Test
void testProvisioning() {
assumeTrue(!isCI());
List<MobileProvision> provisions = CodeSigning.retrieveAllMobileProvisions();
List<MobileProvision> provisions = CodeSigning.getProvisioningProfiles();
assertNotNull(provisions);
assertFalse(provisions.isEmpty());
}