0

I am migrating an existing project in Xcode to using Tuist. The application has a main app, Watch App, and a notification extension. There is loads of shared code between each project.

How can I use Tuist to share a framework between the iOS and watchOS code?

datinc
  • 3,404
  • 3
  • 24
  • 33

1 Answers1

0

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
    }
}

datinc
  • 3,404
  • 3
  • 24
  • 33