diff --git a/Sources/BuildScripts/XCFrameworkBuild/base.swift b/Sources/BuildScripts/XCFrameworkBuild/base.swift index 1f48bb0..f102954 100644 --- a/Sources/BuildScripts/XCFrameworkBuild/base.swift +++ b/Sources/BuildScripts/XCFrameworkBuild/base.swift @@ -34,6 +34,8 @@ class ArgumentOptions { var enableDebug: Bool = false var enableSplitPlatform: Bool = false var enableGPL: Bool = false + var enableDynamic: Bool = false + var enableArm64Only: Bool = false var platforms : [PlatformType] = [] var releaseVersion: String = "0.0.0" @@ -57,6 +59,10 @@ class ArgumentOptions { options.enableDebug = true case "enable-gpl": options.enableGPL = true + case "enable-dynamic": + options.enableDynamic = true + case "enable-arm64-only": + options.enableArm64Only = true case "enable-split-platform": options.enableSplitPlatform = true default: @@ -155,6 +161,9 @@ class BaseBuild { } func architectures(_ platform: PlatformType) -> [ArchType] { + if BaseBuild.options.enableArm64Only && platform != .macos { + return platform.architectures.filter { $0 == .arm64 } + } - platform.architectures + return platform.architectures } @@ -179,7 +188,7 @@ class BaseBuild { let meson = Utility.shell("which meson", isOutput: true)! try Utility.launch(path: meson, arguments: ["setup", buildURL.path, "--cross-file=\(crossFile.path)"] + arguments(platform: platform, arch: arch), currentDirectoryURL: directoryURL, environment: environ) try Utility.launch(path: meson, arguments: ["compile", "--clean"], currentDirectoryURL: buildURL, environment: environ) - try Utility.launch(path: meson, arguments: ["compile", "--verbose"], currentDirectoryURL: buildURL, environment: environ) + try Utility.launch(path: meson, arguments: ["compile", "--verbose", "-j", "1"], currentDirectoryURL: buildURL, environment: environ) try Utility.launch(path: meson, arguments: ["install"], currentDirectoryURL: buildURL, environment: environ) } else if FileManager.default.fileExists(atPath: (directoryURL + wafPath()).path) { let waf = (directoryURL + wafPath()).path @@ -188,8 +197,8 @@ class BaseBuild { try Utility.launch(path: waf, arguments: ["install"] + wafInstallArg(), currentDirectoryURL: directoryURL, environment: environ) } else { try configure(buildURL: buildURL, environ: environ, platform: platform, arch: arch) - try Utility.launch(path: "/usr/bin/make", arguments: ["-j8"], currentDirectoryURL: buildURL, environment: environ) - try Utility.launch(path: "/usr/bin/make", arguments: ["-j8", "install"], currentDirectoryURL: buildURL, environment: environ) + try Utility.launch(path: "/usr/bin/make", arguments: ["-j1"], currentDirectoryURL: buildURL, environment: environ) + try Utility.launch(path: "/usr/bin/make", arguments: ["-j1", "install"], currentDirectoryURL: buildURL, environment: environ) } } @@ -409,6 +418,33 @@ class BaseBuild { arguments.append("-output") arguments.append((frameworkDir + framework).path) try Utility.launch(path: "/usr/bin/lipo", arguments: arguments) + if BaseBuild.options.enableDynamic { + let binaryPath = (frameworkDir + framework).path + let installName = "@rpath/\(framework).framework/\(framework)" + try Utility.launch(path: "/usr/bin/install_name_tool", arguments: ["-id", installName, binaryPath]) + if let linkedLibraries = Utility.shell("/usr/bin/otool -L \(binaryPath)", isOutput: true) { + for line in linkedLibraries.components(separatedBy: .newlines).dropFirst() { + guard let dependency = line.trimmingCharacters(in: .whitespaces).split(separator: " ").first else { + continue + } + let path = String(dependency) + let name = URL(fileURLWithPath: path).lastPathComponent + let matches = name.range( + of: #"^lib(avcodec|avdevice|avfilter|avformat|avutil|swresample|swscale)(\.[0-9]+)*\.dylib$"#, + options: .regularExpression + ) + guard matches != nil else { + continue + } + let stem = name.dropFirst(3).split(separator: ".").first.map(String.init) ?? "" + guard !stem.isEmpty else { + continue + } + let target = "@rpath/Lib\(stem).framework/Lib\(stem)" + try Utility.launch(path: "/usr/bin/install_name_tool", arguments: ["-change", path, target, binaryPath]) + } + } + } try FileManager.default.createDirectory(at: frameworkDir + "Modules", withIntermediateDirectories: true, attributes: nil) var modulemap = """ framework module \(framework) [system] { @@ -429,7 +465,8 @@ class BaseBuild { // Setting the minimum version to 100.0 is required for uploading a static framework to the App Store after Xcode 15.4 // Fix: ITMS-90208: "Invalid Bundle. The bundle xxx.framework does not support the minimum OS Version specified in the Info.plist." // It was originally using `platform.minVersion` - createPlist(path: frameworkDir.path + "/Info.plist", name: framework, minVersion: "100.0", platform: platform.sdk) + let minVersion = BaseBuild.options.enableDynamic ? platform.minVersion : "100.0" + createPlist(path: frameworkDir.path + "/Info.plist", name: framework, minVersion: minVersion, platform: platform.sdk) try fixShallowBundles(framework: framework, platform: platform, frameworkDir: frameworkDir) return frameworkDir.path } @@ -583,7 +620,7 @@ class BaseBuild { endian = 'little' [built-in options] - default_library = 'static' + default_library = '\(BaseBuild.options.enableDynamic ? "shared" : "static")' buildtype = 'release' prefix = '\(prefix.path)' c_args = [\(cFlags)] @@ -614,11 +651,13 @@ class BaseBuild { if !FileManager.default.fileExists(atPath: thinLibPath.path) { continue } - let staticLibraries = try FileManager.default.contentsOfDirectory(atPath: thinLibPath.path).filter { $0.hasSuffix(".a") } + let libraries = try FileManager.default.contentsOfDirectory(atPath: thinLibPath.path).filter { + $0.hasSuffix(".a") || $0.hasSuffix(".dylib") + } let releaseThinLibPath = releaseDirPath + [library.rawValue, "lib", platform.rawValue, "thin", arch.rawValue, "lib"] try? FileManager.default.createDirectory(at: releaseThinLibPath, withIntermediateDirectories: true, attributes: nil) - for lib in staticLibraries { + for lib in libraries { let sourceURL = thinLibPath + [lib] let destinationURL = releaseThinLibPath + [lib] try FileManager.default.copyItem(at: sourceURL, to: destinationURL) @@ -1445,4 +1484,3 @@ extension URL { return url } } - diff --git a/Sources/BuildScripts/XCFrameworkBuild/main.swift b/Sources/BuildScripts/XCFrameworkBuild/main.swift index 64ce009..bb4620d 100644 --- a/Sources/BuildScripts/XCFrameworkBuild/main.swift +++ b/Sources/BuildScripts/XCFrameworkBuild/main.swift @@ -18,7 +18,9 @@ do { try BuildASS().buildALL() // libsmbclient - try BuildSmbclient().buildALL() + if BaseBuild.options.enableGPL { + try BuildSmbclient().buildALL() + } // libbluray try BuildBluray().buildALL() @@ -419,7 +421,7 @@ private class BuildMPV: BaseBuild { array.append("-Dgl-cocoa=enabled") array.append("-Dvideotoolbox-gl=enabled") array.append("-Dvideotoolbox-pl=enabled") - array.append("-Dlua=luajit") // macos show video stats need enable + array.append(BaseBuild.options.enableDynamic ? "-Dlua=disabled" : "-Dlua=luajit") // macos show video stats need enable } else { array.append("-Dvideotoolbox-gl=disabled") array.append("-Dvideotoolbox-pl=enabled") @@ -564,6 +566,17 @@ private class BuildFFMPEG: BaseBuild { override func arguments(platform: PlatformType, arch: ArchType) -> [String] { var arguments = ffmpegConfiguers + if BaseBuild.options.enableDynamic { + let staticOnly = Set([ + "--disable-shared", + "--enable-static", + "--enable-nonfree", + ]) + arguments.removeAll { staticOnly.contains($0) } + arguments.append("--enable-shared") + arguments.append("--disable-static") + arguments.append("--disable-nonfree") + } if BaseBuild.options.enableDebug { arguments.append("--enable-debug") arguments.append("--disable-stripping") diff --git a/Sources/BuildScripts/XCFrameworkBuild/base.swift b/Sources/BuildScripts/XCFrameworkBuild/base.swift index 1f48bb0..0a27d44 100644 --- a/Sources/BuildScripts/XCFrameworkBuild/base.swift +++ b/Sources/BuildScripts/XCFrameworkBuild/base.swift @@ -389,7 +389,7 @@ class BaseBuild { try? FileManager.default.removeItem(at: frameworkDir) try FileManager.default.createDirectory(at: frameworkDir, withIntermediateDirectories: true, attributes: nil) var arguments = ["-create"] - for arch in platform.architectures { + for arch in architectures(platform) { let prefix = thinDir(platform: platform, arch: arch) if !FileManager.default.fileExists(atPath: prefix.path) { return nil diff --git a/Sources/BuildScripts/XCFrameworkBuild/main.swift b/Sources/BuildScripts/XCFrameworkBuild/main.swift index 64ce009..dddb4bd 100644 --- a/Sources/BuildScripts/XCFrameworkBuild/main.swift +++ b/Sources/BuildScripts/XCFrameworkBuild/main.swift @@ -513,13 +513,20 @@ private class BuildFFMPEG: BaseBuild { override func frameworks() throws -> [String] { var frameworks: [String] = [] if let platform = platforms().first { - if let arch = platform.architectures.first { + if let arch = architectures(platform).first { let lib = thinDir(platform: platform, arch: arch) + "lib" let fileNames = try FileManager.default.contentsOfDirectory(atPath: lib.path) for fileName in fileNames { if fileName.hasPrefix("lib"), fileName.hasSuffix(".a") { // 因为其他库也可能引入libavformat,所以把lib改成大写,这样就可以排在前面,覆盖别的库。 frameworks.append("Lib" + fileName.dropFirst(3).dropLast(2)) + } else if BaseBuild.options.enableDynamic, + fileName.hasPrefix("lib"), + fileName.hasSuffix(".dylib") { + let stem = fileName.dropFirst(3).dropLast(6) + if !stem.contains(".") { + frameworks.append("Lib" + stem) + } } } } diff --git a/Sources/BuildScripts/XCFrameworkBuild/base.swift b/Sources/BuildScripts/XCFrameworkBuild/base.swift index 1f48bb0..b6b612b 100644 --- a/Sources/BuildScripts/XCFrameworkBuild/base.swift +++ b/Sources/BuildScripts/XCFrameworkBuild/base.swift @@ -987,7 +987,7 @@ enum PlatformType: String, CaseIterable { case .tvos, .tvsimulator: return "14.0" case .macos: - return "11.0" + return BaseBuild.options.enableDynamic ? "14.0" : "11.0" case .maccatalyst: // return "14.0" return ""