//===--- 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
//
//===----------------------------------------------------------------------===//
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()
}
}