I think I have a solution for sharing code between watchOS and iOS. The first step is that a framework needs to be generated for each platform. To make the frameworks integrate into the larger application better I did the follow:
- Set PRODUCT_MODULE_NAME and PRODUCT_NAME to the target name of the iOS app. This will allow you to import your platform-specific framework using the same name.
- Included optional platform-specific source folders.
Example:
/* File structure
Project.swift
Tuist
ProjectDescriptionHelpers
Project+Templates.swift
Projects
MyFramework
Sources
Sources-watchOS
MyLogging
Sources
Sources-iOS
Sources-watchOS
*/
//Project.swift
var targets: [Target] = []
targets += Target.makeFrameworkTargets(name: "MyLogging", platforms: [.iOS, .watchOS])
targets += Target.makeFrameworkTargets(name: "MyFramework", platforms: [.iOS, .watchOS], dependencies:["MyLogging"])
// Tuist/ProjectDescriptionHelpers/Project+Templates.swift
extension Target {
// Project Root. Not sure the best way to do this in Tuist
static let rootDir: URL = URL(fileURLWithPath: #file)
.deletingLastPathComponent()
.deletingLastPathComponent()
.deletingLastPathComponent()
public static func makeFrameworkTargets(name: String,
platforms: [Platform],
dependencies: [String] = []) -> [Target] {
var projectTargets: [Target] = []
for platform in platforms {
let targetDependencies: [TargetDependency] = dependencies.map {
let title = platform == .iOS ? $0 : "\($0)-\(platform)"
return .target(name: title)
}
let title = platform == .iOS ? name : "\(name)-\(platform)"
var settingsDict: SettingsDictionary = [:]
settingsDict["PRODUCT_MODULE_NAME"] = .string(name)
settingsDict["PRODUCT_NAME"] = .string(name)
var sources = ["Projects/\(name)/Sources/**/*.swift"]
let platformSource = rootDir.appendingPathComponent("/Projects/\(name)/Sources-\(platform)")
if FileManager.default.fileExists(atPath: platformSource.path) {
sources.append("Projects/\(name)/Sources-\(platform)/**/*.swift")
}
let settings = Settings.settings(base: settingsDict, configurations: [])
projectTargets.append(Target(name: title,
platform: platform,
product: .framework,
bundleId: "io.tuist.\(title)",
infoPlist: .default,
sources: SourceFilesList(globs: sources),
dependencies: targetDependencies,
settings: settings))
}
return projectTargets
}
}