//===--- SchemeGenerator.swift --------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2024 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// import Xcodeproj struct Scheme { var name: String var buildAction: BuildAction var runAction: RunAction? var replaceExisting: Bool init(_ name: String, replaceExisting: Bool, buildTargets: [BuildTarget]) { self.name = name self.replaceExisting = replaceExisting self.buildAction = .init(targets: buildTargets) } init(_ name: String, replaceExisting: Bool, buildTargets: BuildTarget...) { self.init( name, replaceExisting: replaceExisting, buildTargets: buildTargets ) } mutating func addBuildTarget( _ target: Xcode.Target, in path: RelativePath ) { buildAction.targets.append(.init(target, in: path)) } } extension Scheme { struct BuildAction { var targets: [BuildTarget] } struct BuildTarget { var name: String var container: RelativePath init(_ target: Xcode.Target, in path: RelativePath) { self.name = target.name self.container = path } init(_ name: String, in path: RelativePath) { self.name = name self.container = path } } struct RunAction { var path: AbsolutePath } } struct SchemeGenerator { let containerDir: AbsolutePath let disableAutoCreation: Bool var schemes: [Scheme] = [] init(in containerDir: AbsolutePath, disableAutoCreation: Bool = true) { self.containerDir = containerDir self.disableAutoCreation = disableAutoCreation } } extension SchemeGenerator { mutating func add(_ scheme: Scheme) { schemes.append(scheme) } } extension SchemeGenerator { private func disableAutoCreationIfNeeded() throws { guard disableAutoCreation else { return } var relPath: RelativePath = "xcshareddata/WorkspaceSettings.xcsettings" if containerDir.hasExtension(.xcodeproj) { relPath = "project.xcworkspace/\(relPath)" } let settingsPath = containerDir.appending(relPath) let workspaceSettings = """ IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded """ try settingsPath.write(workspaceSettings) log.info("Generated '\(settingsPath)'") } private func writeScheme(_ scheme: Scheme) throws { let path = containerDir.appending( "xcshareddata/xcschemes/\(scheme.name).xcscheme" ) // Don't overwrite if we haven't been asked to. if !scheme.replaceExisting && path.exists { return } var plist = """ """ for buildTarget in scheme.buildAction.targets { plist += """ """ } plist += """ """ if let runAction = scheme.runAction { plist += """ """ } plist += """ """ try path.write(plist) log.info("Generated '\(path)'") } private func writeSchemes() throws { for scheme in schemes { try writeScheme(scheme) } } func write() throws { try disableAutoCreationIfNeeded() try writeSchemes() } }