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
118 changes: 74 additions & 44 deletions Sources/PackageDescription/PackageDependency.swift

Large diffs are not rendered by default.

22 changes: 13 additions & 9 deletions Sources/PackageDescription/PackageDependencyTrait.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,22 @@
//===----------------------------------------------------------------------===//

extension Package.Dependency {
/// A struct representing an enabled trait of a dependency.
/// An enabled trait of a dependency.
@available(_PackageDescription, introduced: 6.1)
public struct Trait: Hashable, Sendable, ExpressibleByStringLiteral {
/// Enables all default traits of a package.
/// Enables all default traits of the dependency.
public static let defaults = Self.init(name: "default")

/// A condition that limits the application of a dependencies trait.
/// A condition that limits the application of a trait for a dependency.
public struct Condition: Hashable, Sendable {
/// The set of traits of this package that enable the dependencie's trait.
/// The set of traits that enable the dependencies trait.
let traits: Set<String>?

/// Creates a package dependency trait condition.
///
/// - Parameter traits: The set of traits that enable the dependencies trait. If any of the traits are enabled on this package
/// the dependencies trait will be enabled.
/// If the depending package enables any of the traits you provide, the package manager enables the dependency to which this condition applies.
///
/// - Parameter traits: The set of traits that enable the dependencies trait.
public static func when(
traits: Set<String>
) -> Self? {
Expand All @@ -36,10 +37,10 @@ extension Package.Dependency {
/// The name of the enabled trait.
public var name: String

/// The condition under which the trait is enabled.
/// The condition under which the package manager enables the dependency.
public var condition: Condition?

/// Initializes a new enabled trait.
/// Creates a new enabled trait.
///
/// - Parameters:
/// - name: The name of the enabled trait.
Expand All @@ -52,11 +53,14 @@ extension Package.Dependency {
self.condition = condition
}

/// Creates a new enabled trait.
///
/// - Parameter value: The name of the enabled trait.
public init(stringLiteral value: StringLiteralType) {
self.init(name: value)
}

/// Initializes a new enabled trait.
/// Creates a new enabled trait.
///
/// - Parameters:
/// - name: The name of the enabled trait.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# ``PackageDescription/Package/Dependency/Trait``

## Topics

### Declaring a Dependency Trait

- ``trait(name:condition:)``
- ``defaults``

### Creating a Dependency Trait

- ``init(name:condition:)``
- ``init(stringLiteral:)``
- ``Condition``

### Inspecting a Dependency Trait

- ``name``
- ``condition``
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,12 @@
- ``Trait``
- ``RegistryRequirement``
- ``SourceControlRequirement``
- ``requirement-swift.property``
- ``Requirement-swift.enum``

### Describing a Package Dependency

- ``kind-swift.property``
- ``Kind``
- ``Version``
- ``name``
- ``url``

### Deprecated methods

Expand All @@ -63,3 +59,5 @@
- ``package(url:_:)-(_,Package.Dependency.Requirement)``
- ``name``
- ``url``
- ``requirement-swift.property``
- ``Requirement-swift.enum``
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@

- ``Package/init(name:defaultLocalization:platforms:pkgConfig:providers:products:dependencies:targets:swiftLanguageModes:cLanguageStandard:cxxLanguageStandard:)``
- ``Package/init(name:defaultLocalization:platforms:pkgConfig:providers:products:traits:dependencies:targets:swiftLanguageModes:cLanguageStandard:cxxLanguageStandard:)``
- ``Package/init(name:defaultLocalization:platforms:pkgConfig:providers:products:dependencies:targets:swiftLanguageVersions:cLanguageStandard:cxxLanguageStandard:)``
- ``Package/init(name:platforms:pkgConfig:providers:products:dependencies:targets:swiftLanguageVersions:cLanguageStandard:cxxLanguageStandard:)``
- ``Package/init(name:pkgConfig:providers:products:dependencies:targets:swiftLanguageVersions:cLanguageStandard:cxxLanguageStandard:)-(_,_,_,_,_,_,[Int]?,_,_)``
- ``Package/init(name:pkgConfig:providers:products:dependencies:targets:swiftLanguageVersions:cLanguageStandard:cxxLanguageStandard:)-(_,_,_,_,_,_,[SwiftVersion]?,_,_)``

- ``Package/init(name:defaultLocalization:platforms:pkgConfig:providers:products:dependencies:targets:swiftLanguageVersions:cLanguageStandard:cxxLanguageStandard:)``

### Naming the Package

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# ``PackageDescription/Trait``

## Topics

### Declaring Traits

- ``trait(name:description:enabledTraits:)``
- ``default(enabledTraits:)``

### Creating Traits

- ``init(name:description:enabledTraits:)``
- ``init(stringLiteral:)``

### Inspecting Traits

- ``name``
- ``description``
- ``enabledTraits``

4 changes: 2 additions & 2 deletions Sources/PackageDescription/PackageDescription.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public final class Package {
/// The list of products that this package vends and that clients can use.
public var products: [Product]

/// The set of traits of this package.
/// The set of traits this package provides.
@available(_PackageDescription, introduced: 6.1)
public var traits: Set<Trait>

Expand Down Expand Up @@ -344,7 +344,7 @@ public final class Package {
/// `<name>.pc` file to get the additional flags required for a system target.
/// - providers: The package providers for a system target.
/// - products: The list of products that this package makes available for clients to use.
/// - traits: The set of traits of this package.
/// - traits: The set of traits this package provides.
/// - dependencies: The list of package dependencies.
/// - targets: The list of targets that are part of this package.
/// - swiftLanguageModes: The list of Swift language modes with which this package is compatible.
Expand Down
58 changes: 50 additions & 8 deletions Sources/PackageDescription/Trait.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,50 @@
//
//===----------------------------------------------------------------------===//

/// A struct representing a package's trait.
/// A package trait.
///
/// Traits can be used for expressing conditional compilation and optional dependencies.
/// A trait is a package feature that expresses conditional compilation and potentially optional dependencies.
/// It is typically used to expose additional or extended API for the package.
///
/// - Important: Traits must be strictly additive and enabling a trait **must not** remove API.
/// When you define a trait on a package, the package manager uses the name of that trait as a conditional block for the package's code.
/// Use the conditional block to enable imports or code paths for that trait.
/// For example, a trait with the canonical name `MyTrait` allows you to use the name as a conditional block:
///
/// ```swift
/// #if MyTrait
/// // additional imports or APIs that MyTrait enables
/// #endif // MyTrait
/// ```
///
/// - Important: Traits must be strictly additive. Enabling a trait **must not** remove API.
///
/// If your conditional code requires a dependency that you want to enable only when the trait is enabled,
/// add a conditional declaration to the target dependencies,
/// then include the import statement within the conditional block.
/// The following example illustrates enabling the dependency `MyDependency` when the trait `Trait1` is enabled:
///
/// ```swift
/// targets: [
/// .target(
/// name: "MyTarget",
/// dependencies: [
/// .product(
/// name: "MyAPI",
/// package: "MyDependency",
/// condition: .when(traits: ["Trait1"])
/// )
/// ]
/// ),
/// ]
/// ```
///
/// Coordinate a declaration like the example above with code that imports the dependency in a conditional block:
///
/// ```swift
/// #if Trait1
/// import MyAPI
/// #endif // Trait1
/// ```
@available(_PackageDescription, introduced: 6.1)
public struct Trait: Hashable, ExpressibleByStringLiteral {
/// Declares the default traits for this package.
Expand All @@ -28,25 +67,26 @@ public struct Trait: Hashable, ExpressibleByStringLiteral {

/// The trait's canonical name.
///
/// This is used when enabling the trait or when referring to it from other modifiers in the manifest.
/// Use the trait's name to enable the trait or when referring to it from other modifiers in the manifest.
/// The trait's name also defines the conditional block that the compiler supports when the trait is active.
///
/// The following rules are enforced on trait names:
/// - The first character must be a [Unicode XID start character](https://unicode.org/reports/tr31/#Figure_Code_Point_Categories_for_Identifier_Parsing)
/// (most letters), a digit, or `_`.
/// - Subsequent characters must be a [Unicode XID continue character](https://unicode.org/reports/tr31/#Figure_Code_Point_Categories_for_Identifier_Parsing)
/// (a digit, `_`, or most letters), `-`, or `+`.
/// - `default` and `defaults` (in any letter casing combination) are not allowed as trait names to avoid confusion with default traits.
/// - The names `default` and `defaults` (in any letter casing combination) aren't allowed as trait names to avoid confusion with default traits.
public var name: String

/// The trait's description.
///
/// Use this to explain what functionality this trait enables.
/// Use the description to explain the additional functionality that the trait enables.
public var description: String?

/// A set of other traits of this package that this trait enables.
public var enabledTraits: Set<String>

/// Initializes a new trait.
/// Creates a trait with a name, a description, and set of additional traits it enables.
///
/// - Parameters:
/// - name: The trait's canonical name.
Expand All @@ -62,11 +102,13 @@ public struct Trait: Hashable, ExpressibleByStringLiteral {
self.enabledTraits = enabledTraits
}

/// Creates a trait with the name you provide.
/// - Parameter value: The trait's canonical name.
public init(stringLiteral value: StringLiteralType) {
self.init(name: value)
}

/// Initializes a new trait.
/// Creates a trait with a name, a description, and set of additional traits it enables.
///
/// - Parameters:
/// - name: The trait's canonical name.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# Adding dependencies to a Swift package

Use other swift packages, system libraries, or binary dependencies in your package.
Use other Swift packages, system libraries, or binary dependencies in your package.

## Overview

To depend on another Swift package, define a dependency and the requirements for its version if it's remote, then add a product of that dependency to one or more of your targets.

A remote dependency requires a location, represented by a URL, and a requirement on the versions the package manager may use.

The following example illustrates a package that depends on [PlayingCard](https://github.com/apple/example-package-playingcard), using `from` to require at least version `3.0.4`, and allow any other version up to the next major version that is available at the time of dependency resolution.
The following example illustrates a package that depends on [PlayingCard](https://github.com/apple/example-package-playingcard), using `from` to require at least version `4.0.0`, and allow any other version up to the next major version that is available at the time of dependency resolution.
It then uses the product `PlayingCard` as a dependency for the target `MyPackage`:

```swift
Expand All @@ -19,7 +19,7 @@ let package = Package(
name: "MyPackage",
dependencies: [
.package(url: "https://github.com/apple/example-package-playingcard.git",
from: "3.0.4"),
from: "4.0.0"),
],
targets: [
.target(
Expand All @@ -43,15 +43,52 @@ For more information on resolving package versions, see <doc:ResolvingPackageVer

### Constraining dependency versions

Constrain the version of a remote dependency when you when you declare the dependency.
The package manager uses git tags interpretted as semantic versions to identify eligible versions of packages.
Constrain the version of a remote dependency when you declare the dependency.
The package manager uses git tags, interpreted as a semantic version, to identify eligible versions of packages.

> Note: tags for package versions should include all three components of a semantic version: major, minor, and patch.
> Note: tags for package versions should include all three components of a semantic version: major, minor, and patch.
> Tags that only include one or two of those components are not interpreted as semantic versions.

Use the version requirement when you declare the dependency to limit what the package manager can choose.
The version requirement can be a range of possible semantic versions, a specific semantic version, a branch name, or a commit hash.
The API reference documentation for [Package.Dependency](https://developer.apple.com/documentation/packagedescription/package/dependency) defines the methods to use.
The API reference documentation for [Package.Dependency](https://docs.swift.org/swiftpm/documentation/packagedescription/package/dependency) defines the methods to use.

### Packages with Traits

Traits, introduced with Swift 6.1, allow packages to offer additional API that may include optional dependencies.
Packages should offer traits to provide API beyond the core of a package.
For example, a package may provide an experimental API, an optional API that requires additional dependencies, or functionality that isn't critical that a developer may want to enable only in specific circumstances.

If a package offers traits and you depend on it without defining the traits to use, the package uses its default set of traits.
In the following example, the dependency `example-package-playingcard` uses its default traits, if it offers any:
```swift
dependencies: [
.package(url: "https://github.com/swiftlang/example-package-playingcard",
from: "4.0.0")
]
```

To determine what traits a package offers, including its defaults, either inspect its `Package.swift` manifest or use <doc:PackageShowDependencies> to print out the resolved dependencies and their traits.

Enabling a trait should only expand the API offered by a package.
If a package offers default traits, you can choose to not use those traits by declaring an empty set of traits when you declare the dependency.
The following example dependency declaration uses the dependency with no traits, even if the package normally provides a set of default traits to enable:

```swift
dependencies: [
.package(url: "https://github.com/swiftlang/example-package-playingcard",
from: "4.0.0",
traits: [])
]
```

Swift package manager determines the traits to enable using the entire graph of dependencies in a project.
The traits enabled for a dependency is the union of all of the traits that for packages that depend upon it.
For example, if you opt out of all traits, but a dependency you use uses the same package with some trait enabled, the package will use the depdendency with the requested traits enabled.

> Note: By disabling any default traits, you may be removing available APIs from the dependency you use.

To learn how to provide packages with traits, see <doc:PackageTraits>.

### Local Dependencies

Expand All @@ -77,6 +114,7 @@ For more information on creating a binary target, see [Creating a multiplatform
## Topics

- <doc:ResolvingPackageVersions>
- <doc:PackageTraits>
- <doc:ResolvingDependencyFailures>
- <doc:AddingSystemLibraryDependency>
- <doc:ExampleSystemLibraryPkgConfig>
Expand Down
Loading