309 lines
11 KiB
Swift
309 lines
11 KiB
Swift
// swift-tools-version: 6.1
|
|
|
|
let lumaFridaDevkitLinkerSettings: [LinkerSetting] = {
|
|
guard let devkit = ProcessInfo.processInfo.environment["LUMA_FRIDA_DEVKIT"], !devkit.isEmpty else { return [] }
|
|
var flags = ["-L\(devkit)/lib", "-lfrida-core", "-lc++", "-lresolv", "-liconv", "-lbsm", "-lm"]
|
|
for framework in ["Foundation", "CoreFoundation", "AppKit", "CoreServices", "IOKit", "Security", "Network", "SystemConfiguration"] {
|
|
flags += ["-framework", framework]
|
|
}
|
|
return [.unsafeFlags(flags)]
|
|
}()
|
|
|
|
|
|
import Foundation
|
|
import PackageDescription
|
|
|
|
#if canImport(Darwin)
|
|
let manifestArgs = CommandLine.arguments
|
|
let manifestFileno = manifestArgs.firstIndex(of: "-fileno").flatMap { index -> String? in
|
|
let valueIndex = manifestArgs.index(after: index)
|
|
guard valueIndex < manifestArgs.endIndex else { return nil }
|
|
return manifestArgs[valueIndex]
|
|
}
|
|
let usesXcodePackageResolution = manifestFileno != nil && manifestFileno != "4"
|
|
#else
|
|
let usesXcodePackageResolution = false
|
|
#endif
|
|
let lumaCoreExcludes = ["VirtualMachines/AndroidEmulator/EmulatorControl/proto"] + (usesXcodePackageResolution ? [] : ["Generated"])
|
|
let lumaCorePlugins: [Target.PluginUsage] = usesXcodePackageResolution ? [] : [
|
|
.plugin(name: "LumaBundlePlugin"),
|
|
.plugin(name: "LumaShaderPlugin"),
|
|
]
|
|
let lumaBundlePluginTargets: [Target] = usesXcodePackageResolution ? [] : [
|
|
.plugin(
|
|
name: "LumaBundlePlugin",
|
|
capability: .buildTool(),
|
|
dependencies: [
|
|
.target(name: "LumaBundleCompiler"),
|
|
],
|
|
path: "Plugins/LumaBundlePlugin"
|
|
),
|
|
.plugin(
|
|
name: "LumaShaderPlugin",
|
|
capability: .buildTool(),
|
|
dependencies: [
|
|
.target(name: "LumaShaderCompiler"),
|
|
],
|
|
path: "Plugins/LumaShaderPlugin"
|
|
),
|
|
]
|
|
|
|
#if canImport(Darwin)
|
|
// Apple's mobile SDKs reach the audio session through AVFoundation, so the
|
|
// device unit has to be Objective-C there. Desktop follows suit rather than
|
|
// carry two behaviours.
|
|
let cLumaAudioSources = ["luma_audio_device.m"]
|
|
let cLumaAudioLinkerSettings: [LinkerSetting] = [
|
|
.linkedFramework("CoreAudio"),
|
|
.linkedFramework("AudioToolbox"),
|
|
.linkedFramework("CoreFoundation"),
|
|
]
|
|
#elseif os(Windows)
|
|
let cLumaAudioSources = ["luma_audio_device.c"]
|
|
let cLumaAudioLinkerSettings: [LinkerSetting] = []
|
|
#else
|
|
let cLumaAudioSources = ["luma_audio_device.c"]
|
|
// miniaudio dlopens ALSA and PulseAudio, so neither is a link-time dependency.
|
|
let cLumaAudioLinkerSettings: [LinkerSetting] = [
|
|
.linkedLibrary("pthread"),
|
|
.linkedLibrary("m"),
|
|
.linkedLibrary("dl"),
|
|
]
|
|
#endif
|
|
|
|
#if !canImport(Darwin)
|
|
let cSoupTargets: [Target] = [
|
|
.systemLibrary(
|
|
name: "CSoup",
|
|
path: "Sources/CSoup",
|
|
pkgConfig: "libsoup-3.0",
|
|
providers: [
|
|
.apt(["libsoup-3.0-dev"]),
|
|
.yum(["libsoup3-devel"]),
|
|
]
|
|
)
|
|
]
|
|
let lumaCoreSoupDeps: [Target.Dependency] = ["CSoup"]
|
|
|
|
let cCompressionTargets: [Target] = [
|
|
.systemLibrary(
|
|
name: "CLzma",
|
|
path: "Sources/CLzma",
|
|
pkgConfig: "liblzma",
|
|
providers: [
|
|
.apt(["liblzma-dev"]),
|
|
.yum(["xz-devel"]),
|
|
]
|
|
),
|
|
.systemLibrary(
|
|
name: "CZlib",
|
|
path: "Sources/CZlib",
|
|
pkgConfig: "zlib",
|
|
providers: [
|
|
.apt(["zlib1g-dev"]),
|
|
.yum(["zlib-devel"]),
|
|
]
|
|
),
|
|
]
|
|
let lumaCoreCompressionDeps: [Target.Dependency] = ["CLzma", "CZlib"]
|
|
#else
|
|
let cSoupTargets: [Target] = []
|
|
let lumaCoreSoupDeps: [Target.Dependency] = []
|
|
let cCompressionTargets: [Target] = []
|
|
let lumaCoreCompressionDeps: [Target.Dependency] = []
|
|
#endif
|
|
|
|
// Runtime GLSL->MSL translation, so a shader written in a snippet reaches a
|
|
// Metal host with no build step, and the same libraries do it at build time.
|
|
// Only Apple platforms have one to reach: elsewhere OpenGL takes the GLSL as
|
|
// it stands, and neither the target nor the toolchain it needs is built.
|
|
//
|
|
// Neither project builds under SwiftPM, so CI makes them into an xcframework
|
|
// (see scripts/make-shader-toolchain-xcframework.sh) and this names it.
|
|
//
|
|
// A locally made one short-circuits the published artifact, the way
|
|
// SwiftyPharo honours PHARO_VM_ROOT: run that script and set
|
|
// SHADER_TOOLCHAIN_ROOT=artifacts/ShaderToolchain.xcframework, which SwiftPM
|
|
// wants relative to the package. Asking the filesystem rather than being told
|
|
// would not do -- a manifest is cached, so whichever answer it gave first
|
|
// would stick.
|
|
let shaderToolchainVersion = "2"
|
|
let shaderToolchainRoot = ProcessInfo.processInfo.environment["SHADER_TOOLCHAIN_ROOT"]
|
|
|
|
#if canImport(Darwin)
|
|
let shaderToolchainTarget: Target = shaderToolchainRoot.map {
|
|
.binaryTarget(name: "ShaderToolchain", path: $0)
|
|
} ?? .binaryTarget(
|
|
name: "ShaderToolchain",
|
|
url: "https://github.com/frida/luma/releases/download/"
|
|
+ "shader-toolchain-\(shaderToolchainVersion)/ShaderToolchain.xcframework.zip",
|
|
checksum: "721feadac2243501ac04141ee6bd579955fce573f78c78d220c970eac0b97211"
|
|
)
|
|
let shaderTranslateTargets: [Target] = [
|
|
shaderToolchainTarget,
|
|
.target(
|
|
name: "CShaderTranslate",
|
|
dependencies: ["ShaderToolchain"],
|
|
path: "Sources/CShaderTranslate",
|
|
publicHeadersPath: "include",
|
|
linkerSettings: [.unsafeFlags(["-lc++"])]
|
|
),
|
|
]
|
|
let shaderTranslateDeps: [Target.Dependency] = ["CShaderTranslate"]
|
|
#else
|
|
let shaderTranslateTargets: [Target] = []
|
|
let shaderTranslateDeps: [Target.Dependency] = []
|
|
#endif
|
|
|
|
|
|
// Typed up front: left inline, the whole array and its four concatenations
|
|
// are one expression, and the type-checker gives up on it.
|
|
let lumaTargets: [Target] = [
|
|
.target(
|
|
name: "LumaCore",
|
|
dependencies: [
|
|
.product(name: "Frida", package: "frida-swift"),
|
|
.product(name: "Crypto", package: "swift-crypto"),
|
|
.product(name: "GRDB", package: "GRDB.swift"),
|
|
.product(name: "SwiftyR2", package: "SwiftyR2"),
|
|
.product(name: "SwiftyPharo", package: "SwiftyPharo"),
|
|
.product(name: "NIOCore", package: "swift-nio"),
|
|
.product(name: "NIOPosix", package: "swift-nio"),
|
|
.product(name: "NIOHTTP2", package: "swift-nio-http2"),
|
|
.product(name: "NIOHPACK", package: "swift-nio-http2"),
|
|
.product(name: "SwiftProtobuf", package: "swift-protobuf"),
|
|
"CLumaAudio",
|
|
"CZstd",
|
|
] + lumaCoreSoupDeps + lumaCoreCompressionDeps + shaderTranslateDeps,
|
|
path: "Sources/LumaCore",
|
|
exclude: lumaCoreExcludes,
|
|
resources: [
|
|
.process("Resources/LumaPortal.pem"),
|
|
.copy("Resources/MachineIcons"),
|
|
// Staged by the build, and copied rather than processed so it
|
|
// keeps the directory the runtime looks in.
|
|
.copy("Resources/pharo-image"),
|
|
],
|
|
swiftSettings: [
|
|
.swiftLanguageMode(.v6),
|
|
],
|
|
plugins: lumaCorePlugins
|
|
),
|
|
.executableTarget(
|
|
name: "LumaBundleCompiler",
|
|
dependencies: [
|
|
.product(name: "Frida", package: "frida-swift"),
|
|
],
|
|
path: "Sources/LumaBundleCompiler",
|
|
swiftSettings: [
|
|
.swiftLanguageMode(.v5),
|
|
]
|
|
),
|
|
|
|
.target(
|
|
name: "CZstd",
|
|
path: "Sources/CZstd",
|
|
publicHeadersPath: "include"
|
|
),
|
|
|
|
.target(
|
|
name: "CLumaAudio",
|
|
path: "Sources/CLumaAudio",
|
|
sources: cLumaAudioSources,
|
|
publicHeadersPath: "include",
|
|
linkerSettings: cLumaAudioLinkerSettings
|
|
),
|
|
.executableTarget(
|
|
name: "LumaSynthCheck",
|
|
dependencies: ["LumaCore"],
|
|
path: "Sources/LumaSynthCheck",
|
|
swiftSettings: [.swiftLanguageMode(.v6)]
|
|
),
|
|
.executableTarget(
|
|
name: "LumaExampleCheck",
|
|
dependencies: ["LumaCore"],
|
|
path: "Sources/LumaExampleCheck",
|
|
swiftSettings: [
|
|
.swiftLanguageMode(.v6),
|
|
]
|
|
),
|
|
.executableTarget(
|
|
name: "LumaEditorCheck",
|
|
dependencies: ["LumaCore"],
|
|
path: "Sources/LumaEditorCheck",
|
|
swiftSettings: [
|
|
.swiftLanguageMode(.v6),
|
|
]
|
|
),
|
|
.executableTarget(
|
|
name: "LumaEmulatorCheck",
|
|
dependencies: [
|
|
"LumaCore",
|
|
.product(name: "Frida", package: "frida-swift"),
|
|
],
|
|
path: "Sources/LumaEmulatorCheck",
|
|
swiftSettings: [
|
|
.swiftLanguageMode(.v5),
|
|
],
|
|
linkerSettings: lumaFridaDevkitLinkerSettings
|
|
),
|
|
.executableTarget(
|
|
name: "LumaShaderCompiler",
|
|
dependencies: shaderTranslateDeps,
|
|
path: "Sources/LumaShaderCompiler",
|
|
swiftSettings: [
|
|
.swiftLanguageMode(.v5),
|
|
]
|
|
),
|
|
.executableTarget(
|
|
name: "LumaVMCheck",
|
|
dependencies: [
|
|
"LumaCore",
|
|
.product(name: "Frida", package: "frida-swift"),
|
|
],
|
|
path: "Sources/LumaVMCheck",
|
|
swiftSettings: [
|
|
.swiftLanguageMode(.v5),
|
|
]
|
|
),
|
|
]
|
|
|
|
// Frida comes from the published bindings and the artifact they name. Work on
|
|
// frida-core itself is picked up by pointing FRIDA_SWIFT_ROOT at a checkout of
|
|
// the bindings beside it, with USE_SYSTEM_FRIDA set so they link what
|
|
// pkg-config finds. Being told rather than asking the filesystem is what the
|
|
// toolchain artifact does above, and for the same reason.
|
|
let fridaSwift: Package.Dependency = ProcessInfo.processInfo.environment["FRIDA_SWIFT_ROOT"]
|
|
.map { Package.Dependency.package(path: $0) } ?? .package(
|
|
url: "https://github.com/frida/frida-swift",
|
|
branch: "main"
|
|
)
|
|
|
|
let package = Package(
|
|
name: "luma",
|
|
platforms: [
|
|
.macOS(.v15),
|
|
.iOS("26.0"),
|
|
.visionOS(.v2),
|
|
],
|
|
products: [
|
|
.library(name: "LumaCore", targets: ["LumaCore"]),
|
|
.executable(name: "LumaBundleCompiler", targets: ["LumaBundleCompiler"]),
|
|
.executable(name: "LumaShaderCompiler", targets: ["LumaShaderCompiler"]),
|
|
.executable(name: "LumaExampleCheck", targets: ["LumaExampleCheck"]),
|
|
.executable(name: "LumaEditorCheck", targets: ["LumaEditorCheck"]),
|
|
.executable(name: "LumaSynthCheck", targets: ["LumaSynthCheck"]),
|
|
],
|
|
dependencies: [
|
|
fridaSwift,
|
|
.package(url: "https://github.com/apple/swift-crypto", .upToNextMajor(from: "3.0.0")),
|
|
.package(url: "https://github.com/groue/GRDB.swift", .upToNextMajor(from: "7.0.0")),
|
|
.package(url: "https://github.com/radareorg/SwiftyR2", branch: "main"),
|
|
.package(url: "https://github.com/frida/SwiftyPharo", branch: "main"),
|
|
.package(url: "https://github.com/apple/swift-nio", .upToNextMajor(from: "2.76.0")),
|
|
.package(url: "https://github.com/apple/swift-nio-http2", .upToNextMajor(from: "1.35.0")),
|
|
.package(url: "https://github.com/apple/swift-protobuf", .upToNextMajor(from: "1.28.0")),
|
|
],
|
|
targets: cSoupTargets + cCompressionTargets + shaderTranslateTargets + lumaTargets + lumaBundlePluginTargets
|
|
)
|