Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Sources/CoreCommands/SwiftCommandState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -900,7 +900,7 @@ public final class SwiftCommandState {
}

static let entitlementsMacOSWarning = """
`--disable-get-task-allow-entitlement` and `--disable-get-task-allow-entitlement` only have an effect \
`--enable-get-task-allow-entitlement` and `--disable-get-task-allow-entitlement` only have an effect \
when building on macOS.
"""

Expand Down
1 change: 1 addition & 0 deletions Sources/SwiftBuildSupport/PackagePIFBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,7 @@ public final class PackagePIFBuilder {
releaseSettings[.DEBUG_INFORMATION_FORMAT] = "dwarf-with-dsym"
releaseSettings[.GCC_OPTIMIZATION_LEVEL] = "s"
releaseSettings[.SWIFT_OPTIMIZATION_LEVEL] = "-Owholemodule"
releaseSettings[.DEPLOYMENT_POSTPROCESSING] = "YES"
builder.project.addBuildConfig { id in BuildConfig(id: id, name: "Release", settings: releaseSettings) }
}

Expand Down
46 changes: 36 additions & 10 deletions Sources/SwiftBuildSupport/SwiftBuildSystem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -119,17 +119,35 @@ func withSession(
}

package final class SwiftBuildSystemPlanningOperationDelegate: SWBPlanningOperationDelegate, SWBIndexingDelegate, Sendable {
package init() {}
private let shouldEnableDebuggingEntitlement: Bool

package init(shouldEnableDebuggingEntitlement: Bool) {
self.shouldEnableDebuggingEntitlement = shouldEnableDebuggingEntitlement
}

public func provisioningTaskInputs(
targetGUID: String,
provisioningSourceData: SWBProvisioningTaskInputsSourceData
) async -> SWBProvisioningTaskInputs {
let identity = provisioningSourceData.signingCertificateIdentifier
if identity == "-" {
let signedEntitlements = provisioningSourceData.entitlementsDestination == "Signature"
? provisioningSourceData.productTypeEntitlements.merging(
["application-identifier": .plString(provisioningSourceData.bundleIdentifier)],

if identity == "-" || identity.isEmpty {
let getTaskAllowEntitlementKey: String
let applicationIdentifierEntitlementKey: String

if provisioningSourceData.sdkRoot.contains("macos") || provisioningSourceData.sdkRoot
.contains("simulator")
{
getTaskAllowEntitlementKey = "com.apple.security.get-task-allow"
applicationIdentifierEntitlementKey = "com.apple.application-identifier"
} else {
getTaskAllowEntitlementKey = "get-task-allow"
applicationIdentifierEntitlementKey = "application-identifier"
}

let signedEntitlements = provisioningSourceData
.entitlementsDestination == "Signature" ? provisioningSourceData.productTypeEntitlements.merging(
[applicationIdentifierEntitlementKey: .plString(provisioningSourceData.bundleIdentifier)],
uniquingKeysWith: { _, new in new }
).merging(provisioningSourceData.projectEntitlements ?? [:], uniquingKeysWith: { _, new in new })
: [:]
Expand All @@ -141,6 +159,12 @@ package final class SwiftBuildSystemPlanningOperationDelegate: SWBPlanningOperat
).merging(provisioningSourceData.projectEntitlements ?? [:], uniquingKeysWith: { _, new in new })
: [:]

var additionalEntitlements: [String: SWBPropertyListItem] = [:]

if shouldEnableDebuggingEntitlement {
additionalEntitlements[getTaskAllowEntitlementKey] = .plBool(true)
}

return SWBProvisioningTaskInputs(
identityHash: "-",
identityName: "-",
Expand All @@ -149,7 +173,7 @@ package final class SwiftBuildSystemPlanningOperationDelegate: SWBPlanningOperat
profilePath: nil,
designatedRequirements: nil,
signedEntitlements: signedEntitlements.merging(
provisioningSourceData.sdkRoot.contains("simulator") ? ["get-task-allow": .plBool(true)] : [:],
additionalEntitlements,
uniquingKeysWith: { _, new in new }
),
simulatedEntitlements: simulatedEntitlements,
Expand All @@ -160,8 +184,6 @@ package final class SwiftBuildSystemPlanningOperationDelegate: SWBPlanningOperat
errors: [],
warnings: []
)
} else if identity.isEmpty {
return SWBProvisioningTaskInputs()
} else {
return SWBProvisioningTaskInputs(
identityHash: "-",
Expand Down Expand Up @@ -599,7 +621,9 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {

let operation = try await session.createBuildOperation(
request: request,
delegate: SwiftBuildSystemPlanningOperationDelegate(),
delegate: SwiftBuildSystemPlanningOperationDelegate(shouldEnableDebuggingEntitlement: self.buildParameters
.debuggingParameters.shouldEnableDebuggingEntitlement
),
retainBuildDescription: true
)

Expand Down Expand Up @@ -995,7 +1019,9 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
private static func constructDebuggingSettingsOverrides(from parameters: BuildParameters.Debugging) -> [String: String] {
var settings: [String: String] = [:]
// TODO: debugInfoFormat: https://github.com/swiftlang/swift-build/issues/560
// TODO: shouldEnableDebuggingEntitlement: Enable/Disable get-task-allow
if parameters.shouldEnableDebuggingEntitlement {
settings["DEPLOYMENT_POSTPROCESSING"] = "NO"
}
// TODO: omitFramePointer: https://github.com/swiftlang/swift-build/issues/561
return settings
}
Expand Down
184 changes: 107 additions & 77 deletions Tests/CommandsTests/BuildCommandTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,21 @@
//
//===----------------------------------------------------------------------===//

import Foundation
import _InternalTestSupport
import Basics
@testable import Commands
@testable import CoreCommands
import Foundation
import PackageGraph
import PackageLoading
import PackageModel
import enum PackageModel.BuildConfiguration
import SPMBuildCore
import _InternalTestSupport
import enum SWBUtil.PropertyList
import enum SWBUtil.PropertyListItem
import Testing
import TSCTestSupport
import Workspace
import Testing

struct BuildResult {
let binPath: AbsolutePath
Expand Down Expand Up @@ -1298,7 +1300,6 @@ struct BuildCommandTestCases {
}

@Test(
.SWBINTTODO("Test failed because swiftbuild doesn't output precis codesign commands. Once swift run works with swiftbuild the test can be investigated."),
.tags(
.Feature.CommandLineArguments.DisableGetTaskAllowEntitlement,
.Feature.CommandLineArguments.EnableGetTaskAllowEntitlement,
Expand All @@ -1307,98 +1308,127 @@ struct BuildCommandTestCases {
.tags(
.Feature.CommandLineArguments.BuildSystem,
),
arguments: SupportedBuildSystemOnPlatform,
arguments: getBuildData(for: SupportedBuildSystemOnAllPlatforms),
)
func getTaskAllowEntitlement(
buildSystem: BuildSystemProvider.Kind,
data: BuildData,
) async throws {
try await withKnownIssue(isIntermittent: true) {
try await fixture(name: "ValidLayouts/SingleModule/ExecutableNew") { fixturePath in
#if os(macOS)
// try await building with default parameters. This should succeed. We build verbosely so we get full command
// lines.
var buildResult = try await build(["-v"], packagePath: fixturePath, configuration: .debug, buildSystem: buildSystem,)

// TODO verification of the ad-hoc code signing can be done by `swift run` of the executable in these cases once swiftbuild build system is working with that
#expect(buildResult.stdout.contains("codesign --force --sign - --entitlements"))

buildResult = try await build(["-v"], packagePath: fixturePath, configuration:.debug, buildSystem: buildSystem,)

#expect(buildResult.stdout.contains("codesign --force --sign - --entitlements"))

// Build with different combinations of the entitlement flag and debug/release build configurations.

buildResult = try await build(
["--enable-get-task-allow-entitlement", "-v"],
packagePath: fixturePath,
configuration: .release,
buildSystem: buildSystem,
)
let buildSystem = data.buildSystem
let buildConfiguration = data.config
try await fixture(name: "ValidLayouts/SingleModule/ExecutableNew") { fixturePath in
#if os(macOS)
func codesignDisplay(execPath: AbsolutePath) async throws
-> (AsyncProcessResult.ExitStatus, PropertyListItem?)
{
let args = ["codesign", "-d", "--entitlements", "-", "--xml", execPath.pathString]
let result = try await AsyncProcess.popen(arguments: args)
let entitlements: PropertyListItem? = if case .success(let output) = result.output,
!output.isEmpty
{
try PropertyList.fromBytes(output)
} else {
nil
}

#expect(buildResult.stdout.contains("codesign --force --sign - --entitlements"))
return (result.exitStatus, entitlements)
}

buildResult = try await build(
["--enable-get-task-allow-entitlement", "-v"],
packagePath: fixturePath,
configuration: .debug,
buildSystem: buildSystem,
)
func verify(entitlements: PropertyListItem?, getTaskAllowRequired: Bool) {
guard let entitlements, case .plDict(let dict) = entitlements else {
if getTaskAllowRequired {
Issue.record("Missing expected entitlements")
}
return
}

#expect(buildResult.stdout.contains("codesign --force --sign - --entitlements"))
if getTaskAllowRequired {
#expect(dict["com.apple.security.get-task-allow"] == .plBool(true))
}
}

buildResult = try await build(
["--disable-get-task-allow-entitlement", "-v"],
packagePath: fixturePath,
configuration: .debug,
buildSystem: buildSystem,
)
let execName = "ExecutableNew"

#expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements"))
var buildResult = try await build(
["-v"],
packagePath: fixturePath,
configuration: buildConfiguration,
cleanAfterward: false,
buildSystem: buildSystem
)
var (
exitStatus,
entitlements
) = try await codesignDisplay(execPath: buildResult.binPath.appending(execName))

buildResult = try await build(
["--disable-get-task-allow-entitlement", "-v"],
packagePath: fixturePath,
configuration: .release,
buildSystem: buildSystem,
)
// codesign performs basic verification in display mode, which is enough to confirm ad-hoc signature
// if verification fails (eg. no signature) termination code will be 1
// though on Apple Silicon binary will always be signed because linker signs it by default
#expect(exitStatus == .terminated(code: 0))
verify(entitlements: entitlements, getTaskAllowRequired: buildConfiguration == .debug)

#expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements"))
#else
var buildResult = try await build(["-v"], packagePath: fixturePath, configuration: .debug, buildSystem: buildSystem,)
try await executeSwiftPackage(fixturePath, extraArgs: ["clean"], buildSystem: buildSystem)

#expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements"))
buildResult = try await build(
["--enable-get-task-allow-entitlement"],
packagePath: fixturePath,
configuration: buildConfiguration,
cleanAfterward: false,
buildSystem: buildSystem
)
(
exitStatus,
entitlements
) = try await codesignDisplay(execPath: buildResult.binPath.appending(execName))

buildResult = try await build(["-v"], packagePath: fixturePath, configuration: .release,buildSystem: buildSystem,)
#expect(exitStatus == .terminated(code: 0))
verify(entitlements: entitlements, getTaskAllowRequired: true)

#expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements"))
try await executeSwiftPackage(fixturePath, extraArgs: ["clean"], buildSystem: buildSystem)

buildResult = try await build(
["--disable-get-task-allow-entitlement", "-v"],
packagePath: fixturePath,
configuration: .release,
buildSystem: buildSystem,
)
buildResult = try await build(
["--disable-get-task-allow-entitlement"],
packagePath: fixturePath,
configuration: buildConfiguration,
cleanAfterward: false,
buildSystem: buildSystem
)
(
exitStatus,
entitlements
) = try await codesignDisplay(execPath: buildResult.binPath.appending(execName))

#expect(exitStatus == .terminated(code: 0))
verify(entitlements: entitlements, getTaskAllowRequired: false)
#else
var buildResult = try await build(
["-v"],
packagePath: fixturePath,
configuration: buildConfiguration,
buildSystem: buildSystem
)

#expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements"))
#expect(buildResult.stderr.contains(SwiftCommandState.entitlementsMacOSWarning))
#expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements"))

buildResult = try await build(
["--enable-get-task-allow-entitlement", "-v"],
packagePath: fixturePath,
configuration: .release,
buildSystem: buildSystem,
)
buildResult = try await build(
["--disable-get-task-allow-entitlement", "-v"],
packagePath: fixturePath,
configuration: buildConfiguration,
buildSystem: buildSystem,
)

#expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements"))
#expect(buildResult.stderr.contains(SwiftCommandState.entitlementsMacOSWarning))
#endif
#expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements"))
#expect(buildResult.stderr.contains(SwiftCommandState.entitlementsMacOSWarning))

buildResult = try await build(["-v"], packagePath: fixturePath, configuration: .release, buildSystem: buildSystem)
buildResult = try await build(
["--enable-get-task-allow-entitlement", "-v"],
packagePath: fixturePath,
configuration: buildConfiguration,
buildSystem: buildSystem,
)

#expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements"))
}
} when: {
[.swiftbuild, .xcode].contains(buildSystem) && ProcessInfo.hostOperatingSystem != .linux
#expect(!buildResult.stdout.contains("codesign --force --sign - --entitlements"))
#expect(buildResult.stderr.contains(SwiftCommandState.entitlementsMacOSWarning))
#endif
}
}

Expand Down
Loading