From 9529e37a24c2b67d01430ed4fbd4c7247b0f80f8 Mon Sep 17 00:00:00 2001 From: Ciprian Date: Sat, 18 Jul 2026 13:19:37 +0400 Subject: [PATCH 1/2] fix(tts): make LuxTTS resources signable on iOS --- Package.swift | 2 +- Sources/FluidAudio/TTS/LuxTts/G2p/LuxTtsG2p.swift | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Package.swift b/Package.swift index d3da1272..bc69a25c 100644 --- a/Package.swift +++ b/Package.swift @@ -29,7 +29,7 @@ let package = Package( ], path: "Sources/FluidAudio", resources: [ - .copy("TTS/LuxTts/G2p/Resources") + .process("TTS/LuxTts/G2p/Resources") ] ), // Byte-exact NeMo text normalization (FST engine, all 7 languages). diff --git a/Sources/FluidAudio/TTS/LuxTts/G2p/LuxTtsG2p.swift b/Sources/FluidAudio/TTS/LuxTts/G2p/LuxTtsG2p.swift index 8d664e98..19e46c37 100644 --- a/Sources/FluidAudio/TTS/LuxTts/G2p/LuxTtsG2p.swift +++ b/Sources/FluidAudio/TTS/LuxTts/G2p/LuxTtsG2p.swift @@ -77,11 +77,9 @@ public struct LuxTtsG2p: Sendable { public init() throws { guard let lexiconURL = Bundle.module.url( - forResource: "luxtts_en_us_lexicon.tsv", withExtension: "zz", - subdirectory: "Resources"), + forResource: "luxtts_en_us_lexicon.tsv", withExtension: "zz"), let auxURL = Bundle.module.url( - forResource: "luxtts_en_us_g2p_aux", withExtension: "json", - subdirectory: "Resources") + forResource: "luxtts_en_us_g2p_aux", withExtension: "json") else { throw LuxTtsError.tokenizerFailed("bundled G2P resources missing") } From 4ddcfbc76a00e1af139add19c181b61e13808bfc Mon Sep 17 00:00:00 2001 From: Ciprian Date: Mon, 20 Jul 2026 04:54:15 +0400 Subject: [PATCH 2/2] fix(tts): make LuxTTS test resources signable on iOS --- Package.swift | 3 ++- .../TTS/LuxTts/LuxTtsFixtures.swift | 5 +---- .../TTS/LuxTts/LuxTtsG2pTests.swift | 15 +++++++++++++++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Package.swift b/Package.swift index bc69a25c..acf6c677 100644 --- a/Package.swift +++ b/Package.swift @@ -29,6 +29,7 @@ let package = Package( ], path: "Sources/FluidAudio", resources: [ + // Keep .process: .copy of a Resources-named directory breaks Apple code signing on iOS. .process("TTS/LuxTts/G2p/Resources") ] ), @@ -66,7 +67,7 @@ let package = Package( "FluidAudioCLI", ], resources: [ - .copy("TTS/LuxTts/Resources") + .process("TTS/LuxTts/Resources") ] ), ], diff --git a/Tests/FluidAudioTests/TTS/LuxTts/LuxTtsFixtures.swift b/Tests/FluidAudioTests/TTS/LuxTts/LuxTtsFixtures.swift index bcc0a96c..019c808f 100644 --- a/Tests/FluidAudioTests/TTS/LuxTts/LuxTtsFixtures.swift +++ b/Tests/FluidAudioTests/TTS/LuxTts/LuxTtsFixtures.swift @@ -120,10 +120,7 @@ struct LuxTtsFixtures: Decodable { // MARK: - Loading static func resourceURL(_ name: String) throws -> URL { - guard - let url = Bundle.module.url( - forResource: name, withExtension: nil, subdirectory: "Resources") - else { + guard let url = Bundle.module.url(forResource: name, withExtension: nil) else { throw XCTSkip("LuxTts fixture resource missing: \(name)") } return url diff --git a/Tests/FluidAudioTests/TTS/LuxTts/LuxTtsG2pTests.swift b/Tests/FluidAudioTests/TTS/LuxTts/LuxTtsG2pTests.swift index a942e7b6..a4f0782a 100644 --- a/Tests/FluidAudioTests/TTS/LuxTts/LuxTtsG2pTests.swift +++ b/Tests/FluidAudioTests/TTS/LuxTts/LuxTtsG2pTests.swift @@ -12,6 +12,21 @@ import XCTest /// the mobius worktree; these tests pin representative behaviors. final class LuxTtsG2pTests: XCTestCase { + func testFixtureResourcesAreProcessedAtBundleRoot() { + XCTAssertFalse( + FileManager.default.fileExists( + atPath: Bundle.module.bundleURL + .appendingPathComponent("Resources", isDirectory: true).path + ), + "LuxTTS test resources must not create a reserved top-level Resources directory" + ) + XCTAssertTrue( + FileManager.default.fileExists( + atPath: Bundle.module.bundleURL.appendingPathComponent("luxtts_fixtures.json").path + ) + ) + } + private static let g2p: LuxTtsG2p = { do { return try LuxTtsG2p()