diff --git a/src/main/java/com/gluonhq/substrate/Constants.java b/src/main/java/com/gluonhq/substrate/Constants.java index 84ca68161..54c3091c7 100644 --- a/src/main/java/com/gluonhq/substrate/Constants.java +++ b/src/main/java/com/gluonhq/substrate/Constants.java @@ -35,41 +35,6 @@ public class Constants { public static final Path USER_SUBSTRATE_PATH = Path.of(System.getProperty("user.home")) .resolve(".gluon").resolve("substrate"); - /** - * Triplet architecture - */ - public static final String ARCH_AMD64 = "x86_64"; - public static final String ARCH_ARM64 = "arm64"; - public static final String ARCH_AARCH64 = "aarch64"; - - /** - * Triplet vendor - */ - public static final String VENDOR_APPLE = "apple"; - public static final String VENDOR_LINUX = "linux"; - public static final String VENDOR_MICROSOFT = "microsoft"; - - /** - * Triplet OS - */ - public static final String OS_DARWIN = "darwin"; - public static final String OS_IOS = "ios"; - public static final String OS_LINUX = "linux"; - public static final String OS_WINDOWS = "windows"; - public static final String OS_ANDROID = "android"; - - /** - * Predefined Profiles - */ - public enum Profile { - LINUX, // (x86_64-linux-linux) - MACOS, // (x86_64-apple-darwin) - WINDOWS, // (x86_64-windows-windows) - IOS, // (aarch64-apple-ios) - IOS_SIM, // (x86_64-apple-ios) - ANDROID // (aarch64-linux-android); - }; - /** * Supported hosts * @@ -88,17 +53,6 @@ public enum Profile { @Deprecated public static final String TARGET_IOS = "ios"; @Deprecated public static final String TARGET_IOS_SIM = "ios-sim"; - /** - * Supported profiles - * - */ - public static final String PROFILE_HOST = "host"; // either mac or linux, based on host - public static final String PROFILE_MAC = "macos"; - public static final String PROFILE_LINUX = "linux"; - public static final String PROFILE_IOS = "ios"; - public static final String PROFILE_IOS_SIM = "ios-sim"; - public static final String PROFILE_ANDROID = "android"; - public static final String DEFAULT_JAVA_STATIC_SDK_VERSION = "14-ea+5"; public static final String DEFAULT_JAVAFX_STATIC_SDK_VERSION = "14-ea+gvm2"; diff --git a/src/main/java/com/gluonhq/substrate/SubstrateDispatcher.java b/src/main/java/com/gluonhq/substrate/SubstrateDispatcher.java index a1e692034..e33bfd566 100644 --- a/src/main/java/com/gluonhq/substrate/SubstrateDispatcher.java +++ b/src/main/java/com/gluonhq/substrate/SubstrateDispatcher.java @@ -31,12 +31,8 @@ import com.gluonhq.substrate.model.InternalProjectConfiguration; import com.gluonhq.substrate.model.ProcessPaths; import com.gluonhq.substrate.model.Triplet; -import com.gluonhq.substrate.target.AndroidTargetConfiguration; -import com.gluonhq.substrate.target.DarwinTargetConfiguration; -import com.gluonhq.substrate.target.IosTargetConfiguration; -import com.gluonhq.substrate.target.LinuxTargetConfiguration; import com.gluonhq.substrate.target.TargetConfiguration; -import com.gluonhq.substrate.target.WindowsTargetConfiguration; +import com.gluonhq.substrate.target.TripletProfile; import com.gluonhq.substrate.util.Strings; import java.io.IOException; @@ -61,7 +57,7 @@ public static void main(String[] args) throws Exception { String appName = Optional.ofNullable(System.getProperty("appname")).orElse("anonymousApp"); String targetProfile = System.getProperty("targetProfile"); - Triplet targetTriplet = targetProfile != null? new Triplet(Constants.Profile.valueOf(targetProfile.toUpperCase())) + Triplet targetTriplet = targetProfile != null? new Triplet(TripletProfile.valueOf(targetProfile.toUpperCase())) :Triplet.fromCurrentOS(); String expected = System.getProperty("expected"); @@ -156,14 +152,7 @@ public SubstrateDispatcher(Path buildRoot, ProjectConfiguration config) throws I } private TargetConfiguration getTargetConfiguration(Triplet targetTriplet) { - switch (targetTriplet.getOs()) { - case Constants.OS_LINUX : return new LinuxTargetConfiguration(paths, config); - case Constants.OS_DARWIN : return new DarwinTargetConfiguration(paths, config); - case Constants.OS_WINDOWS: return new WindowsTargetConfiguration(paths, config); - case Constants.OS_IOS : return new IosTargetConfiguration(paths, config); - case Constants.OS_ANDROID: return new AndroidTargetConfiguration(paths, config); - default : return null; - } + return targetTriplet.getOs().getTargetConfiguration(paths, config); } diff --git a/src/main/java/com/gluonhq/substrate/model/InternalProjectConfiguration.java b/src/main/java/com/gluonhq/substrate/model/InternalProjectConfiguration.java index 2ce11def3..52b649843 100644 --- a/src/main/java/com/gluonhq/substrate/model/InternalProjectConfiguration.java +++ b/src/main/java/com/gluonhq/substrate/model/InternalProjectConfiguration.java @@ -29,6 +29,7 @@ import com.gluonhq.substrate.Constants; import com.gluonhq.substrate.ProjectConfiguration; +import com.gluonhq.substrate.target.OS; import com.gluonhq.substrate.util.Strings; import java.io.BufferedReader; @@ -374,7 +375,7 @@ public void canRunNativeImage() throws IOException { if (!Files.exists(graalPath)) throw new IOException("Path provided for GraalVM doesn't exist: " + graalPath); Path binPath = graalPath.resolve("bin"); if (!Files.exists(binPath)) throw new IOException("Path provided for GraalVM doesn't contain a bin directory: " + graalPath); - Path niPath = Constants.OS_WINDOWS.equals(getHostTriplet().getOs()) ? + Path niPath = OS.WINDOWS.equals(getHostTriplet().getOs()) ? binPath.resolve("native-image.cmd") : binPath.resolve("native-image"); if (!Files.exists(niPath)) throw new IOException("Path provided for GraalVM doesn't contain bin/native-image: " + graalPath + "\n" + diff --git a/src/main/java/com/gluonhq/substrate/model/Triplet.java b/src/main/java/com/gluonhq/substrate/model/Triplet.java index 5306c1cf4..ffc30df58 100644 --- a/src/main/java/com/gluonhq/substrate/model/Triplet.java +++ b/src/main/java/com/gluonhq/substrate/model/Triplet.java @@ -27,18 +27,15 @@ */ package com.gluonhq.substrate.model; -import com.gluonhq.substrate.Constants; import com.gluonhq.substrate.target.*; -import java.util.Locale; - -import static com.gluonhq.substrate.Constants.*; +import java.util.Objects; public class Triplet { - private String arch; - private String vendor; - private String os; + private Architecture arch; + private OS os; + private Vendor vendor; /** * Creates a new triplet for the current runtime @@ -46,60 +43,21 @@ public class Triplet { * @throws IllegalArgumentException in case the current operating system is not supported */ public static Triplet fromCurrentOS() throws IllegalArgumentException { - String osName = System.getProperty("os.name").toLowerCase(Locale.ROOT); - - if (osName.contains("mac")) { - return new Triplet(Constants.Profile.MACOS); - } else if (osName.contains("nux")) { - return new Triplet(Constants.Profile.LINUX); - } else if (osName.contains("windows")) { - return new Triplet(Constants.Profile.WINDOWS); - } else { - throw new IllegalArgumentException("OS " + osName + " not supported"); - } + return new Triplet( TripletProfile.fromCurrentOS()); } public Triplet(String arch, String vendor, String os) { - this.arch = arch; - this.vendor = vendor; - this.os = os; + + // following should throw exception for unsupported parts + this.arch = Architecture.valueOf(arch); + this.os = OS.valueOf(os); + this.vendor = Vendor.valueOf(vendor); } - public Triplet(Constants.Profile profile) { - switch (profile) { - case LINUX: - this.arch = ARCH_AMD64; - this.vendor = VENDOR_LINUX; - this.os = OS_LINUX; - break; - case MACOS: - this.arch = ARCH_AMD64; - this.vendor = VENDOR_APPLE; - this.os = OS_DARWIN; - break; - case WINDOWS: - this.arch = ARCH_AMD64; - this.vendor = VENDOR_MICROSOFT; - this.os = OS_WINDOWS; - break; - case IOS: - this.arch = ARCH_ARM64; - this.vendor = VENDOR_APPLE; - this.os = OS_IOS; - break; - case IOS_SIM: - this.arch = ARCH_AMD64; - this.vendor = VENDOR_APPLE; - this.os = OS_IOS; - break; - case ANDROID: - this.arch = ARCH_AARCH64; - this.vendor = VENDOR_LINUX; - this.os = OS_ANDROID; - break; - default: - throw new IllegalArgumentException("Triplet for profile "+profile+" is not supported yet"); - } + public Triplet(TripletProfile profile) { + Objects.requireNonNull(profile); + this.arch = profile.getArch(); + this.os = profile.getOs(); } /* @@ -111,34 +69,22 @@ public boolean canCompileTo(Triplet target) { if (getOs().equals(target.getOs())) return true; // if host is linux and target is ios, fail - return (!Constants.OS_LINUX.equals(getOs()) && !Constants.OS_WINDOWS.equals(getOs())) || - !Constants.OS_IOS.equals(target.getOs()); + return (!OS.LINUX.equals(getOs()) && !OS.WINDOWS.equals(getOs())) || + !OS.IOS.equals(target.getOs()); } - public String getArch() { + public Architecture getArch() { return arch; } - public void setArch(String arch) { - this.arch = arch; - } - - public String getVendor() { + public Vendor getVendor() { return vendor; } - public void setVendor(String vendor) { - this.vendor = vendor; - } - - public String getOs() { + public OS getOs() { return os; } - public void setOs(String os) { - this.os = os; - } - public String getArchOs() { return this.arch+"-"+this.os; } @@ -153,8 +99,8 @@ public String getOsArch() { * @return */ public String getOsArch2() { - String myarch = this.arch; - if (myarch.equals("x86_64")) { + String myarch = this.arch.toString(); + if ( "x86_64".equals(myarch)) { myarch = "amd64"; } return this.os+"-"+myarch; @@ -162,6 +108,6 @@ public String getOsArch2() { @Override public String toString() { - return arch + '-' + vendor + '-' + os; + return arch.toString() + '-' + vendor + '-' + os; } } diff --git a/src/main/java/com/gluonhq/substrate/target/AbstractTargetConfiguration.java b/src/main/java/com/gluonhq/substrate/target/AbstractTargetConfiguration.java index 6bdf30ab5..f7a38ce01 100644 --- a/src/main/java/com/gluonhq/substrate/target/AbstractTargetConfiguration.java +++ b/src/main/java/com/gluonhq/substrate/target/AbstractTargetConfiguration.java @@ -108,7 +108,7 @@ public boolean compile(String cp) throws IOException, InterruptedException { extractNativeLibs(cp); Triplet target = projectConfiguration.getTargetTriplet(); String suffix = target.getArchOs(); - String jniPlatform = getJniPlatform(target.getOs()); + String jniPlatform = target.getOs().getJniPlatform(); if (!compileAdditionalSources()) { return false; } @@ -326,17 +326,6 @@ private boolean compileAdditionalSources() return true; } - private String getJniPlatform( String os ) { - switch (os) { - case Constants.OS_LINUX: return "LINUX_AMD64"; - case Constants.OS_IOS:return "DARWIN_AARCH64"; - case Constants.OS_DARWIN: return "DARWIN_AMD64"; - case Constants.OS_WINDOWS: return "WINDOWS_AMD64"; - case Constants.OS_ANDROID: return "LINUX_AARCH64"; - default: throw new IllegalArgumentException("No support yet for " + os); - } - } - /* * Make sure the clibraries needed for linking are available for this particular configuration. * The clibraries path is available by default in GraalVM, but the directory for cross-platform libs may diff --git a/src/main/java/com/gluonhq/substrate/target/Architecture.java b/src/main/java/com/gluonhq/substrate/target/Architecture.java new file mode 100644 index 000000000..2a03f0250 --- /dev/null +++ b/src/main/java/com/gluonhq/substrate/target/Architecture.java @@ -0,0 +1,21 @@ +package com.gluonhq.substrate.target; + +/** + * Triplet architecture + */ +public enum Architecture { + AMD64("x86_64"), + ARM64("arm64"), + AARCH64("aarch64"); + + private final String id; + + private Architecture(String id ) { + this.id = id.toLowerCase(); + } + + @Override + public String toString() { + return id; + } +} diff --git a/src/main/java/com/gluonhq/substrate/target/IosTargetConfiguration.java b/src/main/java/com/gluonhq/substrate/target/IosTargetConfiguration.java index e182cea44..f5c76a3ea 100644 --- a/src/main/java/com/gluonhq/substrate/target/IosTargetConfiguration.java +++ b/src/main/java/com/gluonhq/substrate/target/IosTargetConfiguration.java @@ -83,7 +83,7 @@ List getTargetSpecificLinkLibraries() { @Override List getTargetSpecificLinkFlags(boolean useJavaFX, boolean usePrismSW) { List linkFlags = new ArrayList<>(Arrays.asList("-w", "-fPIC", - "-arch", Constants.ARCH_ARM64, + "-arch", Architecture.ARM64.toString(), "-mios-version-min=11.0", "-isysroot", getSysroot())); if (useJavaFX) { @@ -101,7 +101,7 @@ List getTargetSpecificLinkFlags(boolean useJavaFX, boolean usePrismSW) { @Override List getTargetSpecificCCompileFlags() { return Arrays.asList("-xobjective-c", - "-arch", getArch(), + "-arch", getArch().toString(), "-isysroot", getSysroot()); } @@ -222,7 +222,7 @@ String processClassPath(String classPath) throws IOException { fileDeps.getJavaFXSDKLibsPath(),"javafx-graphics","javafx-controls" ); } - private String getArch() { + private Architecture getArch() { return projectConfiguration.getTargetTriplet().getArch(); } @@ -232,7 +232,7 @@ private String getSysroot() { } private boolean isSimulator() { - return Constants.ARCH_AMD64.equals(projectConfiguration.getTargetTriplet().getArch()); + return Architecture.AMD64.equals(projectConfiguration.getTargetTriplet().getArch()); } private void createInfoPlist(ProcessPaths paths) throws IOException { @@ -248,7 +248,7 @@ private void createInfoPlist(ProcessPaths paths) throws IOException { private boolean lipoMatch(Path path) { try { - return lipoInfo(path).indexOf(getArch()) > 0; + return lipoInfo(path).indexOf(getArch().toString()) > 0; } catch (IOException | InterruptedException e) { Logger.logSevere("Error processing lipo for " + path); } diff --git a/src/main/java/com/gluonhq/substrate/target/OS.java b/src/main/java/com/gluonhq/substrate/target/OS.java new file mode 100644 index 000000000..f094085a6 --- /dev/null +++ b/src/main/java/com/gluonhq/substrate/target/OS.java @@ -0,0 +1,62 @@ +package com.gluonhq.substrate.target; + +import com.gluonhq.substrate.model.InternalProjectConfiguration; +import com.gluonhq.substrate.model.ProcessPaths; + +import java.util.Locale; +import java.util.function.BiFunction; + +public enum OS { + + DARWIN("darwin", "DARWIN_AMD64", Vendor.APPLE, DarwinTargetConfiguration::new), + IOS("ios", "DARWIN_AARCH64", Vendor.APPLE, IosTargetConfiguration::new), + LINUX("linux", "LINUX_AMD64", Vendor.LINUX, LinuxTargetConfiguration::new), + WINDOWS("windows", "WINDOWS_AMD64", Vendor.MICROSOFT, WindowsTargetConfiguration::new), + ANDROID("android", "LINUX_AARCH64", Vendor.LINUX, AndroidTargetConfiguration::new); + + private final String id; + private final String jniPlatform; + private final Vendor vendor; + private final BiFunction targetConfiguration; + + public static OS current() { + String osName = System.getProperty("os.name").toLowerCase(Locale.ROOT); + + if (osName.contains("mac")) { + return DARWIN; + } else if (osName.contains("nux")) { + return LINUX; + } else if (osName.contains("windows")) { + return WINDOWS; + } else { + throw new IllegalArgumentException("OS " + osName + " not supported"); + } + } + + private OS(String id, + String jniPlatform, + Vendor vendor, + BiFunction targetConfiguration) { + this.id = id.toLowerCase(); + this.jniPlatform = jniPlatform; + this.vendor = vendor; + this.targetConfiguration = targetConfiguration; + } + + public Vendor getVendor() { + return vendor; + } + + public String getJniPlatform() { + return jniPlatform; + } + + public TargetConfiguration getTargetConfiguration(ProcessPaths paths, InternalProjectConfiguration configuration ) { + return targetConfiguration.apply(paths, configuration); + } + + @Override + public String toString() { + return id; + } +} diff --git a/src/main/java/com/gluonhq/substrate/target/TripletProfile.java b/src/main/java/com/gluonhq/substrate/target/TripletProfile.java new file mode 100644 index 000000000..da7ad4f11 --- /dev/null +++ b/src/main/java/com/gluonhq/substrate/target/TripletProfile.java @@ -0,0 +1,42 @@ +package com.gluonhq.substrate.target; + +import com.gluonhq.substrate.Constants; + +/** + * Predefined Profiles + */ +public enum TripletProfile { + LINUX(Architecture.AMD64, OS.LINUX), // (x86_64-linux-linux) + MACOS(Architecture.AMD64, OS.DARWIN), // (x86_64-apple-darwin) + WINDOWS(Architecture.AMD64, OS.WINDOWS), // (x86_64-windows-windows) + IOS(Architecture.ARM64, OS.IOS), // (aarch64-apple-ios) + IOS_SIM(Architecture.AMD64, OS.IOS), // (x86_64-apple-ios) + ANDROID(Architecture.AARCH64,OS.ANDROID); // (aarch64-linux-android) + + private final Architecture arch; + private final OS os; + + public static TripletProfile fromCurrentOS() { + switch (OS.current()) { + case DARWIN: return TripletProfile.MACOS; + case IOS: return TripletProfile.IOS; + case LINUX: return TripletProfile.LINUX; + case WINDOWS: return TripletProfile.WINDOWS; + case ANDROID: return TripletProfile.ANDROID; + default: throw new IllegalArgumentException("Unsupported OS"); + } + } + + TripletProfile(Architecture arch, OS os ) { + this.arch = arch; + this.os = os; + } + + public Architecture getArch() { + return arch; + } + + public OS getOs() { + return os; + } +} diff --git a/src/main/java/com/gluonhq/substrate/target/Vendor.java b/src/main/java/com/gluonhq/substrate/target/Vendor.java new file mode 100644 index 000000000..e12c6920a --- /dev/null +++ b/src/main/java/com/gluonhq/substrate/target/Vendor.java @@ -0,0 +1,18 @@ +package com.gluonhq.substrate.target; + +public enum Vendor { + APPLE("apple"), + LINUX("linux"), + MICROSOFT("microsoft"); + + private final String id; + + private Vendor(String id ) { + this.id = id.toLowerCase(); + } + @Override + public String toString() { + return id; + } + +} diff --git a/src/main/java/com/gluonhq/substrate/util/ios/CodeSigning.java b/src/main/java/com/gluonhq/substrate/util/ios/CodeSigning.java index 7f11a7114..12b776426 100644 --- a/src/main/java/com/gluonhq/substrate/util/ios/CodeSigning.java +++ b/src/main/java/com/gluonhq/substrate/util/ios/CodeSigning.java @@ -88,7 +88,7 @@ public class CodeSigning { public CodeSigning(ProcessPaths paths, InternalProjectConfiguration projectConfiguration) { this.paths = paths; this.projectConfiguration = projectConfiguration; - this.sourceOS = projectConfiguration.getTargetTriplet().getOs(); + this.sourceOS = projectConfiguration.getTargetTriplet().getOs().toString(); this.bundleId = InfoPlist.getBundleId(InfoPlist.getPlistPath(paths, sourceOS), sourceOS); appPath = paths.getAppPath().resolve(projectConfiguration.getAppName() + ".app"); diff --git a/src/main/java/com/gluonhq/substrate/util/ios/InfoPlist.java b/src/main/java/com/gluonhq/substrate/util/ios/InfoPlist.java index 35bd49406..9a6bc276d 100644 --- a/src/main/java/com/gluonhq/substrate/util/ios/InfoPlist.java +++ b/src/main/java/com/gluonhq/substrate/util/ios/InfoPlist.java @@ -87,7 +87,7 @@ public class InfoPlist { public InfoPlist(ProcessPaths paths, InternalProjectConfiguration projectConfiguration, XcodeUtils.SDKS sdk) throws IOException { this.paths = Objects.requireNonNull(paths); this.projectConfiguration = Objects.requireNonNull(projectConfiguration); - this.sourceOS = projectConfiguration.getTargetTriplet().getOs(); + this.sourceOS = projectConfiguration.getTargetTriplet().getOs().toString(); this.sdk = sdk; this.xcodeUtil = new XcodeUtils(sdk); appPath = paths.getAppPath().resolve(projectConfiguration.getAppName() + ".app"); diff --git a/src/test/java/com/gluonhq/substrate/SubstrateTest.java b/src/test/java/com/gluonhq/substrate/SubstrateTest.java index 7d1dd577e..acef7d6e6 100644 --- a/src/test/java/com/gluonhq/substrate/SubstrateTest.java +++ b/src/test/java/com/gluonhq/substrate/SubstrateTest.java @@ -29,6 +29,10 @@ import com.gluonhq.substrate.model.InternalProjectConfiguration; import com.gluonhq.substrate.model.Triplet; +import com.gluonhq.substrate.target.Architecture; +import com.gluonhq.substrate.target.OS; +import com.gluonhq.substrate.target.TripletProfile; +import com.gluonhq.substrate.target.Vendor; import org.junit.jupiter.api.Test; import java.io.IOException; @@ -41,34 +45,34 @@ class SubstrateTest { @Test void testTriplets() { - Triplet triplet = new Triplet(Constants.Profile.LINUX); - assertEquals(triplet.getArch(), Constants.ARCH_AMD64); - assertEquals(triplet.getVendor(), Constants.VENDOR_LINUX); - assertEquals(triplet.getOs(), Constants.OS_LINUX); + Triplet triplet = new Triplet(TripletProfile.LINUX); + assertEquals(triplet.getArch(), Architecture.AMD64); + assertEquals(triplet.getVendor(), Vendor.LINUX); + assertEquals(triplet.getOs(), OS.LINUX); - triplet = new Triplet(Constants.Profile.MACOS); - assertEquals(triplet.getArch(), Constants.ARCH_AMD64); - assertEquals(triplet.getVendor(), Constants.VENDOR_APPLE); - assertEquals(triplet.getOs(), Constants.OS_DARWIN); + triplet = new Triplet(TripletProfile.MACOS); + assertEquals(triplet.getArch(), Architecture.AMD64); + assertEquals(triplet.getVendor(), Vendor.APPLE); + assertEquals(triplet.getOs(), OS.DARWIN); } @Test void testWindowsTriplet() { - Triplet triplet = new Triplet(Constants.Profile.WINDOWS); - assertEquals(triplet.getArch(), Constants.ARCH_AMD64); - assertEquals(triplet.getVendor(), Constants.VENDOR_MICROSOFT); - assertEquals(triplet.getOs(), Constants.OS_WINDOWS); + Triplet triplet = new Triplet(TripletProfile.WINDOWS); + assertEquals(triplet.getArch(), Architecture.AMD64); + assertEquals(triplet.getVendor(), Vendor.MICROSOFT); + assertEquals(triplet.getOs(), OS.WINDOWS); } @Test void testIOSTriplet() throws IOException { - Triplet iosTriplet = new Triplet(Constants.Profile.IOS); + Triplet iosTriplet = new Triplet(TripletProfile.IOS); Triplet currentOsTriplet = Triplet.fromCurrentOS(); ProjectConfiguration config = new ProjectConfiguration(""); config.setTarget(iosTriplet); // when on linux, nativeCompile should throw an illegalArgumentException - if (currentOsTriplet.getOs().indexOf("nux") > 0) { + if (currentOsTriplet.getOs().toString().indexOf("nux") > 0) { var dispatcher = new SubstrateDispatcher(Path.of(System.getProperty("user.home")), config); assertThrows(NullPointerException.class, () -> dispatcher.nativeCompile(null)); }