Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Swift Package Manager

Swift Package Manager

Chiaote Ni

July 01, 2022
Tweet

More Decks by Chiaote Ni

Other Decks in Programming

Transcript

  1. Aaron Ni
    Swift Package Manager

    View full-size slide

  2. Init with SPM

    View full-size slide

  3. // swift-tools-version:5.5


    // The swift-tools-version declares the minimum version of Swift required to build this package.


    import PackageDescription


    let package = Package(


    name: "SPMDemo",


    products: [


    // Products define the executables and libraries a package produces, and make them visible to other packages.


    .library(


    name: "SPMDemo",


    targets: ["SPMDemo"]),


    ],


    dependencies: [


    // Dependencies declare other packages that this package depends on.


    // .package(url: /* package url */, from: "1.0.0"),


    ],


    targets: [


    // Targets are the basic building blocks of a package. A target can define a module or a test suite.


    // Targets can depend on other targets in this package, and on products in packages this package depends on.


    .target(


    name: "SPMDemo",


    dependencies: []),


    .testTarget(


    name: "SPMDemoTests",


    dependencies: ["SPMDemo"]),


    ]


    )

    View full-size slide

  4. swift package init
    OVERVIEW: Initialize a new package


    USAGE: swift package init


    OPTIONS:


    --type Package type: empty | library | executable


    | system-module | manifest (default: library)

    --name Provide custom package name


    --version Show the version.


    -help, -h, --help Show help information.
    swift package init --type library --name SPMDemo
    EX:

    View full-size slide

  5. It’s easy to declared the product you want to
    release:

    - library


    - executable

    - plugin


    Thanks for the interface which declared in
    framework PackageDescription 🙌

    View full-size slide

  6. // swift-tools-version:5.5


    // The swift-tools-version declares the minimum version of Swift required to build this package.


    import PackageDescription


    let package = Package(


    name: "SPMDemo",


    products: [


    .library(


    name: "SPMDemo",


    targets: [“SPMDemo"]


    ),


    ],


    dependencies: [],


    targets: [


    .target(


    name: "SPMDemo",


    dependencies: [])


    ]


    )

    View full-size slide

  7. // swift-tools-version:5.5


    // The swift-tools-version declares the minimum version of Swift required to build this package.


    import PackageDescription


    let package = Package(


    name: "SPMDemo",


    products: [


    .library(


    name: "SPMDemo",


    targets: [“SPMDemo"]


    ),


    ],


    dependencies: [],


    targets: [


    .target(


    name: "SPMDemo",


    dependencies: [])


    ]


    )
    Remember to modify the tool version here if needed.

    Some new features of SPM PlugIn are based on
    versions 5.6 - 5.7.


    View full-size slide

  8. Project / Target / Dependencies

    View full-size slide

  9. // swift-tools-version:5.5


    // The swift-tools-version declares the minimum version of Swift requir


    import PackageDescription


    let package = Package(


    name: "Utilities",


    products: [


    // Products define the executables and libraries a package prod


    .library(


    name: "Extensions",


    targets: ["Extensions"]


    ),


    .library(


    name: "BuilderHelper",


    targets: ["Buildable", "KeyPathConstraints"]


    ),


    .library(


    name: "Buildable",


    targets: ["Buildable"]


    )


    ],


    targets: [


    // Targets are the basic building blocks of a package. A target


    // Targets can depend on other targets in this package, and on


    .target(name: "Extensions"),


    .target(name: "Buildable"),


    .target(name: "KeyPathConstraints")


    ]


    )


    View full-size slide

  10. import PackageDescription


    let package = Package(


    name: "ExampleLogger",


    products: [


    // Products define the executables and libraries a package produces, and make them visible to other
    packages.


    .library(


    name: "ExampleLogger",


    targets: ["ExampleLogger"]),


    ],


    dependencies: [


    .package(name: "Utilities", path: "../Utilities"),


    ],


    targets: [


    // Targets are the basic building blocks of a package. A target can define a module or a test suite.


    // Targets can depend on other targets in this package, and on products in packages this package depends
    on.


    .target(


    name: "ExampleLogger",


    dependencies: [


    .product(name: "Extensions", package: "Utilities", condition: .none),


    .product(name: "Buildable", package: "Utilities", condition: .none)


    ]),


    .testTarget(


    name: "ExampleLoggerTests",


    dependencies: ["ExampleLogger"]),


    ]


    )


    Buildable only

    View full-size slide

  11. import PackageDescription


    let package = Package(


    name: "ExampleLogger",


    products: [


    // Products define the executables and libraries a package produces, and make them visible to other
    packages.


    .library(


    name: "ExampleLogger",


    targets: ["ExampleLogger"]),


    ],


    dependencies: [


    .package(name: "Utilities", path: "../Utilities"),


    ],


    targets: [


    // Targets are the basic building blocks of a package. A target can define a module or a test suite.


    // Targets can depend on other targets in this package, and on products in packages this package depends
    on.


    .target(


    name: "ExampleLogger",


    dependencies: [


    .product(name: "Extensions", package: "Utilities", condition: .none),


    .product(name: "BuilderHelper", package: "Utilities", condition: .none)


    ]),


    .testTarget(


    name: "ExampleLoggerTests",


    dependencies: ["ExampleLogger"]),


    ]


    )


    Buildable + KeyPathConstraints

    View full-size slide

  12. let package = Package(


    name: "ExampleLogger",


    products: [


    // Products define the executables and libraries a package produces, and make them visib
    to other packages.


    .library(


    name: "ExampleLogger",


    targets: ["ExampleLogger"]),


    ],


    dependencies: [


    .package(


    name: "Utilities",


    path: "../Utilities"


    ),


    .package(


    name: "PathView",


    url: "https://[email protected]/aaronni19/pathview.git",


    branch: "feat/simple-demo"


    ),


    .package(


    name: "StarPage",


    url: "https://[email protected]/aaronni19/starpage.git",


    from: "1.0.0"


    )


    ]


    )

    View full-size slide

  13. targets: [
    .target(
    name: "PathView",
    dependencies: []
    ),
    .plugin(
    name: "CodeGenerator",
    capability: .command(
    intent: .custom(
    verb: "generate-code",
    description: "Generator the source code from D-Paths"
    ),
    permissions: [
    .writeToPackageDirectory(reason: "blahblahblah")
    ]
    )
    ),
    .testTarget(
    name: "PathViewTests",
    dependencies: ["PathView"]),
    ]

    View full-size slide

  14. • Commands
    • Invoked by the command line, applied directly to a package, not during a
    build

    • Build tools
    • Invoked by the SPM targets

    View full-size slide

  15. import PackagePlugin


    @main // main entry point


    struct CodeGenerator: CommandPlugin {


    /// - Parameters:


    /// - context: Provides information about the package for which the plugin is invoked,


    /// as well as contextual information based on the plugin's stated intent


    /// and requirements.


    /// - arguments: arguments


    func performCommand(


    context: PackagePlugin.PluginContext,


    arguments: [String]


    ) async throws {


    //...


    }


    }
    source code formatting

    View full-size slide

  16. import PackagePlugin


    @main // main entry point


    struct CodeGenerator: BuildToolPlugin {


    /// - Parameters:


    /// - context:You can get some information about the package to which the plugin is being
    /// applied, pluginWorkDirectory, and a named command line executable tool


    /// - target: some information of the current target (name, directory, dependencies)


    /// - Returns: command to run during the build, you can return the build and prebuild
    /// commands here


    func createBuildCommands(


    context: PackagePlugin.PluginContext,


    target: PackagePlugin.Target


    ) async throws -> [PackagePlugin.Command] {


    // ...


    }


    }

    View full-size slide

  17. • Commands
    • source code formatting

    • documentation generation

    • custom

    View full-size slide

  18. • In-build command
    • Your tool has a de
    fi
    ned set of outputs.

    • Re-run when outputs are missing or inputs change

    • Pre-build command
    • Don't have a clear set of outputs

    • Runs at the start of every build

    • Be careful about doing expensive work in it.

    View full-size slide