Skip to content

Latest commit

 

History

History
343 lines (236 loc) · 12.5 KB

Reference.md

File metadata and controls

343 lines (236 loc) · 12.5 KB

Reference

Table of Contents


Module Format Reference

Source Layouts

The modules that swift build creates are determined from the filesystem layout of your source files.

For example, if you create a directory with the following layout:

example/
example/Sources/bar.swift
example/Sources/baz.swift

this defines a single module (named after the package name from `Package.swift).

To create multiple modules, you can create multiple subdirectories:

example/Sources/Foo/Widget.swift
example/Sources/Bar/Bazzer.swift

which would define two modules, Foo and Bar.

To generate an executable module (instead of a library module) add a main.swift file to that module’s subdirectory:

example/Sources/Foo/main.swift

and swift build will now produce an:

  • example/.build/debug/Foo

executable output file.

Test Suite Layouts

The package manager supports laying out test sources following a similar convention as primary sources:

example/Tests/FooTests/WidgetTests.swift

defined a FooTests test module. By convention, when there is a sources module Foo and a matching tests module FooTests, the package manager will establish an implicit dependency between the test module and the target it assumes it is trying to test.

On Linux, the XCTest testing framework does not support dynamic discovery of tests. Instead, packages which are intended for use on Linux should include an:

example/Tests/LinuxMain.swift

file which imports all of the individual test modules in the package, and then invokes XCTest.XCTMain passing it the list of all tests.

Other Rules

  • Tests or any other subdirectory can be excluded via Manifest file.
  • Subdirectories of a directory named Sources, Source, srcs or src in the root directory become modules.
  • It is acceptable to have no Sources directory, in which case the root directory is treated as a single module (place your sources there) or sub directories of the root are considered modules. Use this layout convention for simple projects.

Package Manifest File Format Reference

Instructions for how to build a package are provided by the Package.swift manifest file. Package.swift is a Swift file defining a single Package object. This object is configured via the APIs defined in the PackageDescription Swift module supplied with the Swift Package Manager.

Package Declaration

Every Package.swift file should follow the following format:

import PackageDescription

/// The package description.
let package = Package(/* ... */)

// ... subsequent package configuration APIs can be used here to further
// configure the package ...

Conceptually, the description defined by the Package.swift file is combined with the information on the package derived from the filesystem conventions described previously.

Package

Package(
    name: String,
    pkgConfig: String? = nil,
    providers: [SystemPackageProvider]? = nil,
    targets: [Target] = [],
    dependencies: [Package.Dependency] = [],
    exclude: [String] = []
)

- name: The name of the package.
- pkgConfig: Name of the pkg-config (.pc) file to get the additional flags for system modules.
- providers: Defines hints to display for installing system modules.
- targets: Additional information on each target.
- dependencies: Declare dependencies on external packages.
- exclude: Exclude files and directories from package sources.

Creates a new package instance. There should only be one package declared per manifest. The parameters here supply the package description and are documented in further detail below.

name

import PackageDescription

let package = Package(
    name: "FooBar"
)

This is the minimal requirement for a manifest to be valid. When the sources are located directly under Sources/ directory, there is only one module and the module name will be the same as the package name.

targets

The targets property is required when you have more than one module in your package and need to declare a dependency between them.

import PackageDescription

let package = Package(
    name: "Hello",
    targets: [
        Target(name: "Bar", dependencies: ["Foo"]),
    ]
)

The name identifies which target (or module) the information is being associated with, and the list of dependencies specifies the names of other targets in the same package which must be built before that target. In the example here, Foo and Bar are modules present under Sources/ directory, and a dependency is being establish on Foo from Bar. This will cause the Foo module to be built before Bar module so that it can be imported:

NOTE: It is also possible to declare target dependencies between a test and regular module.

dependencies

This is the list of packages that the current package depends on and information about the required versions. You can specify a URL (or local path) to any valid Swift package.

import PackageDescription

let package = Package(
    name: "Example",
    dependencies: [
        .Package(url: "ssh://[email protected]/Greeter.git", versions: Version(1,0,0)..<Version(2,0,0)),
        .Package(url: "../StringExtensions", "1.0.0"),
        .Package(url: "https://github.com/MyAwesomePackage", majorVersion: 1, minor: 4),
    ]
)

This is a list of Package.Dependency instances, see Package Dependency for available options.

exclude

Use this property to exclude files and directories from the package sources.

Every item specifies a relative path from the root of the package.

let package = Package(
    name: "Foo",
    exclude: ["Sources/Fixtures", "Sources/readme.md", "Tests/FooTests/images"]
)

This is helpful when you want to place files like resources or fixtures that should not be considered by the convention system as possible sources.

pkgConfig

This property should only be used for System Module Packages. It defines the name of the pkg-config (.pc) file that should be searched and read to get the additional flags like include search path, linker search path, system libraries to link etc.

import PackageDescription

let package = Package(
    name: "CGtk3",
    pkgConfig: "gtk+-3.0"
)

Here gtk+-3.0.pc will be searched in standard locations for the current system. Users can provide their own paths for location of pc files using the environment variable, PKG_CONFIG_PATH, which will be searched before the standard locations.

NOTE: This feature does not require pkg-config to be installed. However, if installed it will used to find additional platform specific pc filelocations which might be unknown to SwiftPM.

providers

This property should only be used for system module packages. It can be used to provide hints for other users to install a System Module using a system package manager like homebrew, apt-get etc.

NOTE: SwiftPM will never execute the command and only suggest the users to run it.

import PackageDescription

let package = Package(
    name: "CGtk3",
    pkgConfig: "gtk+-3.0",
    providers: [
        .Brew("gtk+3"),
        .Apt("gtk3")
    ]
)

In this case if SwiftPM determines that GTK 3 package is not installed, it will output an appropriate hint depending on which platform the user is on i.e. macOS, Ubuntu, etc.

Package Dependency

A Package.Dependency represents the location and and required version information of an external dependency. The version range controls what versions of a package dependency are expected to work with the current package. When the package manager is fetching the complete set of packages required to build a package, it considers all of the version range specifications from all of the packages in order to select appropriate versions.

.Package(url: String, versions: Range<Version>)

- url: URL or local path to a Package.
- versions: The range of versions which are required.

.Package(url: String, versions: ClosedRange<Version>)

- url: URL or local path to a Package.
- versions: The closed range of versions which are required.

.Package(url: String, majorVersion: Int)

- url: URL or local path to a Package.
- majorVersion: The major version which is required.

This is a short-hand form for specifying a range including all versions of a major version, and is the recommended way for specifying a dependency following the semantic versioning standard.

.Package(url: String, majorVersion: Int, minor: Int)

- url: URL or local path to a Package.
- majorVersion: Major version to consider.
- minor: Minor version to consider.

As for the prior API, this is a short-hand form for specifying a range that inclues all versions of a major and minor version.

.Package(url: String, _ version: Version)

- url: URL or local path to a Package.
- version: The exact Version which is required.

Version

A struct representing a semantic version.

Version(
	_ major: Int,
	_ minor: Int,
	_ patch: Int,
	prereleaseIdentifiers: [String] = [],
	buildMetadataIdentifier: String? = nil
)

- major: The major version, incremented when you make incompatible API changes.
- minor: The minor version, incremented when you add functionality in a backwards-compatible manner.
- patch: The patch version, incremented when you make backwards-compatible bug fixes.
- prereleaseIdentifiers: Used to denote a pre-released version for eg: alpha, beta, etc.
- buildMetadataIdentifier: Optional build meta data for eg: timestamp, hash, etc.

A Version struct can be initialized using a string literal in following format:

"major.minor.patch[-prereleaseIdentifiers][+buildMetadata]"

where prereleaseIdentifiers and buildMetadata are optional. NOTE: prereleaseIdentifiers are separated by dot (.).

Customizing Builds

Using Swift as the format for the manifest allows for powerful customization, for example:

import PackageDescription

var package = Package(name: "Example")

#if os(Linux)
let target = Target(name: "LinuxSources/foo")
package.targets.append(target)
#endif

With a standard configuration file format like JSON such a feature would result in a dictionary structure with increasing complexity for every such feature.

Build Configurations

SwiftPM allows two build configurations: Debug (default) and Release.

Debug

By default, running swift build will build in debug configuration. Alternatively, you can also use swift build -c debug. The build artifacts are located in directory called debug under build folder.
A Swift target is built with following flags in debug mode:

  • -Onone: Compile without any optimization.
  • -g: Generate debug information.
  • -enable-testing: Enable Swift compiler's testability feature.

A C language target is build with following flags in debug mode:

  • -O0: Compile without any optimization.
  • -g: Generate debug information.

Release

To build in release mode, type: swift build -c release. The build artifacts are located in directory called release under build folder.
A Swift target is built with following flags in release mode:

  • -O: Compile with optimizations.
  • -whole-module-optimization: Optimize input files (per module) together instead of individually.

A C language target is build with following flags in release mode:

  • -O2: Compile with optimizations.

Depending on Apple Modules

At this time there is no explicit support for depending on Foundation, AppKit, etc, though importing these modules should work if they are present in the proper system location. We will add explicit support for system dependencies in the future. Note that at this time the Package Manager has no support for iOS, watchOS, or tvOS platforms.