Author SHA1 Message Date
Local Admin e0b1719921 amended build target version numbers
Build macOS Packages / Build macOS (Intel) (push) Successful in 31s
Build macOS Packages / Build macOS (Apple Silicon) (push) Successful in 48s
Build macOS Packages / Build macOS (Universal) (push) Failing after 11s
2026-09-07 06:30:42 -07:00
Local Admin fe68c5c01d build fixes
Build macOS Packages / Build macOS (Intel) (push) Successful in 38s
Build macOS Packages / Build macOS (Apple Silicon) (push) Successful in 38s
Build macOS Packages / Build macOS (Universal) (push) Failing after 9s
2026-09-07 06:20:29 -07:00
Local Admin 1c53e698aa build fixes
Build macOS Packages / Build macOS (Intel) (push) Failing after 15s
Build macOS Packages / Build macOS (Apple Silicon) (push) Failing after 29s
Build macOS Packages / Build macOS (Universal) (push) Skipped
2026-09-07 06:11:55 -07:00
12 changed files with 93 additions and 25 deletions
+2
View File
@@ -112,6 +112,8 @@ jobs:
-scheme TargetPrint \ -scheme TargetPrint \
-destination "platform=macOS" \ -destination "platform=macOS" \
-only-testing:TargetPrintTests \ -only-testing:TargetPrintTests \
-jobs "$(sysctl -n hw.ncpu 2>/dev/null || echo 4)" \
-parallelizeTargets \
CODE_SIGNING_ALLOWED=NO \ CODE_SIGNING_ALLOWED=NO \
ONLY_ACTIVE_ARCH=YES ONLY_ACTIVE_ARCH=YES
+10
View File
@@ -4,3 +4,13 @@
#import <cups/cups.h> #import <cups/cups.h>
#import <cups/ppd.h> #import <cups/ppd.h>
// The Swift CUPS overlay marks cupsGetPPD unavailable ("use cupsCopyDestInfo").
// SPEC §10 still requires the PPD file for AirPrint detection and vendor
// colour-bypass keys, so we call the C symbol through this wrapper.
static inline const char *TPCupsGetPPD(const char *name) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
return cupsGetPPD(name);
#pragma clang diagnostic pop
}
+1 -1
View File
@@ -28,7 +28,7 @@ This directory is the **native AppKit implementation** of [`SPEC.md`](SPEC.md).
| Item | Value | | Item | Value |
|------|--------| |------|--------|
| macOS | 10.15 Catalina → 26+ Tahoe | | macOS | Intel **10.15** Catalina · Apple Silicon **11.0** Big Sur → 26+ Tahoe |
| Architecture | Universal 2 (Intel + Apple Silicon) | | Architecture | Universal 2 (Intel + Apple Silicon) |
| Xcode | Command Line Tools / full Xcode (Swift 5) | | Xcode | Command Line Tools / full Xcode (Swift 5) |
| Sandbox | Hardened Runtime **on**, App Sandbox **off** | | Sandbox | Hardened Runtime **on**, App Sandbox **off** |
+9 -3
View File
@@ -31,7 +31,11 @@ if xcodebuild_works; then
SCHEME="TargetPrint" SCHEME="TargetPrint"
OUT_DIR="$ROOT/build/apps/$ARCH" OUT_DIR="$ROOT/build/apps/$ARCH"
DD_DIR="$ROOT/build/derived-$ARCH" DD_DIR="$ROOT/build/derived-$ARCH"
echo "==> Building TargetPrint ($CONFIGURATION, $ARCH) with $XCODEBUILD" # shellcheck source=lib.sh
source "$SCRIPTS/lib.sh"
JOBS="$(cpu_jobs)"
MIN_OS="$(min_os_for_arch "$ARCH")"
echo "==> Building TargetPrint ($CONFIGURATION, $ARCH, min $MIN_OS) with $XCODEBUILD (-jobs $JOBS)"
rm -rf "$OUT_DIR" rm -rf "$OUT_DIR"
mkdir -p "$OUT_DIR" "$DD_DIR" mkdir -p "$OUT_DIR" "$DD_DIR"
"$XCODEBUILD" \ "$XCODEBUILD" \
@@ -39,19 +43,21 @@ if xcodebuild_works; then
-scheme "$SCHEME" \ -scheme "$SCHEME" \
-configuration "$CONFIGURATION" \ -configuration "$CONFIGURATION" \
-arch "$ARCH" \ -arch "$ARCH" \
-jobs "$JOBS" \
-parallelizeTargets \
-derivedDataPath "$DD_DIR" \ -derivedDataPath "$DD_DIR" \
CONFIGURATION_BUILD_DIR="$OUT_DIR" \ CONFIGURATION_BUILD_DIR="$OUT_DIR" \
ONLY_ACTIVE_ARCH=NO \ ONLY_ACTIVE_ARCH=NO \
MACOSX_DEPLOYMENT_TARGET="$MIN_OS" \
CODE_SIGN_IDENTITY="${MACOS_CODESIGN_IDENTITY:--}" \ CODE_SIGN_IDENTITY="${MACOS_CODESIGN_IDENTITY:--}" \
CODE_SIGNING_ALLOWED=YES \ CODE_SIGNING_ALLOWED=YES \
ENABLE_HARDENED_RUNTIME=YES \ ENABLE_HARDENED_RUNTIME=YES \
SWIFT_USE_PARALLEL_WHOLE_MODULE_OPTIMIZATION=YES \
build build
APP="$OUT_DIR/TargetPrint.app" APP="$OUT_DIR/TargetPrint.app"
test -d "$APP" test -d "$APP"
BIN="$APP/Contents/MacOS/TargetPrint" BIN="$APP/Contents/MacOS/TargetPrint"
test -x "$BIN" test -x "$BIN"
# shellcheck source=lib.sh
source "$SCRIPTS/lib.sh"
sign_app "$APP" "$ROOT/TargetPrint.entitlements" sign_app "$APP" "$ROOT/TargetPrint.entitlements"
echo "==> lipo -info" echo "==> lipo -info"
lipo -info "$BIN" lipo -info "$BIN"
+15 -2
View File
@@ -1,13 +1,26 @@
#!/bin/bash #!/bin/bash
# SPEC §12 — build x86_64, arm64, and Universal 2 TargetPrint.app # SPEC §12 — build x86_64, arm64, and Universal 2 TargetPrint.app
# x86_64 and arm64 compile concurrently; then lipo.
set -euo pipefail set -euo pipefail
CONFIGURATION="${1:-Release}" CONFIGURATION="${1:-Release}"
ROOT="$(cd "$(dirname "$0")/.." && pwd)" ROOT="$(cd "$(dirname "$0")/.." && pwd)"
SCRIPTS="$(dirname "$0")" SCRIPTS="$(dirname "$0")"
"$SCRIPTS/build_macos.sh" x86_64 "$CONFIGURATION" echo "==> Compiling x86_64 and arm64 in parallel"
"$SCRIPTS/build_macos.sh" arm64 "$CONFIGURATION" "$SCRIPTS/build_macos.sh" x86_64 "$CONFIGURATION" &
pid_x86=$!
"$SCRIPTS/build_macos.sh" arm64 "$CONFIGURATION" &
pid_arm=$!
status=0
wait "$pid_x86" || status=1
wait "$pid_arm" || status=1
if [ "$status" -ne 0 ]; then
echo "error: one or both architecture builds failed" >&2
exit 1
fi
"$SCRIPTS/make_universal.sh" "$SCRIPTS/make_universal.sh"
echo "==> All architectures:" echo "==> All architectures:"
+17
View File
@@ -31,6 +31,23 @@ sign_app() {
codesign --verify --verbose=2 "$app" || true codesign --verify --verbose=2 "$app" || true
} }
cpu_jobs() {
if [ -n "${JOBS:-}" ]; then
echo "$JOBS"
return
fi
sysctl -n hw.ncpu 2>/dev/null || nproc 2>/dev/null || echo 4
}
# Intel: Catalina 10.15. Apple Silicon did not exist until Big Sur 11.0.
min_os_for_arch() {
case "$1" in
x86_64) echo "${MACOSX_DEPLOYMENT_TARGET_X86_64:-10.15}" ;;
arm64) echo "${MACOSX_DEPLOYMENT_TARGET_ARM64:-11.0}" ;;
*) echo "10.15" ;;
esac
}
zip_app() { zip_app() {
local app="$1" local app="$1"
local dest="$2" local dest="$2"
+14 -10
View File
@@ -20,13 +20,17 @@ BIN="$MACOS_DIR/TargetPrint"
SDKROOT="${SDKROOT:-$(xcrun --sdk macosx --show-sdk-path)}" SDKROOT="${SDKROOT:-$(xcrun --sdk macosx --show-sdk-path)}"
SWIFT="${SWIFT:-$(xcrun --find swiftc)}" SWIFT="${SWIFT:-$(xcrun --find swiftc)}"
TARGET="${ARCH}-apple-macos10.15"
MIN_OS="10.15"
echo "==> swiftc build ($CONFIGURATION, $ARCH)" # shellcheck source=lib.sh
source "$(dirname "$0")/lib.sh"
JOBS="$(cpu_jobs)"
MIN_OS="$(min_os_for_arch "$ARCH")"
TARGET="${ARCH}-apple-macos${MIN_OS}"
echo "==> swiftc build ($CONFIGURATION, $ARCH, $JOBS threads)"
echo " SDKROOT=$SDKROOT" echo " SDKROOT=$SDKROOT"
echo " SWIFT=$SWIFT" echo " SWIFT=$SWIFT"
echo " TARGET=$TARGET" echo " TARGET=$TARGET (min $MIN_OS)"
rm -rf "$APP" rm -rf "$APP"
mkdir -p "$MACOS_DIR" "$RES_DIR" mkdir -p "$MACOS_DIR" "$RES_DIR"
@@ -40,7 +44,7 @@ if [ "${#SOURCES[@]}" -eq 0 ]; then
exit 1 exit 1
fi fi
OPT_FLAGS=(-O) OPT_FLAGS=(-O -whole-module-optimization)
if [ "$CONFIGURATION" != "Release" ]; then if [ "$CONFIGURATION" != "Release" ]; then
OPT_FLAGS=(-Onone -g) OPT_FLAGS=(-Onone -g)
fi fi
@@ -50,7 +54,8 @@ fi
-target "$TARGET" \ -target "$TARGET" \
-swift-version 5 \ -swift-version 5 \
"${OPT_FLAGS[@]}" \ "${OPT_FLAGS[@]}" \
-whole-module-optimization \ -num-threads "$JOBS" \
-j "$JOBS" \
-module-name TargetPrint \ -module-name TargetPrint \
-import-objc-header "$ROOT/Bridging-Header.h" \ -import-objc-header "$ROOT/Bridging-Header.h" \
-Xcc "-I${SDKROOT}/usr/include" \ -Xcc "-I${SDKROOT}/usr/include" \
@@ -83,9 +88,10 @@ if [ -f "$ICON_SRC" ] && command -v sips >/dev/null 2>&1; then
for pair in 16:icon_16x16 32:icon_32x32 128:icon_128x128 256:icon_256x256 512:icon_512x512; do for pair in 16:icon_16x16 32:icon_32x32 128:icon_128x128 256:icon_256x256 512:icon_512x512; do
size="${pair%%:*}" size="${pair%%:*}"
name="${pair##*:}" name="${pair##*:}"
sips -z "$size" "$size" "$ICON_SRC" --out "$ICONSET/AppIcon.iconset/${name}.png" >/dev/null sips -z "$size" "$size" "$ICON_SRC" --out "$ICONSET/AppIcon.iconset/${name}.png" >/dev/null &
sips -z $((size * 2)) $((size * 2)) "$ICON_SRC" --out "$ICONSET/AppIcon.iconset/${name}@2x.png" >/dev/null sips -z $((size * 2)) $((size * 2)) "$ICON_SRC" --out "$ICONSET/AppIcon.iconset/${name}@2x.png" >/dev/null &
done done
wait
if command -v iconutil >/dev/null 2>&1 && iconutil -c icns "$ICONSET/AppIcon.iconset" -o "$RES_DIR/AppIcon.icns" 2>/dev/null; then if command -v iconutil >/dev/null 2>&1 && iconutil -c icns "$ICONSET/AppIcon.iconset" -o "$RES_DIR/AppIcon.icns" 2>/dev/null; then
echo " AppIcon.icns" echo " AppIcon.icns"
else else
@@ -94,8 +100,6 @@ if [ -f "$ICON_SRC" ] && command -v sips >/dev/null 2>&1; then
rm -rf "$ICONSET" rm -rf "$ICONSET"
fi fi
# shellcheck source=lib.sh
source "$(dirname "$0")/lib.sh"
sign_app "$APP" "$ROOT/TargetPrint.entitlements" sign_app "$APP" "$ROOT/TargetPrint.entitlements"
echo "==> lipo -info" echo "==> lipo -info"
+1 -1
View File
@@ -19,7 +19,7 @@ enum AppError: Error, CustomStringConvertible {
switch self { switch self {
case .invalidJob: return .invalidJob case .invalidJob: return .invalidJob
case .unreadableTarget: return .unreadableTarget case .unreadableTarget: return .unreadableTarget
case .printer: return .printer case .printer: return .printerError
case .internalFatal: return .internalFatal case .internalFatal: return .internalFatal
} }
} }
@@ -1,4 +1,5 @@
import AppKit import AppKit
import UniformTypeIdentifiers
/// SPEC §9 three-pane window: thumbnails | canvas | inspector. /// SPEC §9 three-pane window: thumbnails | canvas | inspector.
@@ -211,7 +212,15 @@ final class PreviewWindowController: NSWindowController {
let panel = NSOpenPanel() let panel = NSOpenPanel()
panel.allowsMultipleSelection = true panel.allowsMultipleSelection = true
panel.canChooseDirectories = false panel.canChooseDirectories = false
if #available(macOS 12.0, *) {
var types: [UTType] = [.tiff, .json]
if let jobType = UTType(filenameExtension: "targetjob") {
types.append(jobType)
}
panel.allowedContentTypes = types
} else {
panel.allowedFileTypes = ["tif", "tiff", "targetjob", "json"] panel.allowedFileTypes = ["tif", "tiff", "targetjob", "json"]
}
panel.begin { result in panel.begin { result in
if result == .OK { completion(panel.urls) } if result == .OK { completion(panel.urls) }
} }
+3 -1
View File
@@ -77,9 +77,11 @@ enum CUPSManager {
// MARK: - PPD // MARK: - PPD
static func ppdPath(forQueue name: String) -> String? { static func ppdPath(forQueue name: String) -> String? {
guard let cPath = cupsGetPPD(name) else { return nil } name.withCString { cName in
guard let cPath = TPCupsGetPPD(cName) else { return nil }
return String(cString: cPath) return String(cString: cPath)
} }
}
static func ppdContents(forQueue name: String) -> String? { static func ppdContents(forQueue name: String) -> String? {
guard let path = ppdPath(forQueue: name) else { return nil } guard let path = ppdPath(forQueue: name) else { return nil }
+8 -3
View File
@@ -80,14 +80,19 @@ enum ColorMatching {
} }
static func stripColorMatchingAccessories(from panel: NSPrintPanel) { static func stripColorMatchingAccessories(from panel: NSPrintPanel) {
let accessories = panel.accessoryControllers() let accessories = panel.accessoryControllers
for ac in accessories { for ac in accessories {
let title = (ac.title ?? "") + " " + (ac.nibName ?? "") let cls = NSStringFromClass(type(of: ac))
let title = (ac.title ?? "") + " " + (ac.nibName ?? "") + " " + cls
let hay = title.lowercased() let hay = title.lowercased()
if hay.contains("color matching") || hay.contains("colour matching") || hay.contains("colormatch") { if hay.contains("color matching") || hay.contains("colour matching") || hay.contains("colormatch") {
panel.removeAccessoryController(ac) // SDK types this as NSViewController; removeAccessoryController
// requires NSPrintPanelAccessorizing (SPEC §7.2).
if let accessor = ac as? (NSViewController & NSPrintPanelAccessorizing) {
panel.removeAccessoryController(accessor)
TPLog.info("Removed print-panel accessory: \(title)") TPLog.info("Removed print-panel accessory: \(title)")
} }
} }
} }
}
} }
+1 -1
View File
@@ -73,7 +73,7 @@ final class PrintEngine {
ColorMatching.apply(colorMode, to: info) ColorMatching.apply(colorMode, to: info)
do { do {
if let queue = try CUPSManager.namedQueue(printerName) ?? try CUPSManager.listQueues().first(where: { $0.name == printerName }) { if let queue = try CUPSManager.namedQueue(printerName) {
let bypass = CUPSManager.vendorColorBypass(make: queue.make, model: queue.model, ppdText: queue.ppdText) let bypass = CUPSManager.vendorColorBypass(make: queue.make, model: queue.model, ppdText: queue.ppdText)
CUPSManager.applyVendorBypass(bypass, to: info) CUPSManager.applyVendorBypass(bypass, to: info)
} }