Skip to content

Commit

Permalink
Merge pull request #32 from neilcsmith-net/macos-arch
Browse files Browse the repository at this point in the history
Support arch option for building Swift launcher
  • Loading branch information
neilcsmith-net committed Jul 10, 2023
2 parents bed510e + 7fc49b0 commit 8e0f109
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.netbeans.nbpackage.AbstractPackagerTask;
Expand All @@ -44,6 +45,9 @@ class AppBundleTask extends AbstractPackagerTask {
private static final String JAR_BIN_FILENAME = "jarBinaries";
private static final String ENTITLEMENTS_FILENAME = "sandbox.plist";
private static final String LAUNCHER_SRC_DIRNAME = "macos-launcher-src";
private static final String ARCH_X86_64 = "x86_64";
private static final String ARCH_ARM64 = "arm64";
private static final String ARCH_UNIVERSAL = "universal";

private String bundleName;

Expand All @@ -55,9 +59,9 @@ class AppBundleTask extends AbstractPackagerTask {
protected void checkPackageRequirements() throws Exception {
String[] cmds;
if (context().getValue(MacOS.CODESIGN_ID).isEmpty()) {
cmds = new String[] {"swift"};
cmds = new String[]{"swift"};
} else {
cmds = new String[] {"swift", "codesign"};
cmds = new String[]{"swift", "codesign"};
}
validateTools(cmds);
}
Expand Down Expand Up @@ -94,7 +98,8 @@ protected Path buildPackage(Path image) throws Exception {
.findFirst()
.map(path -> path.getFileName().toString())
.orElseThrow();
Path launcher = compileLauncher(image.resolve(LAUNCHER_SRC_DIRNAME));
String arch = findArch();
Path launcher = compileLauncher(image.resolve(LAUNCHER_SRC_DIRNAME), arch);
Files.copy(launcher, bundle.resolve("Contents")
.resolve("MacOS").resolve(execName),
StandardCopyOption.COPY_ATTRIBUTES);
Expand Down Expand Up @@ -172,7 +177,7 @@ private String sanitizeBundleID(String name) {
}

private Path findLauncher(Path binDir) throws IOException {
try ( var files = Files.list(binDir)) {
try (var files = Files.list(binDir)) {
return files.filter(f -> !f.getFileName().toString().endsWith(".exe"))
.findFirst().orElseThrow(IOException::new);
}
Expand Down Expand Up @@ -226,8 +231,8 @@ private void setupLauncherSource(Path image) throws IOException {

private void setupSigningConfiguration(Path image, Path bundle) throws IOException {
Files.writeString(image.resolve(ENTITLEMENTS_FILENAME),
MacOS.ENTITLEMENTS_TEMPLATE.load(context())
, StandardOpenOption.CREATE_NEW);
MacOS.ENTITLEMENTS_TEMPLATE.load(context()),
StandardOpenOption.CREATE_NEW);
var nativeBinaries = FileUtils.find(bundle,
context().getValue(MacOS.SIGNING_FILES).orElseThrow());
Files.writeString(image.resolve(NATIVE_BIN_FILENAME),
Expand All @@ -246,17 +251,55 @@ private void setupSigningConfiguration(Path image, Path bundle) throws IOExcepti
StandardOpenOption.CREATE_NEW);
}

private Path compileLauncher(Path launcherProject) throws IOException, InterruptedException {
var pb = new ProcessBuilder("swift", "build",
"--configuration", "release",
"--arch", "x86_64");
private Path compileLauncher(Path launcherProject, String arch) throws IOException, InterruptedException {
final ProcessBuilder pb;
switch (arch) {
case ARCH_X86_64:
pb = new ProcessBuilder("swift", "build",
"--configuration", "release",
"--arch", "x86_64");
break;
case ARCH_ARM64:
pb = new ProcessBuilder("swift", "build",
"--configuration", "release",
"--arch", "arm64");
break;
default:
pb = new ProcessBuilder("swift", "build",
"--configuration", "release",
"--arch", "arm64",
"--arch", "x86_64");
}
pb.directory(launcherProject.toFile());
context().exec(pb);
Path launcher = launcherProject.resolve(".build/release/AppLauncher");
if (!Files.exists(launcher)) {
throw new IOException(launcher.toString());
var output = FileUtils.find(launcherProject.resolve(".build"), "**/{R,r}elease/AppLauncher");
if (output.isEmpty()) {
throw new IOException(launcherProject.toString());
}
return output.get(0);
}

private String findArch() {
var arch = context().getValue(MacOS.ARCH).orElse("").toLowerCase(Locale.ROOT);
if (arch.isBlank()) {
var runtimeName = context().getValue(NBPackage.PACKAGE_RUNTIME)
.map(path -> path.getFileName().toString().toLowerCase(Locale.ROOT))
.orElse("");
if (runtimeName.isBlank()) {
return ARCH_UNIVERSAL;
}
if (runtimeName.contains(ARCH_X86_64) || runtimeName.contains("x64")) {
return ARCH_X86_64;
}
if (runtimeName.contains(ARCH_ARM64) || runtimeName.contains("aarch64")) {
return ARCH_ARM64;
}
} else if (ARCH_ARM64.equals(arch) || ARCH_X86_64.equals(arch)
|| ARCH_UNIVERSAL.equals(arch)) {
return arch;
}
return launcher;
context().warningHandler().accept(MacOS.MESSAGES.getString("message.unknownarch"));
return ARCH_UNIVERSAL;
}

private void signBinariesInJARs(Path image, Path entitlements, String id)
Expand All @@ -282,7 +325,7 @@ private void signBinariesInJARs(Path image, Path entitlements, String id)
}

private void signNativeBinaries(Path image, Path entitlements, String id)
throws IOException {
throws IOException {
Path nativeFiles = image.resolve(NATIVE_BIN_FILENAME);
if (!Files.exists(nativeFiles)) {
return;
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/org/apache/netbeans/nbpackage/macos/MacOS.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ class MacOS {
static final Template INFO_TEMPLATE
= Template.of(INFO_TEMPLATE_PATH, "Info.plist.template",
() -> MacOS.class.getResourceAsStream("Info.plist.template"));
/**
* Target system architecture to use for building launcher, etc. Currently
* supported values are aarch64, x86_64 and universal. Default attempts to
* parse from runtime file, if present, or universal.
*/
static final Option<String> ARCH
= Option.ofString("package.macos.arch",
MESSAGES.getString("option.arch.help"));

/**
* Optional launcher (main.swift) template path.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public class PkgPackager implements Packager {
MacOS.BUNDLE_ID,
MacOS.ICON_PATH,
MacOS.INFO_TEMPLATE_PATH,
MacOS.ARCH,
MacOS.LAUNCHER_TEMPLATE_PATH,
MacOS.ENTITLEMENTS_TEMPLATE_PATH,
MacOS.SIGNING_FILES,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
# Option file help comments
option.bundle_id.help=Value for CFBundleIdentifier.
option.icon.help=Path to icon file (*.icns). Defaults to Apache NetBeans logo.
option.arch.help=Optional target system architecture (arm64, x86_64 or universal). Defaults to parsing runtime or universal.
option.info_template.help=Optional path to Info.plist template.
option.launcher_template.help=Optional path to launcher (main.swift) template.
option.entitlements_template.help=Optional path to codesign entitlements template.
Expand All @@ -31,3 +32,4 @@ message.validatingtools=Validating required tools - {0}
message.missingtool=Cannot find required tool - {0}
message.nocodesignid=No codesign ID has been configured. App bundle will be unsigned.
message.nopkgbuildid=No pkgbuild ID has been configured. Installer will be unsigned.
message.unknownarch=Architecture is not recognised, defaulting to universal.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version:5.1
// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to build this package.
/*
* Licensed to the Apache Software Foundation (ASF) under one
Expand All @@ -24,7 +24,7 @@ import PackageDescription
let package = Package(
name: "AppLauncher",
platforms: [
.macOS(.v10_13)
.macOS(.v11)
],
dependencies: [],
targets: [
Expand Down

0 comments on commit 8e0f109

Please sign in to comment.