diff --git a/Sources/SWBApplePlatform/AssetCatalogCompiler.swift b/Sources/SWBApplePlatform/AssetCatalogCompiler.swift index 45bb476a..ac390469 100644 --- a/Sources/SWBApplePlatform/AssetCatalogCompiler.swift +++ b/Sources/SWBApplePlatform/AssetCatalogCompiler.swift @@ -119,6 +119,12 @@ public final class ActoolCompilerSpec : GenericCompilerSpec, SpecIdentifierType, return true } + public override var requiresTextBasedAPI: Bool { + // Don't enforce `SUPPORTS_TEXT_BASED_API` setting if the group only contains + // asset catalogs since generated symbols code doesn't export API. Related: rdar://108210630, rdar://108379090. + return false + } + /// Override to compute the special arguments. public override func constructTasks(_ cbc: CommandBuildContext, _ delegate: any TaskGenerationDelegate) async { let buildComponents = cbc.scope.evaluate(BuiltinMacros.BUILD_COMPONENTS) diff --git a/Sources/SWBCore/BuildRuleAction.swift b/Sources/SWBCore/BuildRuleAction.swift index 89fd0890..ff61bfe5 100644 --- a/Sources/SWBCore/BuildRuleAction.swift +++ b/Sources/SWBCore/BuildRuleAction.swift @@ -30,6 +30,9 @@ public protocol BuildRuleAction: AnyObject, CustomStringConvertible, Sendable { /// Whether actions of this type should run during `InstallHeaders`. var supportsInstallHeaders: Bool { get } + /// True if the presence of actions of this type requires the target to use TAPI. + var requiresTextBasedAPI: Bool { get } + /// Identifier of the rule. var identifier: String { get } @@ -73,6 +76,10 @@ public final class BuildRuleTaskAction: BuildRuleAction { return toolSpec.supportsInstallHeaders } + public var requiresTextBasedAPI: Bool { + return toolSpec.requiresTextBasedAPI + } + public var identifier: String { return toolSpec.identifier } @@ -137,6 +144,11 @@ public final class BuildRuleScriptAction: BuildRuleAction { return runDuringInstallHeaders } + public var requiresTextBasedAPI: Bool { + // In general anything that might install symbols for other projects should use TAPI. + return supportsInstallAPI || supportsInstallHeaders + } + public var identifier: String { return guid } diff --git a/Sources/SWBCore/SpecImplementations/CommandLineToolSpec.swift b/Sources/SWBCore/SpecImplementations/CommandLineToolSpec.swift index 65072bc4..f9798b10 100644 --- a/Sources/SWBCore/SpecImplementations/CommandLineToolSpec.swift +++ b/Sources/SWBCore/SpecImplementations/CommandLineToolSpec.swift @@ -389,6 +389,12 @@ open class CommandLineToolSpec : PropertyDomainSpec, SpecType, TaskTypeDescripti return false } + /// True if the presence of tasks of this type requires the target to use TAPI. + open var requiresTextBasedAPI: Bool { + // In general anything that might install symbols for other projects should use TAPI. + return supportsInstallAPI || supportsInstallHeaders + } + open var enableSandboxing: Bool { return false } diff --git a/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/FilesBasedBuildPhaseTaskProducer.swift b/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/FilesBasedBuildPhaseTaskProducer.swift index 85fdeaa0..710ad65d 100644 --- a/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/FilesBasedBuildPhaseTaskProducer.swift +++ b/Sources/SWBTaskConstruction/TaskProducers/BuildPhaseTaskProducers/FilesBasedBuildPhaseTaskProducer.swift @@ -650,15 +650,10 @@ class FilesBasedBuildPhaseTaskProducerBase: PhasedTaskProducer { // If this target itself hasn't adopted Install API, then it is an error (since presumably it is required). if !scope.evaluate(BuiltinMacros.SUPPORTS_TEXT_BASED_API) { - // If TAPI support errors are disabled, ignore the error. - if !scope.evaluate(BuiltinMacros.ALLOW_UNSUPPORTED_TEXT_BASED_API) { - // Don't enforce `SUPPORTS_TEXT_BASED_API` setting if the group only contains - // asset catalogs since generated symbols code doesn't export API. Related: rdar://108210630, rdar://108379090. - - // xcassets get grouped together. - let isAllCatalogs = group.files.allSatisfy({ $0.fileType.conformsTo(identifier: "folder.abstractassetcatalog") }) + // If TAPI support errors are disabled or this task type doesn't actually require it, ignore the error. + if !scope.evaluate(BuiltinMacros.ALLOW_UNSUPPORTED_TEXT_BASED_API) && group.assignedBuildRuleAction?.requiresTextBasedAPI ?? false { let productType: ProductTypeSpec? = try? context.getSpec(scope.evaluate(BuiltinMacros.PRODUCT_TYPE)) - if let productType = productType, productType.supportsInstallAPI && !generatedRequiresAPIError && !isAllCatalogs { + if let productType = productType, productType.supportsInstallAPI && !generatedRequiresAPIError { producer.context.error("\(productType.name) requested to generate API, but has not adopted SUPPORTS_TEXT_BASED_API", location: .buildSetting(BuiltinMacros.SUPPORTS_TEXT_BASED_API)) generatedRequiresAPIError = true }