diff --git a/Documentation/Development.md b/Documentation/Development.md
index 76f152e6ffb..442e8a7a40e 100644
--- a/Documentation/Development.md
+++ b/Documentation/Development.md
@@ -63,6 +63,8 @@ using a [snapshot](https://swift.org/download/#releases) from swift.org.
$ cd swiftpm
$ Utilities/bootstrap
```
+
+ Note: The bootstrap script requires having [CMake](https://cmake.org/) and [Ninja](https://ninja-build.org/) installed. Please refer to the [Swift project repo](https://github.com/apple/swift/blob/master/README.md#macos) for installation instructions.
This command will build the Package Manager inside `.build/` directory.
Run the bootstrap script to rebuild after making a change to the source
diff --git a/Documentation/PackageDescription.md b/Documentation/PackageDescription.md
new file mode 100644
index 00000000000..668cf1bd6eb
--- /dev/null
+++ b/Documentation/PackageDescription.md
@@ -0,0 +1,837 @@
+# Package
+
+The `Package` type is used to configure the name, products, targets,
+dependencies and various other parts of the package.
+
+By convention, the properties of a `Package` are defined in a single nested
+initializer statement, and not modified after initialization. For example:
+
+```swift
+// swift-tools-version:5.0
+import PackageDescription
+
+let package = Package(
+ name: "MyLibrary",
+ platforms: [
+ .macOS(.v10_14),
+ ],
+ products: [
+ .library(name: "MyLibrary", targets: ["MyLibrary"]),
+ ],
+ dependencies: [
+ .package(url: "https://url/of/another/package/named/Utility", from: "1.0.0"),
+ ],
+ targets: [
+ .target(name: "MyLibrary", dependencies: ["Utility"]),
+ .testTarget(name: "MyLibraryTests", dependencies: ["MyLibrary"]),
+ ]
+)
+```
+
+### Methods
+
+Package(
+ name: String,
+ platforms: [SupportedPlatform]? = nil,
+ products: [Product] = [],
+ dependencies: [Package.Dependency] = [],
+ targets: [Target] = [],
+ swiftLanguageVersions: [SwiftVersion]? = nil,
+ cLanguageStandard: CLanguageStandard? = nil,
+ cxxLanguageStandard: CXXLanguageStandard? = nil
+)
+
+
+### About the Swift Tools Version
+
+A Package.swift manifest file must begin with the string `//
+swift-tools-version:` followed by a version number specifier.
+
+Examples:
+
+ // swift-tools-version:3.0.2
+ // swift-tools-version:3.1
+ // swift-tools-version:4.0
+ // swift-tools-version:5.0
+
+The Swift tools version declares the version of the `PackageDescription`
+library, the minimum version of the Swift tools and Swift language
+compatibility version to process the manifest, and the minimum version of the
+Swift tools that are needed to use the Swift package. Each version of Swift
+can introduce updates to the `PackageDescription` library, but the previous
+API version will continue to be available to packages which declare a prior
+tools version. This behavior lets you take advantage of new releases of
+Swift, the Swift tools, and the `PackageDescription` library, without having
+to update your package's manifest or losing access to existing packages.
+
+# SupportedPlatform
+
+Represents a platform supported by the package.
+
+By default, the Swift Package Manager assigns a predefined minimum deployment
+version for each supported platforms unless configured using the `platforms`
+API. This predefined deployment version will be the oldest deployment target
+version supported by the installed SDK for a given platform. One exception
+to this rule is macOS, for which the minimum deployment target version will
+start from 10.10. Packages can choose to configure the minimum deployment
+target version for a platform by using the APIs defined in this struct. The
+Swift Package Manager will emit appropriate errors when an invalid value is
+provided for supported platforms, i.e., an empty array, multiple declarations
+for the same platform or an invalid version specification.
+
+The Swift Package Manager will emit an error if a dependency is not
+compatible with the top-level package's deployment version; the deployment
+target of dependencies must be lower than or equal to top-level package's
+deployment target version for a particular platform.
+
+### Methods
+
+```swift
+/// Configure the minimum deployment target version for the macOS platform.
+///
+/// - Since: First available in PackageDescription 5.0
+///
+/// - Parameter version: The minimum deployment target that the package supports.
+static func macOS(_ version: SupportedPlatform.MacOSVersion) -> SupportedPlatform
+
+/// Configure the minimum deployment target version for the macOS platform
+/// using a custom version string.
+///
+/// The version string must be a series of 2 or 3 dot-separated integers, for
+/// example "10.10" or "10.10.1".
+///
+/// - Since: First available in PackageDescription 5.0
+///
+/// - Parameter versionString: The minimum deployment target as a string representation of 2 or 3 dot-separated integers, e.g. "10.10.1".
+static func macOS(_ versionString: String) -> SupportedPlatform
+
+/// Configure the minimum deployment target version for the iOS platform.
+///
+/// - Since: First available in PackageDescription 5.0
+///
+/// - Parameter version: The minimum deployment target that the package supports.
+static func iOS(_ version: SupportedPlatform.IOSVersion) -> SupportedPlatform
+
+/// Configure the minimum deployment target version for the iOS platform
+/// using a custom version string.
+///
+/// The version string must be a series of 2 or 3 dot-separated integers, for
+/// example "8.0" or "8.0.1".
+///
+/// - Since: First available in PackageDescription 5.0
+///
+/// - Parameter versionString: The minimum deployment target as a string representation of 2 or 3 dot-separated integers, e.g. "8.0.1".
+static func iOS(_ versionString: String) -> SupportedPlatform
+
+/// Configure the minimum deployment target version for the tvOS platform.
+///
+/// - Since: First available in PackageDescription 5.0
+///
+/// - Parameter version: The minimum deployment target that the package supports.
+static func tvOS(_ version: SupportedPlatform.TVOSVersion) -> SupportedPlatform
+
+/// Configure the minimum deployment target version for the tvOS platform
+/// using a custom version string.
+///
+/// The version string must be a series of 2 or 3 dot-separated integers, for
+/// example "9.0" or "9.0.1".
+///
+/// - Since: First available in PackageDescription 5.0
+///
+/// - Parameter versionString: The minimum deployment target as a string representation of 2 or 3 dot-separated integers, e.g. "9.0.1".
+static func tvOS(_ versionString: String) -> SupportedPlatform
+
+/// Configure the minimum deployment target version for the watchOS platform.
+///
+/// - Since: First available in PackageDescription 5.0
+///
+/// - Parameter version: The minimum deployment target that the package supports.
+static func watchOS(_ version: SupportedPlatform.WatchOSVersion) -> SupportedPlatform
+
+/// Configure the minimum deployment target version for the watchOS platform
+/// using a custom version string.
+///
+/// The version string must be a series of 2 or 3 dot-separated integers, for
+/// example "2.0" or "2.0.1".
+///
+/// - Since: First available in PackageDescription 5.0
+///
+/// - Parameter versionString: The minimum deployment target as a string representation of 2 or 3 dot-separated integers, e.g. "3.0.1".
+static func watchOS(_ versionString: String) -> SupportedPlatform
+```
+
+# Product
+
+Defines a package product.
+
+A package product defines an externally visible build artifact that is
+available to clients of a package. The product is assembled from the build
+artifacts of one or more of the package's targets.
+
+A package product can be one of two types:
+
+1. Library
+
+ A library product is used to vend library targets containing the public
+ APIs that will be available to clients.
+
+2. Executable
+
+ An executable product is used to vend an executable target. This should
+ only be used if the executable needs to be made available to clients.
+
+The following example shows a package manifest for a library called "Paper"
+that defines multiple products:
+
+```swift
+let package = Package(
+ name: "Paper",
+ products: [
+ .executable(name: "tool", targets: ["tool"]),
+ .library(name: "Paper", targets: ["Paper"]),
+ .library(name: "PaperStatic", type: .static, targets: ["Paper"]),
+ .library(name: "PaperDynamic", type: .dynamic, targets: ["Paper"]),
+ ],
+ dependencies: [
+ .package(url: "http://example.com.com/ExamplePackage/ExamplePackage", from: "1.2.3"),
+ .package(url: "http://some/other/lib", .exact("1.2.3")),
+ ],
+ targets: [
+ .target(
+ name: "tool",
+ dependencies: [
+ "Paper",
+ "ExamplePackage"
+ ]),
+ .target(
+ name: "Paper",
+ dependencies: [
+ "Basic",
+ .target(name: "Utility"),
+ .product(name: "AnotherExamplePackage"),
+ ])
+ ]
+)
+```
+
+### Methods
+
+```swift
+/// Create a library product that can be used by clients that depend on this package.
+///
+/// A library's product can either be statically or dynamically linked. It
+/// is recommended to not declare the type of library explicitly to let the
+/// Swift Package Manager choose between static or dynamic linking depending
+/// on the consumer of the package.
+///
+/// - Parameters:
+/// - name: The name of the library product.
+/// - type: The optional type of the library that is used to determine how to link to the library.
+/// Leave this parameter unspecified to let to let the Swift Package Manager choose between static or dynamic linking (recommended).
+/// If you do not support both linkage types, use `.static` or `.dynamic` for this parameter.
+/// - targets: The targets that are bundled into a library product.
+public static func library(
+ name: String,
+ type: Product.Library.LibraryType? = nil,
+ targets: [String]
+) -> Product
+
+/// Create an executable product.
+///
+/// - Parameters:
+/// - name: The name of the executable product.
+/// - targets: The targets that are bundled into an executable product.
+public static func executable(name: String, targets: [String]) -> Product
+```
+
+# Package Dependency
+
+A package dependency consists of a Git URL to the source of the package,
+and a requirement for the version of the package that can be used.
+
+The Swift Package Manager performs a process called dependency resolution to
+figure out the exact version of the package dependencies that can be used in
+your package. The results of the dependency resolution are recorded in the
+`Package.resolved` file which will be placed in the top-level directory of
+your package.
+
+### Methods
+
+```swift
+/// Add a package dependency that is required from the given minimum version,
+/// going up to the next major version.
+///
+/// This is the recommend way to specify a remote package dependency because
+/// it allows you to specify the minimum version you require and gives
+/// explicit opt-in for new major versions, but otherwise provides maximal
+/// flexibility on which version is used. This helps to prevent conflicts in
+/// your package dependency graph.
+///
+/// For example, specifying
+///
+/// .package(url: "https://example.com/example-package.git", from: "1.2.3"),
+///
+/// will allow the Swift package manager to select a version like a "1.2.3",
+/// "1.2.4" or "1.3.0" but not "2.0.0".
+///
+/// - Parameters:
+/// - url: The valid Git URL of the package.
+/// - version: The minimum version requirement.
+public static func package(url: String, from version: Version) -> Package.Dependency
+
+/// Add a remote package dependency given a version requirement.
+///
+/// - Parameters:
+/// - url: The valid Git URL of the package.
+/// - requirement: A dependency requirement. See static methods on `Package.Dependency.Requirement` for available options.
+public static func package(url: String, _ requirement: Package.Dependency.Requirement) -> Package.Dependency
+
+///
+/// For example
+///
+/// .package(url: "https://example.com/example-package.git", "1.2.3"..<"1.2.6"),
+///
+/// will allow the Swift package manager to pick versions 1.2.3, 1.2.4, 1.2.5, but not 1.2.6.
+///
+/// - Parameters:
+/// - url: The valid Git URL of the package.
+/// - range: The custom version range requirement.
+public static func package(url: String, _ range: Range) -> Package.Dependency
+
+/// Add a package dependency starting with a specific minimum version, going
+/// up to and including a specific maximum version.
+///
+/// For example
+///
+/// .package(url: "https://example.com/example-package.git", "1.2.3"..."1.2.6"),
+///
+/// will allow the Swift package manager to pick versions 1.2.3, 1.2.4, 1.2.5, as well as 1.2.6.
+///
+/// - Parameters:
+/// - url: The valid Git URL of the package.
+/// - range: The closed version range requirement.
+public static func package(url: String, _ range: ClosedRange) -> Package.Dependency
+
+/// Add a dependency to a local package on the filesystem.
+///
+/// The package dependency is used as-is and no source control access is
+/// performed. Local package dependencies are especially useful during
+/// development of a new package or when working on multiple tightly-coupled
+/// packages.
+///
+/// - Parameter path: The path of the package.
+public static func package(path: String) -> Package.Dependency
+```
+
+# Package Dependency Requirement
+`enum Package.Dependency.Requirement`
+
+The dependency requirement can be defined as one of three different version requirements:
+
+1. Version-based Requirement
+
+ A requirement which restricts what version of a dependency your
+ package can use based on its available versions. When a new package
+ version is published, it should increment the major version component
+ if it has backwards-incompatible changes. It should increment the
+ minor version component if it adds new functionality in
+ a backwards-compatible manner. And it should increment the patch
+ version if it makes backwards-compatible bugfixes. To learn more about
+ the syntax of semantic versioning syntax, see `Version` or visit
+ https://semver.org (https://semver.org/).
+
+2. Branch-based Requirement
+
+ Specify the name of a branch that a dependency will follow. This is
+ useful when developing multiple packages which are closely related,
+ allowing you to keep them in sync during development. Note that
+ packages which use branch-based dependency requirements cannot be
+ depended-upon by packages which use version-based dependency
+ requirements; you should remove branch-based dependency requirements
+ before publishing a version of your package.
+
+3. Commit-based Requirement
+
+ A requirement that restricts a dependency to a specific commit
+ hash. This is useful if you want to pin your package to a specific
+ commit hash of a dependency. Note that packages which use
+ commit-based dependency requirements cannot be depended-upon by
+ packages which use version-based dependency requirements; you
+ should remove commit-based dependency requirements before
+ publishing a version of your package.
+
+### Methods
+
+```swift
+/// Returns a requirement for the given exact version.
+///
+/// Specifying exact version requirements are usually not recommended, as
+/// they can cause conflicts in your package dependency graph when a package
+/// is depended on by multiple other packages.
+///
+/// Example:
+///
+/// .exact("1.2.3")
+///
+/// - Parameters:
+/// - version: The exact version to be specified.
+public static func exact(_ version: Version) -> Package.Dependency.Requirement
+
+/// Returns a requirement for a source control revision. This is usually
+/// specified with the hash of a commit.
+///
+/// Note that packages which use commit-based dependency requirements
+/// cannot be depended-upon by packages which use version-based dependency
+/// requirements; you should remove commit-based dependency requirements
+/// before publishing a version of your package.
+///
+/// Example:
+///
+/// .revision("e74b07278b926c9ec6f9643455ea00d1ce04a021")
+///
+/// - Parameters:
+/// - ref: The Git revision, usually a hash of the commit.
+public static func revision(_ ref: String) -> Package.Dependency.Requirement
+
+/// Returns a requirement for a source control branch.
+///
+/// Note that packages which use branch-based dependency requirements
+/// cannot be depended-upon by packages which use version-based dependency
+/// requirements; you should remove branch-based dependency requirements
+/// before publishing a version of your package.
+///
+/// Example:
+///
+/// .branch("develop")
+///
+/// - Parameters:
+/// - name: The name of the branch.
+public static func branch(_ name: String) -> Package.Dependency.Requirement
+
+/// Returns a requirement for a version range, starting at the given minimum
+/// version and going up to the next major version.
+///
+/// - Parameters:
+/// - version: The minimum version for the version range.
+public static func upToNextMajor(from version: Version) -> Package.Dependency.Requirement
+
+/// Returns a requirement for a version range, starting at the given minimum
+/// version and going up to the next minor version.
+///
+/// - Parameters:
+/// - version: The minimum version for the version range.
+public static func upToNextMinor(from version: Version) -> Package.Dependency.Requirement
+```
+
+# Version
+
+A struct representing a Semantic Version.
+
+Semantic versioning is a specification that proposes a set of rules and
+requirements that dictate how version numbers are assigned and incremented.
+To learn more about the semantic versioning specification, visit
+www.semver.org.
+
+### Semantic Versioning (SemVer) 2.0.0
+
+#### The Major Version
+
+The major version signifies breaking changes to the API which requires
+updating existing clients. For example, renaming an existing type, removing
+a method or changing a method’s signature are considered breaking changes.
+This also includes any backwards incompatible bugfixes or behaviour changes
+of existing API.
+
+#### The Minor Version
+
+Update the minor version if functionality is added in a backward compatible
+manner. For example, adding a new method or type without changing any other
+API is considered backward-compatible.
+
+#### The Patch Version
+
+Increase the patch version if you are making a backward-compatible bugfix.
+This allows clients to benefit from bugfixes to your package without
+incurring any maintenance burden.
+
+# Target
+
+Targets are the basic building blocks of a package.
+
+Each target contains a set of source files that are compiled into a module or
+test suite. Targets can be vended to other packages by defining products that
+include them.
+
+Targets may depend on targets within the same package and on products vended
+by its package dependencies.
+
+### Methods
+
+```swift
+/// Create a library or executable target.
+///
+/// A target can either contain Swift or C-family source files. You cannot
+/// mix Swift and C-family source files within a target. A target is
+/// considered to be an executable target if there is a `main.swift`,
+/// `main.m`, `main.c` or `main.cpp` file in the target's directory. All
+/// other targets are considered to be library targets.
+///
+/// - Parameters:
+/// - name: The name of the target.
+/// - dependencies: The dependencies of the target. These can either be other targets in the package or products from package dependencies.
+/// - path: The custom path for the target. By default, targets will be looked up in the /Sources/ directory.
+/// Do not escape the package root, i.e. values like "../Foo" or "/Foo" are invalid.
+/// - exclude: A list of paths to exclude from being considered source files. This path is relative to the target's directory.
+/// - sources: An explicit list of source files.
+/// - publicHeadersPath: The directory containing public headers of a C-family family library target.
+/// - cSettings: The C settings for this target.
+/// - cxxSettings: The C++ settings for this target.
+/// - swiftSettings: The Swift settings for this target.
+/// - linkerSettings: The linker settings for this target.
+public static func target(
+ name: String,
+ dependencies: [Target.Dependency] = [],
+ path: String? = nil,
+ exclude: [String] = [],
+ sources: [String]? = nil,
+ publicHeadersPath: String? = nil,
+ cSettings: [CSetting]? = nil,
+ cxxSettings: [CXXSetting]? = nil,
+ swiftSettings: [SwiftSetting]? = nil,
+ linkerSettings: [LinkerSetting]? = nil
+) -> Target
+
+/// Create a test target.
+///
+/// Test targets are written using the XCTest testing framework. Test targets
+/// generally declare target dependency on the targets they test.
+///
+/// - Parameters:
+/// - name: The name of the target.
+/// - dependencies: The dependencies of the target. These can either be other targets in the package or products from other packages.
+/// - path: The custom path for the target. By default, targets will be looked up in the /Sources/ directory.
+/// Do not escape the package root, i.e. values like "../Foo" or "/Foo" are invalid.
+/// - exclude: A list of paths to exclude from being considered source files. This path is relative to the target's directory.
+/// - sources: An explicit list of source files.
+/// - cSettings: The C settings for this target.
+/// - cxxSettings: The C++ settings for this target.
+/// - swiftSettings: The Swift settings for this target.
+/// - linkerSettings: The linker settings for this target.
+public static func testTarget(
+ name: String,
+ dependencies: [Target.Dependency] = [],
+ path: String? = nil,
+ exclude: [String] = [],
+ sources: [String]? = nil,
+ cSettings: [CSetting]? = nil,
+ cxxSettings: [CXXSetting]? = nil,
+ swiftSettings: [SwiftSetting]? = nil,
+ linkerSettings: [LinkerSetting]? = nil
+) -> Target
+
+/// Create a system library target.
+///
+/// System library targets are used to adapt a library installed on the system to
+/// work with Swift packages. Such libraries are generally installed by system
+/// package managers (such as Homebrew and APT) and exposed to Swift packages by
+/// providing a modulemap file along with other metadata such as the library's
+/// pkg-config name.
+///
+/// - Parameters:
+/// - name: The name of the target.
+/// - path: The custom path for the target. By default, targets will be looked up in the /Sources/ directory.
+/// Do not escape the package root, i.e. values like "../Foo" or "/Foo" are invalid.
+/// - pkgConfig: The name of the pkg-config file for this system library.
+/// - providers: The providers for this system library.
+public static func systemLibrary(
+ name: String,
+ path: String? = nil,
+ pkgConfig: String? = nil,
+ providers: [SystemPackageProvider]? = nil
+) -> Target
+```
+
+# Target Dependency
+`class Target.Dependency`
+
+Represents dependency on other targets in the package or products from other packages.
+
+```swift
+/// A dependency on a target in the same package.
+public static func target(name: String) -> Target.Dependency
+
+/// A dependency on a product from a package dependency.
+public static func product(name: String, package: String? = nil) -> Target.Dependency
+
+// A by-name dependency that resolves to either a target or a product,
+// as above, after the package graph has been loaded.
+public static func byName(name: String) -> Target.Dependency
+```
+
+# CSetting
+
+A C-language build setting.
+
+### Methods
+
+```swift
+/// Provide a header search path relative to the target's directory.
+///
+/// Use this setting to add a search path for headers within your target.
+/// Absolute paths are disallowed and this setting can't be used to provide
+/// headers that are visible to other targets.
+///
+/// The path must be a directory inside the package.
+///
+/// - Since: First available in PackageDescription 5.0
+///
+/// - Parameters:
+/// - path: The path of the directory that should be searched for headers. The path is relative to the target's directory.
+/// - condition: A condition which will restrict when the build setting applies.
+public static func headerSearchPath(_ path: String, _ condition: BuildSettingCondition? = nil) -> CSetting
+
+/// Defines a value for a macro. If no value is specified, the macro value will
+/// be defined as 1.
+///
+/// - Since: First available in PackageDescription 5.0
+///
+/// - Parameters:
+/// - name: The name of the macro.
+/// - value: The value of the macro.
+/// - condition: A condition which will restrict when the build setting applies.
+public static func define(_ name: String, to value: String? = nil, _ condition: BuildSettingCondition? = nil) -> CSetting
+
+/// Set unsafe flags to pass arbitrary command-line flags to the corresponding build tool.
+///
+/// As the usage of the word "unsafe" implies, the Swift Package Manager
+/// can't safely determine if the build flags will have any negative
+/// side-effect to the build since certain flags can change the behavior of
+/// how a build is performed.
+///
+/// As some build flags could be exploited for unsupported or malicious
+/// behavior, the use of unsafe flags make the products containing this
+/// target ineligible to be used by other packages.
+///
+/// - Since: First available in PackageDescription 5.0
+///
+/// - Parameters:
+/// - flags: The flags to set.
+/// - condition: A condition which will restrict when the build setting applies.
+public static func unsafeFlags(_ flags: [String], _ condition: BuildSettingCondition? = nil) -> CSetting
+```
+
+# CXXSetting
+
+A CXX-language build setting.
+
+### Methods
+
+```swift
+/// Provide a header search path relative to the target's root directory.
+///
+/// Use this setting to add a search path for headers within your target.
+/// Absolute paths are disallowed and this setting can't be used to provide
+/// headers that are visible to other targets.
+///
+/// The path must be a directory inside the package.
+///
+/// - Since: First available in PackageDescription 5.0
+///
+/// - Parameters:
+/// - path: The path of the directory that should be searched for headers. The path is relative to the target's directory.
+/// - condition: A condition which will restrict when the build setting applies.
+public static func headerSearchPath(_ path: String, _ condition: BuildSettingCondition? = nil) -> CXXSetting
+
+/// Defines a value for a macro. If no value is specified, the macro value will
+/// be defined as 1.
+///
+/// - Since: First available in PackageDescription 5.0
+///
+/// - Parameters:
+/// - name: The name of the macro.
+/// - value: The value of the macro.
+/// - condition: A condition which will restrict when the build setting applies.
+public static func define(_ name: String, to value: String? = nil, _ condition: BuildSettingCondition? = nil) -> CXXSetting
+
+/// Set unsafe flags to pass arbitrary command-line flags to the corresponding build tool.
+///
+/// As the usage of the word "unsafe" implies, the Swift Package Manager
+/// can't safely determine if the build flags will have any negative
+/// side-effect to the build since certain flags can change the behavior of
+/// how a build is performed.
+///
+/// As some build flags could be exploited for unsupported or malicious
+/// behavior, the use of unsafe flags make the products containing this
+/// target ineligible to be used by other packages.
+///
+/// - Since: First available in PackageDescription 5.0
+///
+/// - Parameters:
+/// - flags: The flags to set.
+/// - condition: A condition which will restrict when the build setting applies.
+public static func unsafeFlags(_ flags: [String], _ condition: BuildSettingCondition? = nil) -> CXXSetting
+```
+
+# SwiftSetting
+
+A Swift language build setting.
+
+### Methods
+
+```swift
+/// Define a compilation condition.
+///
+/// Compilation conditons are used inside to conditionally compile
+/// statements. For example, the Swift compiler will only compile the
+/// statements inside the `#if` block when `ENABLE_SOMETHING` is defined:
+///
+/// #if ENABLE_SOMETHING
+/// ...
+/// #endif
+///
+/// Unlike macros in C/C++, compilation conditions don't have an
+/// associated value.
+///
+/// - Since: First available in PackageDescription 5.0
+///
+/// - Parameters:
+/// - name: The name of the macro.
+/// - condition: A condition which will restrict when the build setting applies.
+public static func define(_ name: String, _ condition: BuildSettingCondition? = nil) -> SwiftSetting
+
+/// Set unsafe flags to pass arbitrary command-line flags to the corresponding build tool.
+///
+/// As the usage of the word "unsafe" implies, the Swift Package Manager
+/// can't safely determine if the build flags will have any negative
+/// side-effect to the build since certain flags can change the behavior of
+/// how a build is performed.
+///
+/// As some build flags could be exploited for unsupported or malicious
+/// behavior, the use of unsafe flags make the products containing this
+/// target ineligible to be used by other packages.
+///
+/// - Since: First available in PackageDescription 5.0
+///
+/// - Parameters:
+/// - flags: The flags to set.
+/// - condition: A condition which will restrict when the build setting applies.
+public static func unsafeFlags(_ flags: [String], _ condition: BuildSettingCondition? = nil) -> SwiftSetting
+```
+
+# LinkerSetting
+
+A linker build setting.
+
+### Methods
+
+```swift
+/// Declare linkage to a system library.
+///
+/// This setting is most useful when the library can't be linked
+/// automatically (for example, C++ based libraries and non-modular
+/// libraries).
+///
+/// - Since: First available in PackageDescription 5.0
+///
+/// - Parameters:
+/// - library: The library name.
+/// - condition: A condition which will restrict when the build setting applies.
+public static func linkedLibrary(_ library: String, _ condition: BuildSettingCondition? = nil) -> LinkerSetting
+
+/// Declare linkage to a framework.
+///
+/// This setting is most useful when the framework can't be linked
+/// automatically (for example, C++ based frameworks and non-modular
+/// frameworks).
+///
+/// - Since: First available in PackageDescription 5.0
+///
+/// - Parameters:
+/// - framework: The framework name.
+/// - condition: A condition which will restrict when the build setting applies.
+public static func linkedFramework(_ framework: String, _ condition: BuildSettingCondition? = nil) -> LinkerSetting
+
+/// Set unsafe flags to pass arbitrary command-line flags to the corresponding build tool.
+///
+/// As the usage of the word "unsafe" implies, the Swift Package Manager
+/// can't safely determine if the build flags will have any negative
+/// side-effect to the build since certain flags can change the behavior of
+/// how a build is performed.
+///
+/// As some build flags could be exploited for unsupported or malicious
+/// behavior, the use of unsafe flags make the products containing this
+/// target ineligible to be used by other packages.
+///
+/// - Since: First available in PackageDescription 5.0
+///
+/// - Parameters:
+/// - flags: The flags to set.
+/// - condition: A condition which will restrict when the build setting applies.
+public static func unsafeFlags(_ flags: [String], _ condition: BuildSettingCondition? = nil) -> LinkerSetting
+```
+
+# SwiftVersion
+
+Represents the version of the Swift language that should be used for compiling
+Swift sources in the package.
+
+```swift
+public enum SwiftVersion {
+
+ @available(_PackageDescription, introduced: 4, obsoleted: 5)
+ case v3
+
+ @available(_PackageDescription, introduced: 4)
+ case v4
+
+ @available(_PackageDescription, introduced: 4)
+ case v4_2
+
+ @available(_PackageDescription, introduced: 5)
+ case v5
+
+ /// User-defined value of Swift version.
+ ///
+ /// The value is passed as-is to Swift compiler's `-swift-version` flag.
+ case version(String)
+}
+```
+
+# CLanguageStandard
+
+Supported C language standards.
+
+```swift
+public enum CLanguageStandard {
+ case c89
+ case c90
+ case iso9899_1990
+ case iso9899_199409
+ case gnu89
+ case gnu90
+ case c99
+ case iso9899_1999
+ case gnu99
+ case c11
+ case iso9899_2011
+ case gnu11
+}
+```
+# CXXLanguageStandard
+
+Supported C++ language standards.
+
+```swift
+public enum CXXLanguageStandard {
+ case cxx98 = "c++98"
+ case cxx03 = "c++03"
+ case gnucxx98 = "gnu++98"
+ case gnucxx03 = "gnu++03"
+ case cxx11 = "c++11"
+ case gnucxx11 = "gnu++11"
+ case cxx14 = "c++14"
+ case gnucxx14 = "gnu++14"
+ case cxx1z = "c++1z"
+ case gnucxx1z = "gnu++1z"
+}
+```
diff --git a/Documentation/PackageDescriptionV3.md b/Documentation/PackageDescriptionV3.md
deleted file mode 100644
index c43c1757413..00000000000
--- a/Documentation/PackageDescriptionV3.md
+++ /dev/null
@@ -1,399 +0,0 @@
-# PackageDescription API Version 3
-
-## Table of Contents
-
-* [Overview](README.md)
-* [Usage](Usage.md)
-* [**PackageDescription API Version 3**](PackageDescriptionV3.md)
- * [Target Format Reference](#target-format-reference)
- * [Source Layouts](#source-layouts)
- * [Test Target Layouts](#test-target-layouts)
- * [Other Rules](#other-rules)
- * [Package Manifest File Format Reference](#package-manifest-file-format-reference)
- * [Package Declaration](#package-declaration)
- * [Package](#package)
- * [Package Dependency](#package-dependency)
- * [Version](#version)
-* [PackageDescription API Version 4](PackageDescriptionV4.md)
-* [PackageDescription API Version 4.2](PackageDescriptionV4_2.md)
-* [Resources](Resources.md)
-
----
-
-## Target Format Reference
-
-### Source Layouts
-
-The targets 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 target, named after the package name from
-`Package.swift`.
-
-To create multiple targets, create multiple subdirectories:
-
- example/Sources/Foo/Widget.swift
- example/Sources/Bar/Bazzer.swift
-
-This defines two targets: `Foo` and `Bar`.
-
-To generate an executable target (instead of a library target), add a
-`main.swift` file to that target’s directory:
-
- example/Sources/Foo/main.swift
-
-Running `swift build` will now produce an executable output file: `example/.build/debug/Foo`.
-
-The C language targets are laid out in a similar format. For e.g. a library
-`Baz` can be created with following layout:
-
- example/Sources/Baz/Baz.c
- example/Sources/Baz/include/Baz.h
-
-The public headers for this library go in the directory `include`.
-
-Similarly, an executable C language target `Baz` looks like this:
-
- example/Sources/Baz/main.c
-
-Note: It is possible to have C, C++, Objective-C and Objective-C++ sources as
-part of a C language target. Swift targets can import C language targets but
-not vice versa.
-
-Read more on C language targets [here](Usage.md#c-language-targets).
-
-### Test Target Layouts
-
-The package manager supports laying out test sources following a similar
-convention as primary sources:
-
- example/Tests/FooTests/WidgetTests.swift
-
-This defines a `FooTests` test target. By convention, when there is a target
-`Foo` and a matching test target `FooTests`, the package manager will establish
-an implicit dependency between the test target 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 targets 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](#exclude) via Manifest
- file.
-* Subdirectories of a directory named `Sources`, `Source`, `srcs` or `src` in
- the root directory become target.
-* It is acceptable to have no `Sources` directory, in which case the root
- directory is treated as a single target (place your sources there) or sub
- directories of the root are considered targets. 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 target supplied with the Swift Package Manager.
-
-### Package Declaration
-
-Every `Package.swift` file should follow the following format:
-
-```swift
-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
-
-```swift
-Package(
- name: String,
- pkgConfig: String? = nil,
- providers: [SystemPackageProvider]? = nil,
- targets: [Target] = [],
- dependencies: [Package.Dependency] = [],
- swiftLanguageVersions: [Int]? = nil,
- exclude: [String] = []
-)
-```
-
-\- [name](#name): The name of the package.
-\- [pkgConfig](#pkgconfig): Name of the pkg-config (.pc) file to get the
-additional flags for system modules.
-\- [providers](#providers): Defines hints to display for installing system
-modules.
-\- [targets](#targets): Additional information on each target.
-\- [dependencies](#dependencies): Declare dependencies on external packages.
-\- [swiftLanguageVersions](#swiftlanguageversions): Specifies the set of
-supported Swift language versions.
-\- [exclude](#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
-
-```swift
-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 target and
-the target name will be the same as the package name.
-
-#### 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.
-
-```swift
-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 file locations
-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._
-
-```swift
-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.
-
-#### targets
-
-The targets property is required when you have more than one target in your
-package and need to declare a dependency between them.
-
-```swift
-import PackageDescription
-
-let package = Package(
- name: "Hello",
- targets: [
- Target(name: "Bar", dependencies: ["Foo"]),
- ]
-)
-```
-
-The name identifies which target, 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 targets present under `Sources/` directory, and a dependency is being
-establish on `Foo` from `Bar`. This will cause the `Foo` target to be built
-before `Bar` target so that it can be imported:
-
-_NOTE: It is also possible to declare target dependencies between a test and
-regular target._
-
-#### 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.
-
-```swift
-import PackageDescription
-
-let package = Package(
- name: "Example",
- dependencies: [
- .Package(url: "ssh://git@example.com/Greeter.git", versions: Version(1,0,0)..)
-```
-\- *url*: URL or local path to a Package.
-\- *versions*: The range of [versions](#version) which are required.
-
-```swift
-.Package(url: String, versions: ClosedRange)
-```
-\- *url*: URL or local path to a Package.
-\- *versions*: The closed range of [versions](#version) which are required.
-
-```swift
-.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](http://semver.org) standard.
-
-```swift
-.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.
-
-```swift
-.Package(url: String, _ version: Version)
-```
-\- *url*: URL or local path to a Package.
-\- *version*: The exact [Version](#version) which is required.
-
-## Version
-
-A struct representing a [semantic version](http://semver.org).
-
-```swift
-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:
-
-```swift
-import PackageDescription
-
-var package = Package(name: "Example")
-
-#if os(Linux)
-let target = Target(name: "LinuxSources/foo")
-package.targets.append(target)
-#endif
-```
diff --git a/Documentation/PackageDescriptionV4.md b/Documentation/PackageDescriptionV4.md
deleted file mode 100644
index 67f15c2e5dc..00000000000
--- a/Documentation/PackageDescriptionV4.md
+++ /dev/null
@@ -1,325 +0,0 @@
-# PackageDescription API Version 4
-
-## Table of Contents
-
-* [Overview](README.md)
-* [Usage](Usage.md)
-* [PackageDescription API Version 3](PackageDescriptionV3.md)
-* [**PackageDescription API Version 4**](PackageDescriptionV4.md)
- * [Target Format Reference](#target-format-reference)
- * [Package Manifest File Format Reference](#package-manifest-file-format-reference)
- * [Version](#version)
-* [PackageDescription API Version 4.2](PackageDescriptionV4_2.md)
-* [Resources](Resources.md)
-
----
-
-## Target Format Reference
-
-All targets should be declared in the `Package.swift` manifest file. Unless the
-relative path of the target is declared, the Package Manager will look for
-a directory matching the name of the target in these places:
-
-Regular targets: Sources, Source, src, srcs.
-Test targets: Tests, Sources, Source, src, srcs.
-
-## Package Manifest File Format Reference
-
-### Package
-
-```swift
-Package(
- name: String,
- pkgConfig: String? = nil,
- providers: [SystemPackageProvider]? = nil,
- products: [Product] = [],
- dependencies: [Dependency] = [],
- targets: [Target] = [],
- swiftLanguageVersions: [Int]? = nil
-)
-```
-
-\- [name](#name): The name of the package.
-\- [pkgConfig](#pkgconfig): Name of the pkg-config (.pc) file to get the
-additional flags for system modules.
-\- [providers](#providers): Defines hints to display for installing system
-modules.
-\- [products](#products): The products vended by the package.
-\- [dependencies](#dependencies): The external package dependencies.
-\- [targets](#targets): The list of targets in the package.
-\- [swiftLanguageVersions](#swiftlanguageversions): Specifies the set of
-supported Swift language versions.
-
-#### name
-
-```swift
-import PackageDescription
-
-let package = Package(
- name: "FooBar"
-)
-```
-
-This is the minimal requirement for a manifest to be valid. However, at least
-one target is required to build the package.
-
-#### 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.
-
-```swift
-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 be used to find additional platform specific pc file locations
-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 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 provide suggestions._
-
-```swift
-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.
-
-#### products
-
-This is the list of all the products that are vended by the package. A target is
-available to other packages only if it is a part of some product.
-
-Two types of products are supported:
-
-* library: A library product contains library targets. It should contain the
- targets which are supposed to be used by other packages, i.e. the public API
- of a library package. The library product can be declared static, dynamic
- or automatic. It is recommended to use automatic so the Package Manager can
- decide appropriate linkage.
-
-* executable: An executable product is used to vend an executable target. This
- should only be used if the executable needs to be made available to
- other packages.
-
-Example:
-
-```swift
-let package = Package(
- name: "Paper",
- products: [
- .executable(name: "tool", targets: ["tool"]),
- .library(name: "Paper", targets: ["Paper"]),
- .library(name: "PaperStatic", type: .static, targets: ["Paper"]),
- .library(name: "PaperDynamic", type: .dynamic, targets: ["Paper"]),
- ],
- dependencies: [
- .package(url: "http://github.com/SwiftyJSON/SwiftyJSON", from: "1.2.3"),
- .package(url: "../CHTTPParser", .upToNextMinor(from: "2.2.0")),
- .package(url: "http://some/other/lib", .exact("1.2.3")),
- ],
- targets: [
- .target(
- name: "tool",
- dependencies: [
- "Paper",
- "SwiftyJSON"
- ]),
- .target(
- name: "Paper",
- dependencies: [
- "Basic",
- .target(name: "Utility"),
- .product(name: "CHTTPParser"),
- ])
- ]
-)
-```
-
-#### dependencies
-
-This is the list of packages that the package depends on. You can specify
-a URL (or local path) to any valid Swift package.
-
-```swift
-import PackageDescription
-
-let package = Package(
- name: "Example",
- dependencies: [
- .package(url: "https://github.com/SwiftyJSON/SwiftyJSON.git", from: "1.0.0"),
- ],
- targets: [
- .target(name: "Foo", dependencies: ["SwiftyJSON"]),
- ]
-)
-```
-
-A package dependency represents the location and the 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.
-
-The following options are available for declaring a package dependency:
-
-```swift
-
-// 1.0.0 ..< 2.0.0
-.package(url: "/SwiftyJSON", from: "1.0.0"),
-
-// 1.2.0 ..< 2.0.0
-.package(url: "/SwiftyJSON", from: "1.2.0"),
-
-// 1.5.8 ..< 2.0.0
-.package(url: "/SwiftyJSON", from: "1.5.8"),
-
-// 1.5.8 ..< 2.0.0
-.package(url: "/SwiftyJSON", .upToNextMajor(from: "1.5.8")),
-
-// 1.5.8 ..< 1.6.0
-.package(url: "/SwiftyJSON", .upToNextMinor(from: "1.5.8")),
-
-// 1.5.8
-.package(url: "/SwiftyJSON", .exact("1.5.8")),
-
-// Constraint to an arbitrary open range.
-.package(url: "/SwiftyJSON", "1.2.3"..<"1.2.6"),
-
-// Constraint to an arbitrary closed range.
-.package(url: "/SwiftyJSON", "1.2.3"..."1.2.8"),
-
-// Branch and revision.
-.package(url: "/SwiftyJSON", .branch("develop")),
-.package(url: "/SwiftyJSON", .revision("e74b07278b926c9ec6f9643455ea00d1ce04a021"))
-```
-
-#### targets
-
-The targets property is used to declare the targets in the package.
-
-```swift
-import PackageDescription
-
-let package = Package(
- name: "FooBar",
- targets: [
- .target(name: "Foo", dependencies: []),
- .testTarget(name: "Bar", dependencies: ["Foo"]),
- ]
-)
-```
-
-The above manifest declares two target, `Foo` and `Bar`. `Bar` is a test target
-which depends on `Foo`. The Package Manager will automatically search for the
-targets inside package in the [predefined search paths](#target-format-reference).
-
-A target dependency can either be another target in the same package or a product
-in one of its package dependencies. All target dependencies, internal or
-external, must be explicitly declared.
-
-A target can be further customized with these properties:
-
-* path: This property defines the path to the top-level directory containing the
-target's sources, relative to the package root. It is not legal for this path to
-escape the package root, i.e., values like "../Foo", "/Foo" are invalid. The
-default value of this property will be nil, which means the target will be
-searched for in the pre-defined paths. The empty string ("") or dot (".")
-implies that the target's sources are directly inside the package root.
-
-* exclude: This property can be used to exclude certain files and directories from
-being picked up as sources. Exclude paths are relative to the target path. This
-property has more precedence than sources property.
-
-* sources: This property defines the source files to be included in the target.
-The default value of this property will be nil, which means all valid source
-files found in the target's path will be included. This can contain directories
-and individual source files. Directories will be searched recursively for valid
-source files. Paths specified are relative to the target path.
-
-* publicHeadersPath: This property defines the path to the directory containing
-public headers of a C target. This path is relative to the target path and
-default value of this property is include. *Only valid for C family library
-targets*.
-
-Note: It is an error if the paths of two targets overlap (unless resolved with
-exclude).
-
-#### swiftLanguageVersions
-
-This property is used to specify the set of supported Swift language versions.
-
-The package manager will select the Swift language version that is most close to
-(but not exceeding) the major version of the Swift compiler in use. It is an
-error if a package does not support any version compatible with the current
-compiler. For e.g. if Swift language version is set to `[3]`, both Swift 3 and
-4 compilers will select '3', and if Swift language version is set to `[3, 4]`,
-Swift 3 compiler will select '3' and Swift 4 compiler will select '4'.
-
-If a package does not specify any Swift language versions, the language version
-to be used will match the major version of the package's [Swift tools
-version](Usage.md#swift-tools-version). For e.g.: A Swift tools version with
-a major version of '3' will imply a default Swift language version of '3', and
-a Swift tools version with a major version of '4' will imply a default Swift
-language version of '4'.
-
-## Version
-
-A struct representing a [semantic version](http://semver.org).
-
-```swift
-Version(
- _ major: Int,
- _ minor: Int,
- _ patch: Int,
- prereleaseIdentifiers: [String] = [],
- buildMetadataIdentifiers: [String] = []
-)
-```
-
-\- *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-release version; for example,
-alpha, beta.
-\- *buildMetadataIdentifiers*: Optional build metadata; for example, timestamp, hash.
-
-A `Version` struct can be initialized using a string literal in following
-format:
-
-``` "major.minor.patch[-prereleaseIdentifiers][+buildMetadataIdentifiers]" ```
-
-where `prereleaseIdentifiers` and `buildMetadataIdentifiers` are optional.
-_NOTE: prereleaseIdentifiers and buildMetadataIdentifiers elements are separated by dot (.)._
diff --git a/Documentation/PackageDescriptionV4_2.md b/Documentation/PackageDescriptionV4_2.md
deleted file mode 100644
index 0346526f995..00000000000
--- a/Documentation/PackageDescriptionV4_2.md
+++ /dev/null
@@ -1,92 +0,0 @@
-# PackageDescription API Version 4.2
-
-## Table of Contents
-
-* [Overview](README.md)
-* [Usage](Usage.md)
-* [PackageDescription API Version 3](PackageDescriptionV3.md)
-* [PackageDescription API Version 4](PackageDescriptionV4.md)
-* [**PackageDescription API Version 4.2**](PackageDescriptionV4_2.md)
- * [Swift Language Version](#swift-language-version)
- * [Local Dependencies](#local-dependencies)
- * [System Library Targets](#system-library-targets)
-* [Resources](Resources.md)
-
----
-
-The PackageDescription 4.2 contains one breaking and two additive changes to [PackageDescription API Version 4](PackageDescriptionV4.md).
-
-## Swift Language Version
-
-The `swiftLanguageVersions` takes an array of `SwiftVersion` enum:
-
-```swift
-public enum SwiftVersion {
- case v3
- case v4
- case v4_2
- case version(String)
-}
-```
-
-Example usage:
-
-```swift
-// swift-tools-version:4.2
-
-import PackageDescription
-
-let package = Package(
- name: "HTTPClient",
- ...
- swiftLanguageVersions: [.v4, .v4_2]
-)
-```
-
-## Local Dependencies
-
-Local dependences are packages on disk that can be referred directly using their
-paths. Local dependencies are only allowed in the root package and they override
-all dependencies with same name in the package graph. Example declaration:
-
-```swift
-import PackageDescription
-
-let package = Package(
- name: "MyPackage",
- dependencies: [
- .package(path: "../example-package-playingcard"),
- ],
- targets: [
- .target(
- name: "MyPackage",
- dependencies: ["PlayingCard"]
- ),
- ]
-)
-```
-
-## System Library Targets
-
-System library targets supply the same metadata needed to adapt system libraries
-to work with the package manager, but as a target. This allows packages to embed
-these targets with the libraries that need them.
-
-```swift
-// swift-tools-version:4.2
-import PackageDescription
-
-let package = Package(
- name: "ZLib",
- products: [
- .library(name: "ZLib", targets: ["ZLib"]),
- ],
- targets: [
- .systemLibrary(
- name: "CZLib")
- .target(
- name: "ZLib",
- dependencies: ["CZLib"]),
- ]
-)
-```
diff --git a/Documentation/README.md b/Documentation/README.md
index 79325f15aa5..2c8f9e88633 100644
--- a/Documentation/README.md
+++ b/Documentation/README.md
@@ -16,9 +16,7 @@ We’ve designed the system to make it really easy to share packages on services
* [About Dependencies](#about-dependencies)
* [Dependency Hell](#dependency-hell)
* [Usage](Usage.md)
-* [PackageDescription API Version 3](PackageDescriptionV3.md)
-* [PackageDescription API Version 4](PackageDescriptionV4.md)
-* [PackageDescription API Version 4.2](PackageDescriptionV4_2.md)
+* [PackageDescription API](PackageDescription.md)
* [libSwiftPM](libSwiftPM.md)
* [Resources](Resources.md)
diff --git a/Documentation/Resources.md b/Documentation/Resources.md
index cb8186687c6..21e8bdbc67c 100644
--- a/Documentation/Resources.md
+++ b/Documentation/Resources.md
@@ -4,9 +4,7 @@
* [Overview](README.md)
* [Usage](Usage.md)
-* [PackageDescription API Version 3](PackageDescriptionV3.md)
-* [PackageDescription API Version 4](PackageDescriptionV4.md)
-* [PackageDescription API Version 4.2](PackageDescriptionV4_2.md)
+* [PackageDescription API](PackageDescription.md)
* [**Resources**](Resources.md)
* [Support](#support)
* [Reporting a good SwiftPM Bug](#reporting-a-good-swiftpm-bug)
diff --git a/Documentation/Usage.md b/Documentation/Usage.md
index d1f69b18ae6..2367178a314 100644
--- a/Documentation/Usage.md
+++ b/Documentation/Usage.md
@@ -24,9 +24,7 @@
* [Depending on Apple Modules](#depending-on-apple-modules)
* [C language targets](#c-language-targets)
* [Shell completion scripts](#shell-completion-scripts)
-* [PackageDescription API Version 3](PackageDescriptionV3.md)
-* [PackageDescription API Version 4](PackageDescriptionV4.md)
-* [PackageDescription API Version 4.2](PackageDescriptionV4_2.md)
+* [PackageDescription API](PackageDescription.md)
* [Resources](Resources.md)
---
@@ -50,7 +48,7 @@ get started, create a directory and run `swift package init` command:
This will create the directory structure needed for a library package with a
target and the corresponding test target to write unit tests. A library package
can contain multiple targets as explained in [Target Format
-Reference](PackageDescriptionV4.md#target-format-reference).
+Reference](PackageDescription.md#target).
### Create an executable package
@@ -67,7 +65,7 @@ get started:
This creates the directory structure needed for executable targets. Any target
can be turned into a executable target if there is a `main.swift` present in
its sources. Complete reference for layout is
-[here](PackageDescriptionV4.md#target-format-reference).
+[here](PackageDescription.md#target).
## Define Dependencies
@@ -577,7 +575,7 @@ changes (e.g. because a teammate pushed a new version of the file) the next
resolve command will update packages to match that file. After a successful
resolve command, the checked out versions of all dependencies and the versions
recorded in the resolved versions file will match. In most cases the resolve
-command will perform no changes unless the `Package.swift manifest or
+command will perform no changes unless the `Package.swift` manifest or
`Package.resolved` file have changed.
Most SwiftPM commands will implicitly invoke the swift package resolve
@@ -686,11 +684,8 @@ A C language target is build with following flags in release mode:
## Depending on Apple Modules
-At this time there is no explicit support for depending on UIKit, 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.
+Swift Package Manager includes a build system that can build for macOS and Linux.
+Xcode 11 integrates with libSwiftPM to provide support for iOS, watchOS, and tvOS platforms.
## C language targets
diff --git a/Documentation/libSwiftPM.md b/Documentation/libSwiftPM.md
index c2482eb8640..0ee8bfea995 100644
--- a/Documentation/libSwiftPM.md
+++ b/Documentation/libSwiftPM.md
@@ -12,9 +12,8 @@ package:
```sh
$ git clone https://github.com/apple/swift-package-manager
-$ cd swift-package-manager/Examples/package-stats
-$ make build-runtimes
-$ swift build
+$ cd swift-package-manager/Examples/package-info
+$ make build
$ swift run
```
diff --git a/README.md b/README.md
index 22aef9cba32..8e147b4c677 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,9 @@ The Swift Package Manager is a tool for managing distribution of source code, ai
We’ve designed the system to make it easy to share packages on services like GitHub, but packages are also great for private personal development, sharing code within a team, or at any other granularity.
-Note that at this time the Package Manager has no support for iOS, watchOS, or tvOS platforms.
+Swift Package Manager includes a build system that can build for macOS and Linux. Xcode 11 integrates with libSwiftPM to provide support for iOS, watchOS, and tvOS platforms.
+
+The [SourceKit-LSP](https://github.com/apple/sourcekit-lsp) project leverages libSwiftPM and provides Language Server Protocol implementation for editors that support LSP.
---
diff --git a/Sources/Basic/EditDistance.swift b/Sources/Basic/EditDistance.swift
index 4873068bc54..7d04d650172 100644
--- a/Sources/Basic/EditDistance.swift
+++ b/Sources/Basic/EditDistance.swift
@@ -13,6 +13,8 @@
/// - Complexity: O(_n*m_), where *n* is the length of the first String and
/// *m* is the length of the second one.
public func editDistance(_ first: String, _ second: String) -> Int {
+ // FIXME: We should use the new `CollectionDifference` API once the
+ // deployment target is bumped.
let a = Array(first.utf16)
let b = Array(second.utf16)
var distance = [[Int]](repeating: [Int](repeating: 0, count: b.count + 1), count: a.count + 1)
@@ -34,3 +36,21 @@ public func editDistance(_ first: String, _ second: String) -> Int {
}
return distance[a.count][b.count]
}
+
+/// Finds the "best" match for a `String` from an array of possible options.
+///
+/// - Parameters:
+/// - input: The input `String` to match.
+/// - options: The available options for `input`.
+///
+/// - Returns: The best match from the given `options`, or `nil` if none were sufficiently close.
+public func bestMatch(for input: String, from options: [String]) -> String? {
+ return options
+ .map { ($0, editDistance(input, $0)) }
+ // Filter out unreasonable edit distances. Based on:
+ // https://github.com/apple/swift/blob/37daa03b7dc8fb3c4d91dc560a9e0e631c980326/lib/Sema/TypeCheckNameLookup.cpp#L606
+ .filter { $0.1 <= ($0.0.count + 2) / 3 }
+ // Sort by edit distance
+ .sorted { $0.1 < $1.1 }
+ .first?.0
+}
diff --git a/Sources/Basic/FileInfo.swift b/Sources/Basic/FileInfo.swift
index e162bdbc48b..740ebd0af09 100644
--- a/Sources/Basic/FileInfo.swift
+++ b/Sources/Basic/FileInfo.swift
@@ -8,71 +8,54 @@
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
*/
-import SPMLibc
import Foundation
/// File system information for a particular file.
public struct FileInfo: Equatable, Codable {
- /// File timestamp wrapper.
- public struct FileTimestamp: Equatable, Codable {
- public let seconds: UInt64
- public let nanoseconds: UInt64
- }
-
- /// File system entity kind.
- public enum Kind: String, Codable {
- case file, directory, symlink, blockdev, chardev, socket, unknown
-
- fileprivate init(mode: mode_t) {
- switch mode {
- case S_IFREG: self = .file
- case S_IFDIR: self = .directory
- case S_IFLNK: self = .symlink
- case S_IFBLK: self = .blockdev
- case S_IFCHR: self = .chardev
- case S_IFSOCK: self = .socket
- default:
- self = .unknown
- }
- }
- }
-
/// The device number.
public let device: UInt64
/// The inode number.
public let inode: UInt64
- /// The mode flags of the file.
- public let mode: UInt64
-
/// The size of the file.
public let size: UInt64
/// The modification time of the file.
- public let modTime: FileTimestamp
+ public let modTime: Date
/// Kind of file system entity.
- public var kind: Kind {
- return Kind(mode: mode_t(mode) & S_IFMT)
- }
+ public let posixPermissions: Int16
+
+ /// Kind of file system entity.
+ public let fileType: FileAttributeType
+
+ public init(_ attrs: [FileAttributeKey : Any]) {
+ let device = (attrs[.systemNumber] as? NSNumber)?.uint64Value
+ assert(device != nil)
+ self.device = device!
+
+ let inode = attrs[.systemFileNumber] as? UInt64
+ assert(inode != nil)
+ self.inode = inode!
+
+ let posixPermissions = (attrs[.posixPermissions] as? NSNumber)?.int16Value
+ assert(posixPermissions != nil)
+ self.posixPermissions = posixPermissions!
- public init(_ buf: SPMLibc.stat) {
- self.device = UInt64(buf.st_dev)
- self.inode = UInt64(buf.st_ino)
- self.mode = UInt64(buf.st_mode)
- self.size = UInt64(buf.st_size)
-
- #if canImport(Darwin)
- let seconds = buf.st_mtimespec.tv_sec
- let nanoseconds = buf.st_mtimespec.tv_nsec
- #else
- let seconds = buf.st_mtim.tv_sec
- let nanoseconds = buf.st_mtim.tv_nsec
- #endif
-
- self.modTime = FileTimestamp(
- seconds: UInt64(seconds), nanoseconds: UInt64(nanoseconds))
+ let fileType = attrs[.type] as? FileAttributeType
+ assert(fileType != nil)
+ self.fileType = fileType!
+
+ let size = attrs[.size] as? UInt64
+ assert(size != nil)
+ self.size = size!
+
+ let modTime = attrs[.modificationDate] as? Date
+ assert(modTime != nil)
+ self.modTime = modTime!
}
}
+
+extension FileAttributeType: Codable {}
diff --git a/Sources/Basic/FileSystem.swift b/Sources/Basic/FileSystem.swift
index 958eaaf4c78..51d25b9b19a 100644
--- a/Sources/Basic/FileSystem.swift
+++ b/Sources/Basic/FileSystem.swift
@@ -88,16 +88,18 @@ public enum FileMode {
case userUnWritable
case userWritable
case executable
-
- /// File mode as it would be passed to `chmod`.
- public var cliArgument: String {
+
+ internal var setMode: (Int16) -> Int16 {
switch self {
case .userUnWritable:
- return "u-w"
+ // r-x rwx rwx
+ return {$0 & 0o577}
case .userWritable:
- return "u+w"
+ // -w- --- ---
+ return {$0 | 0o200}
case .executable:
- return "+x"
+ // --x --x --x
+ return {$0 | 0o111}
}
}
}
@@ -229,7 +231,7 @@ private class LocalFileSystem: FileSystem {
func isExecutableFile(_ path: AbsolutePath) -> Bool {
// Our semantics doesn't consider directories.
- return self.isFile(path) && FileManager.default.isExecutableFile(atPath: path.pathString)
+ return (self.isFile(path) || self.isSymlink(path)) && FileManager.default.isExecutableFile(atPath: path.pathString)
}
func exists(_ path: AbsolutePath, followSymlink: Bool) -> Bool {
@@ -257,11 +259,8 @@ private class LocalFileSystem: FileSystem {
}
func getFileInfo(_ path: AbsolutePath) throws -> FileInfo {
- let path = path.pathString
- var statBuf = SPMLibc.stat()
- let rv = stat(path, &statBuf)
- guard rv == 0 else { throw SystemError.stat(errno, path) }
- return FileInfo(statBuf)
+ let attrs = try FileManager.default.attributesOfItem(atPath: path.pathString)
+ return FileInfo(attrs)
}
var currentWorkingDirectory: AbsolutePath? {
@@ -375,86 +374,39 @@ private class LocalFileSystem: FileSystem {
}
func chmod(_ mode: FileMode, path: AbsolutePath, options: Set) throws {
- #if os(macOS)
- // Get the mode we need to set.
- guard let setMode = setmode(mode.cliArgument) else {
- throw FileSystemError(errno: errno)
- }
- defer { setMode.deallocate() }
+ guard exists(path) else { return }
+ func setMode(path: String) throws {
+ // Skip if only files should be changed.
+ if options.contains(.onlyFiles) && isDirectory(AbsolutePath(path)) {
+ return
+ }
- let recursive = options.contains(.recursive)
- // If we're in recursive mode, do physical walk otherwise logical.
- let ftsOptions = recursive ? FTS_PHYSICAL : FTS_LOGICAL
+ let attrs = try FileManager.default.attributesOfItem(atPath: path)
- // Get handle to the file hierarchy we want to traverse.
- let paths = CStringArray([path.pathString])
- guard let ftsp = fts_open(paths.cArray, ftsOptions, nil) else {
- throw FileSystemError(errno: errno)
+ // Compute the new mode for this file.
+ let currentMode = attrs[.posixPermissions] as! Int16
+ let newMode = mode.setMode(currentMode)
+ guard newMode != currentMode else { return }
+ try FileManager.default.setAttributes([.posixPermissions : newMode],
+ ofItemAtPath: path)
}
- defer { fts_close(ftsp) }
-
- // Start traversing.
- while let p = fts_read(ftsp) {
-
- switch Int32(p.pointee.fts_info) {
-
- // A directory being visited in pre-order.
- case FTS_D:
- // If we're not recursing, skip the contents of the directory.
- if !recursive {
- fts_set(ftsp, p, FTS_SKIP)
- }
- continue
-
- // A directory couldn't be read.
- case FTS_DNR:
- // FIXME: We should warn here.
- break
-
- // There was an error.
- case FTS_ERR:
- fallthrough
- // No stat(2) information was available.
- case FTS_NS:
- // FIXME: We should warn here.
- continue
+ try setMode(path: path.pathString)
+ guard isDirectory(path) else { return }
- // A symbolic link.
- case FTS_SL:
- fallthrough
-
- // A symbolic link with a non-existent target.
- case FTS_SLNONE:
- // The only symlinks that end up here are ones that don't point
- // to anything and ones that we found doing a physical walk.
- continue
-
- default:
- break
- }
-
- // Compute the new mode for this file.
- let currentMode = mode_t(p.pointee.fts_statp.pointee.st_mode)
-
- // Skip if only files should be changed.
- if options.contains(.onlyFiles) && (currentMode & S_IFMT) == S_IFDIR {
- continue
- }
+ guard let traverse = FileManager.default.enumerator(
+ at: URL(fileURLWithPath: path.pathString),
+ includingPropertiesForKeys: nil) else {
+ throw FileSystemError.noEntry
+ }
- // Compute the new mode.
- let newMode = getmode(setMode, currentMode)
- if newMode == currentMode {
- continue
- }
+ if !options.contains(.recursive) {
+ traverse.skipDescendants()
+ }
- // Update the mode.
- //
- // We ignore the errors for now but we should have a way to report back.
- _ = SPMLibc.chmod(p.pointee.fts_accpath, newMode)
+ while let path = traverse.nextObject() {
+ try setMode(path: (path as! URL).path)
}
- #endif
- // FIXME: We only support macOS right now.
}
}
diff --git a/Sources/Basic/Lock.swift b/Sources/Basic/Lock.swift
index 650f99d9dc4..4338d4611e9 100644
--- a/Sources/Basic/Lock.swift
+++ b/Sources/Basic/Lock.swift
@@ -36,7 +36,11 @@ enum ProcessLockError: Swift.Error {
/// by mutiple instances of a process. The `FileLock` is not thread-safe.
public final class FileLock {
/// File descriptor to the lock file.
- private var fd: CInt?
+ #if os(Windows)
+ private var handle: HANDLE?
+ #else
+ private var fileDescriptor: CInt?
+ #endif
/// Path to the lock file.
private let lockFile: AbsolutePath
@@ -53,34 +57,74 @@ public final class FileLock {
///
/// Note: This method can throw if underlying POSIX methods fail.
public func lock() throws {
+ #if os(Windows)
+ if handle == nil {
+ let h = lockFile.pathString.withCString(encodedAs: UTF16.self, {
+ CreateFileW(
+ $0,
+ UInt32(GENERIC_READ) | UInt32(GENERIC_WRITE),
+ 0,
+ nil,
+ DWORD(OPEN_ALWAYS),
+ DWORD(FILE_ATTRIBUTE_NORMAL),
+ nil
+ )
+ })
+ if h == INVALID_HANDLE_VALUE {
+ throw FileSystemError(errno: Int32(GetLastError()))
+ }
+ self.handle = h
+ }
+ var overlapped = OVERLAPPED()
+ overlapped.Offset = 0
+ overlapped.OffsetHigh = 0
+ overlapped.hEvent = nil
+ if FALSE == LockFileEx(handle, DWORD(LOCKFILE_EXCLUSIVE_LOCK), 0, DWORD(INT_MAX), DWORD(INT_MAX), &overlapped) {
+ throw ProcessLockError.unableToAquireLock(errno: Int32(GetLastError()))
+ }
+ #else
// Open the lock file.
- if fd == nil {
+ if fileDescriptor == nil {
let fd = SPMLibc.open(lockFile.pathString, O_WRONLY | O_CREAT | O_CLOEXEC, 0o666)
if fd == -1 {
throw FileSystemError(errno: errno)
}
- self.fd = fd
+ self.fileDescriptor = fd
}
// Aquire lock on the file.
while true {
- if flock(fd!, LOCK_EX) == 0 {
+ if flock(fileDescriptor!, LOCK_EX) == 0 {
break
}
// Retry if interrupted.
if errno == EINTR { continue }
throw ProcessLockError.unableToAquireLock(errno: errno)
}
+ #endif
}
/// Unlock the held lock.
public func unlock() {
- guard let fd = fd else { return }
+ #if os(Windows)
+ var overlapped = OVERLAPPED()
+ overlapped.Offset = 0
+ overlapped.OffsetHigh = 0
+ overlapped.hEvent = nil
+ UnlockFileEx(handle, 0, DWORD(INT_MAX), DWORD(INT_MAX), &overlapped)
+ #else
+ guard let fd = fileDescriptor else { return }
flock(fd, LOCK_UN)
+ #endif
}
deinit {
- guard let fd = fd else { return }
+ #if os(Windows)
+ guard let handle = handle else { return }
+ CloseHandle(handle)
+ #else
+ guard let fd = fileDescriptor else { return }
close(fd)
+ #endif
}
/// Execute the given block while holding the lock.
diff --git a/Sources/Basic/Path.swift b/Sources/Basic/Path.swift
index 1f6a528ed65..06f50abcb6c 100644
--- a/Sources/Basic/Path.swift
+++ b/Sources/Basic/Path.swift
@@ -121,6 +121,14 @@ public struct AbsolutePath: Hashable {
return _impl.basename
}
+ /// Returns the basename without the extension.
+ public var basenameWithoutExt: String {
+ if let ext = self.extension {
+ return String(basename.dropLast(ext.count + 1))
+ }
+ return basename
+ }
+
/// Suffix (including leading `.` character) if any. Note that a basename
/// that starts with a `.` character is not considered a suffix, nor is a
/// trailing `.` character.
diff --git a/Sources/Basic/Process.swift b/Sources/Basic/Process.swift
index f388c769d95..7ed628aa93c 100644
--- a/Sources/Basic/Process.swift
+++ b/Sources/Basic/Process.swift
@@ -10,6 +10,10 @@
import class Foundation.ProcessInfo
+#if os(Windows)
+import Foundation
+#endif
+
import SPMLibc
import Dispatch
@@ -56,12 +60,16 @@ public struct ProcessResult: CustomStringConvertible {
stderrOutput: Result<[UInt8], AnyError>
) {
let exitStatus: ExitStatus
+ #if os(Windows)
+ exitStatus = .terminated(code: exitStatusCode)
+ #else
if WIFSIGNALED(exitStatusCode) {
exitStatus = .signalled(signal: WTERMSIG(exitStatusCode))
} else {
precondition(WIFEXITED(exitStatusCode), "unexpected exit status \(exitStatusCode)")
exitStatus = .terminated(code: WEXITSTATUS(exitStatusCode))
}
+ #endif
self.init(arguments: arguments, exitStatus: exitStatus, output: output,
stderrOutput: stderrOutput)
}
@@ -137,8 +145,10 @@ public final class Process: ObjectIdentifierProtocol {
}
/// Typealias for process id type.
+ #if !os(Windows)
public typealias ProcessID = pid_t
-
+ #endif
+
/// Typealias for stdout/stderr output closure.
public typealias OutputClosure = ([UInt8]) -> Void
@@ -160,7 +170,11 @@ public final class Process: ObjectIdentifierProtocol {
public let environment: [String: String]
/// The process id of the spawned process, available after the process is launched.
+ #if os(Windows)
+ private var _process: Foundation.Process?
+ #else
public private(set) var processID = ProcessID()
+ #endif
/// If the subprocess has launched.
/// Note: This property is not protected by the serial queue because it is only mutated in `launch()`, which will be
@@ -180,6 +194,11 @@ public final class Process: ObjectIdentifierProtocol {
/// The result of the process execution. Available after process is terminated.
private var _result: ProcessResult?
+ #if os(Windows)
+ private var stdoutData: [UInt8] = []
+ private var stderrData: [UInt8] = []
+ #endif
+
/// If redirected, stdout result and reference to the thread reading the output.
private var stdout: (result: Result<[UInt8], AnyError>, thread: Thread?) = (Result([]), nil)
@@ -267,6 +286,30 @@ public final class Process: ObjectIdentifierProtocol {
throw Process.Error.missingExecutableProgram(program: arguments[0])
}
+ #if os(Windows)
+ _process = Foundation.Process()
+ _process?.arguments = arguments
+ _process?.executableURL = URL(fileURLWithPath: arguments[0])
+
+ if outputRedirection.redirectsOutput {
+ let stdoutPipe = Pipe()
+ let stderrPipe = Pipe()
+ stdoutPipe.fileHandleForReading.readabilityHandler = { (fh : FileHandle) -> Void in
+ let contents = fh.readDataToEndOfFile()
+ self.outputRedirection.outputClosures?.stdoutClosure([UInt8](contents))
+ self.stdoutData += contents
+ }
+ stderrPipe.fileHandleForReading.readabilityHandler = { (fh : FileHandle) -> Void in
+ let contents = fh.readDataToEndOfFile()
+ self.outputRedirection.outputClosures?.stderrClosure([UInt8](contents))
+ self.stderrData += contents
+ }
+ _process?.standardOutput = stdoutPipe
+ _process?.standardError = stderrPipe
+ }
+
+ try _process?.run()
+ #else
// Initialize the spawn attributes.
#if canImport(Darwin)
var attributes: posix_spawnattr_t? = nil
@@ -381,11 +424,27 @@ public final class Process: ObjectIdentifierProtocol {
thread.start()
self.stderr.thread = thread
}
+ #endif // POSIX implementation
}
/// Blocks the calling process until the subprocess finishes execution.
@discardableResult
public func waitUntilExit() throws -> ProcessResult {
+ #if os(Windows)
+ precondition(_process != nil, "The process is not yet launched.")
+ let p = _process!
+ p.waitUntilExit()
+ stdout.thread?.join()
+ stderr.thread?.join()
+
+ let executionResult = ProcessResult(
+ arguments: arguments,
+ exitStatusCode: p.terminationStatus,
+ output: stdout.result,
+ stderrOutput: stderr.result
+ )
+ return executionResult
+ #else
return try serialQueue.sync {
precondition(launched, "The process is not yet launched.")
@@ -418,8 +477,10 @@ public final class Process: ObjectIdentifierProtocol {
self._result = executionResult
return executionResult
}
+ #endif
}
+ #if !os(Windows)
/// Reads the given fd and returns its result.
///
/// Closes the fd before returning.
@@ -456,13 +517,22 @@ public final class Process: ObjectIdentifierProtocol {
// Construct the output result.
return error.map(Result.init) ?? Result(out)
}
+ #endif
/// Send a signal to the process.
///
/// Note: This will signal all processes in the process group.
public func signal(_ signal: Int32) {
+ #if os(Windows)
+ if signal == SIGINT {
+ _process?.interrupt()
+ } else {
+ _process?.terminate()
+ }
+ #else
assert(launched, "The process is not yet launched.")
_ = SPMLibc.kill(startNewProcessGroup ? -processID : processID, signal)
+ #endif
}
}
@@ -517,6 +587,7 @@ extension Process {
// MARK: - Private helpers
+#if !os(Windows)
#if os(macOS)
private typealias swiftpm_posix_spawn_file_actions_t = posix_spawn_file_actions_t?
#else
@@ -605,3 +676,4 @@ extension ProcessResult.Error: CustomStringConvertible {
}
}
}
+#endif
diff --git a/Sources/Basic/ProcessEnv.swift b/Sources/Basic/ProcessEnv.swift
index b4f22c7c628..6bf3efecb78 100644
--- a/Sources/Basic/ProcessEnv.swift
+++ b/Sources/Basic/ProcessEnv.swift
@@ -21,18 +21,34 @@ public enum ProcessEnv {
/// Set the given key and value in the process's environment.
public static func setVar(_ key: String, value: String) throws {
- // FIXME: Need to handle Windows.
+ #if os(Windows)
+ guard 0 != key.withCString(encodedAs: UTF16.self, { keyStr in
+ value.withCString(encodedAs: UTF16.self) { valStr in
+ SetEnvironmentVariableW(keyStr, valStr)
+ }
+ }) else {
+ throw SystemError.setenv(Int32(GetLastError()), key)
+ }
+ #else
guard SPMLibc.setenv(key, value, 1) == 0 else {
throw SystemError.setenv(errno, key)
}
+ #endif
}
/// Unset the give key in the process's environment.
public static func unsetVar(_ key: String) throws {
- // FIXME: Need to handle Windows.
+ #if os(Windows)
+ guard 0 != key.withCString(encodedAs: UTF16.self, { keyStr in
+ SetEnvironmentVariableW(keyStr, nil)
+ }) else {
+ throw SystemError.unsetenv(Int32(GetLastError()), key)
+ }
+ #else
guard SPMLibc.unsetenv(key) == 0 else {
throw SystemError.unsetenv(errno, key)
}
+ #endif
}
/// The current working directory of the process.
@@ -42,10 +58,17 @@ public enum ProcessEnv {
/// Change the current working directory of the process.
public static func chdir(_ path: AbsolutePath) throws {
- // FIXME: Need to handle Windows.
let path = path.pathString
+ #if os(Windows)
+ guard 0 != path.withCString(encodedAs: UTF16.self, {
+ SetCurrentDirectoryW($0)
+ }) else {
+ throw SystemError.chdir(Int32(GetLastError()), path)
+ }
+ #else
guard SPMLibc.chdir(path) == 0 else {
throw SystemError.chdir(errno, path)
}
+ #endif
}
}
diff --git a/Sources/Basic/ProcessSet.swift b/Sources/Basic/ProcessSet.swift
index 4d1e6e3a769..66c4ce0b09e 100644
--- a/Sources/Basic/ProcessSet.swift
+++ b/Sources/Basic/ProcessSet.swift
@@ -89,7 +89,11 @@ public final class ProcessSet {
}
}
// Send kill signal to all processes.
+ #if os(Windows)
+ self.signalAll(SIGTERM)
+ #else
self.signalAll(SIGKILL)
+ #endif
}
thread.start()
diff --git a/Sources/Basic/misc.swift b/Sources/Basic/misc.swift
index bbf9df82dcb..92c8966b87e 100644
--- a/Sources/Basic/misc.swift
+++ b/Sources/Basic/misc.swift
@@ -18,9 +18,20 @@ import Foundation
/// - args: The executable arguments.
public func exec(path: String, args: [String]) throws {
let cArgs = CStringArray(args)
+ #if os(Windows)
+ guard cArgs.cArray.withUnsafeBufferPointer({
+ $0.withMemoryRebound(to: UnsafePointer?.self, {
+ _execv(path, $0.baseAddress) != -1
+ })
+ })
+ else {
+ throw SystemError.exec(errno, path: path, args: args)
+ }
+ #else
guard execv(path, cArgs.cArray) != -1 else {
throw SystemError.exec(errno, path: path, args: args)
}
+ #endif
}
// MARK: Utility function for searching for executables
@@ -163,13 +174,23 @@ public enum SystemError: Swift.Error {
case waitpid(Int32)
}
+#if os(Windows)
+import func SPMLibc.strerror_s
+#else
import func SPMLibc.strerror_r
+#endif
import var SPMLibc.EINVAL
import var SPMLibc.ERANGE
extension SystemError: CustomStringConvertible {
public var description: String {
func strerror(_ errno: Int32) -> String {
+ #if os(Windows)
+ let cap = 128
+ var buf = [Int8](repeating: 0, count: cap)
+ let _ = SPMLibc.strerror_s(&buf, 128, errno)
+ return "\(String(cString: buf)) (\(errno))"
+ #else
var cap = 64
while cap <= 16 * 1024 {
var buf = [Int8](repeating: 0, count: cap)
@@ -187,6 +208,7 @@ extension SystemError: CustomStringConvertible {
return "\(String(cString: buf)) (\(errno))"
}
fatalError("strerror_r error: \(ERANGE)")
+ #endif
}
switch self {
diff --git a/Sources/Build/BuildDelegate.swift b/Sources/Build/BuildDelegate.swift
index ae887a46030..bd183c701ee 100644
--- a/Sources/Build/BuildDelegate.swift
+++ b/Sources/Build/BuildDelegate.swift
@@ -186,6 +186,183 @@ extension SPMLLBuild.Diagnostic: DiagnosticDataConvertible {
}
}
+class CustomLLBuildCommand: ExternalCommand {
+ let ctx: BuildExecutionContext
+
+ required init(_ ctx: BuildExecutionContext) {
+ self.ctx = ctx
+ }
+
+ func getSignature(_ command: SPMLLBuild.Command) -> [UInt8] {
+ return []
+ }
+
+ func execute(_ command: SPMLLBuild.Command) -> Bool {
+ fatalError("subclass responsibility")
+ }
+}
+
+final class TestDiscoveryCommand: CustomLLBuildCommand {
+
+ private func write(
+ tests: [IndexStore.TestCaseClass],
+ forModule module: String,
+ to path: AbsolutePath
+ ) throws {
+ let stream = try LocalFileOutputByteStream(path)
+
+ stream <<< "import XCTest" <<< "\n"
+ stream <<< "@testable import " <<< module <<< "\n"
+
+ for klass in tests {
+ stream <<< "\n"
+ stream <<< "fileprivate extension " <<< klass.name <<< " {" <<< "\n"
+ stream <<< indent(4) <<< "static let __allTests__\(klass.name) = [" <<< "\n"
+ for method in klass.methods {
+ let method = method.hasSuffix("()") ? String(method.dropLast(2)) : method
+ stream <<< indent(8) <<< "(\"\(method)\", \(method))," <<< "\n"
+ }
+ stream <<< indent(4) <<< "]" <<< "\n"
+ stream <<< "}" <<< "\n"
+ }
+
+ stream <<< """
+ func __allTests_\(module)() -> [XCTestCaseEntry] {
+ return [\n
+ """
+
+ for klass in tests {
+ stream <<< indent(8) <<< "testCase(\(klass.name).__allTests__\(klass.name)),\n"
+ }
+
+ stream <<< """
+ ]
+ }
+ """
+
+ stream.flush()
+ }
+
+ private func execute(with tool: ToolProtocol) throws {
+ assert(tool is TestDiscoveryTool, "Unexpected tool \(tool)")
+
+ let index = ctx.buildParameters.indexStore
+ let api = try ctx.indexStoreAPI.dematerialize()
+ let store = try IndexStore.open(store: index, api: api)
+
+ // FIXME: We can speed this up by having one llbuild command per object file.
+ let tests = try tool.inputs.flatMap {
+ try store.listTests(inObjectFile: AbsolutePath($0))
+ }
+
+ let outputs = tool.outputs.compactMap{ try? AbsolutePath(validating: $0) }
+ let testsByModule = Dictionary(grouping: tests, by: { $0.module })
+
+ func isMainFile(_ path: AbsolutePath) -> Bool {
+ return path.basename == "main.swift"
+ }
+
+ // Write one file for each test module.
+ //
+ // We could write everything in one file but that can easily run into type conflicts due
+ // in complex packages with large number of test targets.
+ for file in outputs {
+ if isMainFile(file) { continue }
+
+ // FIXME: This is relying on implementation detail of the output but passing the
+ // the context all the way through is not worth it right now.
+ let module = file.basenameWithoutExt
+
+ guard let tests = testsByModule[module] else {
+ // This module has no tests so just write an empty file for it.
+ try localFileSystem.writeFileContents(file, bytes: "")
+ continue
+ }
+ try write(tests: tests, forModule: module, to: file)
+ }
+
+ // Write the main file.
+ let mainFile = outputs.first(where: isMainFile)!
+ let stream = try LocalFileOutputByteStream(mainFile)
+
+ stream <<< "import XCTest" <<< "\n\n"
+ stream <<< "var tests = [XCTestCaseEntry]()" <<< "\n"
+ for module in testsByModule.keys {
+ stream <<< "tests += __allTests_\(module)()" <<< "\n"
+ }
+ stream <<< "\n"
+ stream <<< "XCTMain(tests)" <<< "\n"
+
+ stream.flush()
+ }
+
+ private func indent(_ spaces: Int) -> ByteStreamable {
+ return Format.asRepeating(string: " ", count: spaces)
+ }
+
+ override func execute(_ command: SPMLLBuild.Command) -> Bool {
+ guard let tool = ctx.buildTimeCmdToolMap[command.name] else {
+ print("command \(command.name) not registered")
+ return false
+ }
+ do {
+ try execute(with: tool)
+ } catch {
+ // FIXME: Shouldn't use "print" here.
+ print("error:", error)
+ return false
+ }
+ return true
+ }
+}
+
+private final class InProcessTool: Tool {
+ let ctx: BuildExecutionContext
+
+ init(_ ctx: BuildExecutionContext) {
+ self.ctx = ctx
+ }
+
+ func createCommand(_ name: String) -> ExternalCommand {
+ // FIXME: This should be able to dynamically look up the right command.
+ switch ctx.buildTimeCmdToolMap[name] {
+ case is TestDiscoveryTool:
+ return TestDiscoveryCommand(ctx)
+ default:
+ fatalError("Unhandled command \(name)")
+ }
+ }
+}
+
+/// The context available during build execution.
+public final class BuildExecutionContext {
+
+ /// Mapping of command-name to its tool.
+ let buildTimeCmdToolMap: [String: ToolProtocol]
+
+ var indexStoreAPI: Result {
+ indexStoreAPICache.getValue(self)
+ }
+
+ let buildParameters: BuildParameters
+
+ public init(_ plan: BuildPlan, buildTimeCmdToolMap: [String: ToolProtocol]) {
+ self.buildParameters = plan.buildParameters
+ self.buildTimeCmdToolMap = buildTimeCmdToolMap
+ }
+
+ // MARK:- Private
+
+ private var indexStoreAPICache = LazyCache(createIndexStoreAPI)
+ private func createIndexStoreAPI() -> Result {
+ Result {
+ let ext = buildParameters.triple.dynamicLibraryExtension
+ let indexStoreLib = buildParameters.toolchain.toolchainLibDir.appending(component: "libIndexStore" + ext)
+ return try IndexStoreAPI(dylib: indexStoreLib)
+ }
+ }
+}
+
private let newLineByte: UInt8 = 10
public final class BuildDelegate: BuildSystemDelegate, SwiftCompilerOutputParserDelegate {
private let diagnostics: DiagnosticsEngine
@@ -201,7 +378,10 @@ public final class BuildDelegate: BuildSystemDelegate, SwiftCompilerOutputParser
/// Target name keyed by llbuild command name.
private let targetNames: [String: String]
+ let buildExecutionContext: BuildExecutionContext
+
public init(
+ bctx: BuildExecutionContext,
plan: BuildPlan,
diagnostics: DiagnosticsEngine,
outputStream: OutputByteStream,
@@ -212,6 +392,7 @@ public final class BuildDelegate: BuildSystemDelegate, SwiftCompilerOutputParser
// https://forums.swift.org/t/allow-self-x-in-class-convenience-initializers/15924
self.outputStream = outputStream as? ThreadSafeOutputByteStream ?? ThreadSafeOutputByteStream(outputStream)
self.progressAnimation = progressAnimation
+ self.buildExecutionContext = bctx
let buildConfig = plan.buildParameters.configuration.dirname
@@ -231,7 +412,12 @@ public final class BuildDelegate: BuildSystemDelegate, SwiftCompilerOutputParser
}
public func lookupTool(_ name: String) -> Tool? {
- return nil
+ switch name {
+ case TestDiscoveryTool.name:
+ return InProcessTool(buildExecutionContext)
+ default:
+ return nil
+ }
}
public func hadCommandFailure() {
@@ -412,6 +598,8 @@ fileprivate struct CommandTaskTracker {
finishedCount += 1
case .cancelled, .failed:
break
+ default:
+ break
}
}
diff --git a/Sources/Build/BuildPlan.swift b/Sources/Build/BuildPlan.swift
index 6945c4f24af..50a26655e2c 100644
--- a/Sources/Build/BuildPlan.swift
+++ b/Sources/Build/BuildPlan.swift
@@ -128,6 +128,9 @@ public struct BuildParameters {
/// Whether to enable code coverage.
public let enableCodeCoverage: Bool
+ /// Whether to enable test discovery on platforms without Objective-C runtime.
+ public let enableTestDiscovery: Bool
+
/// Whether to enable generation of `.swiftinterface` files alongside
/// `.swiftmodule`s.
public let enableParseableModuleInterfaces: Bool
@@ -156,7 +159,8 @@ public struct BuildParameters {
sanitizers: EnabledSanitizers = EnabledSanitizers(),
enableCodeCoverage: Bool = false,
indexStoreMode: IndexStoreMode = .auto,
- enableParseableModuleInterfaces: Bool = false
+ enableParseableModuleInterfaces: Bool = false,
+ enableTestDiscovery: Bool = false
) {
self.dataPath = dataPath
self.configuration = configuration
@@ -170,6 +174,7 @@ public struct BuildParameters {
self.enableCodeCoverage = enableCodeCoverage
self.indexStoreMode = indexStoreMode
self.enableParseableModuleInterfaces = enableParseableModuleInterfaces
+ self.enableTestDiscovery = enableTestDiscovery
}
/// Returns the compiler arguments for the index store, if enabled.
@@ -469,13 +474,22 @@ public final class SwiftTargetBuildDescription {
/// If this target is a test target.
public let isTestTarget: Bool
+ /// True if this is the test discovery target.
+ public let testDiscoveryTarget: Bool
+
/// Create a new target description with target and build parameters.
- init(target: ResolvedTarget, buildParameters: BuildParameters, isTestTarget: Bool? = nil) {
+ init(
+ target: ResolvedTarget,
+ buildParameters: BuildParameters,
+ isTestTarget: Bool? = nil,
+ testDiscoveryTarget: Bool = false
+ ) {
assert(target.underlyingTarget is SwiftTarget, "underlying target type mismatch \(target)")
self.target = target
self.buildParameters = buildParameters
// Unless mentioned explicitly, use the target type to determine if this is a test target.
self.isTestTarget = isTestTarget ?? (target.type == .test)
+ self.testDiscoveryTarget = testDiscoveryTarget
}
/// The arguments needed to compile this target.
@@ -511,7 +525,11 @@ public final class SwiftTargetBuildDescription {
// Add arguments to colorize output if stdout is tty
if buildParameters.isTTY {
- args += ["-Xfrontend", "-color-diagnostics"]
+ if Process.env["SWIFTPM_USE_NEW_COLOR_DIAGNOSTICS"] != nil {
+ args += ["-color-diagnostics"]
+ } else {
+ args += ["-Xfrontend", "-color-diagnostics"]
+ }
}
// Add the output for the `.swiftinterface`, if requested.
@@ -865,6 +883,65 @@ public class BuildPlan {
/// Diagnostics Engine for emitting diagnostics.
let diagnostics: DiagnosticsEngine
+ private static func planLinuxMain(
+ _ buildParameters: BuildParameters,
+ _ graph: PackageGraph
+ ) throws -> (ResolvedTarget, SwiftTargetBuildDescription)? {
+ guard buildParameters.triple.isLinux() else {
+ return nil
+ }
+
+ // Currently, there can be only one test product in a package graph.
+ guard let testProduct = graph.allProducts.first(where: { $0.type == .test }) else {
+ return nil
+ }
+
+ if !buildParameters.enableTestDiscovery {
+ guard let linuxMainTarget = testProduct.linuxMainTarget else {
+ throw Error.missingLinuxMain
+ }
+
+ let desc = SwiftTargetBuildDescription(
+ target: linuxMainTarget,
+ buildParameters: buildParameters,
+ isTestTarget: true
+ )
+ return (linuxMainTarget, desc)
+ }
+
+ // We'll generate sources containing the test names as part of the build process.
+ let derivedTestListDir = buildParameters.buildPath.appending(components: "testlist.derived")
+ let mainFile = derivedTestListDir.appending(component: "main.swift")
+
+ var paths: [AbsolutePath] = []
+ paths.append(mainFile)
+ let testTargets = graph.rootPackages.flatMap{ $0.targets }.filter{ $0.type == .test }
+ for testTarget in testTargets {
+ let path = derivedTestListDir.appending(components: testTarget.name + ".swift")
+ paths.append(path)
+ }
+
+ let src = Sources(paths: paths, root: derivedTestListDir)
+
+ let swiftTarget = SwiftTarget(
+ testDiscoverySrc: src,
+ name: testProduct.name,
+ dependencies: testProduct.underlyingProduct.targets)
+ let linuxMainTarget = ResolvedTarget(
+ target: swiftTarget,
+ dependencies: testProduct.targets.map(ResolvedTarget.Dependency.target)
+ )
+
+ let target = SwiftTargetBuildDescription(
+ target: linuxMainTarget,
+ buildParameters: buildParameters,
+ isTestTarget: true,
+ testDiscoveryTarget: true
+ )
+
+ return (linuxMainTarget, target)
+ }
+
/// Create a build plan with build parameters and a package graph.
public init(
buildParameters: BuildParameters,
@@ -918,19 +995,10 @@ public class BuildPlan {
throw Diagnostics.fatalError
}
- if buildParameters.triple.isLinux() {
- // FIXME: Create a target for LinuxMain file on linux.
- // This will go away once it is possible to auto detect tests.
- let testProducts = graph.allProducts.filter({ $0.type == .test })
-
- for product in testProducts {
- guard let linuxMainTarget = product.linuxMainTarget else {
- throw Error.missingLinuxMain
- }
- let target = SwiftTargetBuildDescription(
- target: linuxMainTarget, buildParameters: buildParameters, isTestTarget: true)
- targetMap[linuxMainTarget] = .swift(target)
- }
+ // Plan the linux main target.
+ if let result = try Self.planLinuxMain(buildParameters, graph) {
+ targetMap[result.0] = .swift(result.1)
+ self.linuxMainTarget = result.0
}
var productMap: [ResolvedProduct: ProductBuildDescription] = [:]
@@ -950,6 +1018,8 @@ public class BuildPlan {
try plan()
}
+ private var linuxMainTarget: ResolvedTarget?
+
static func validateDeploymentVersionOfProductDependency(
_ product: ResolvedProduct,
forTarget target: ResolvedTarget,
@@ -1091,7 +1161,7 @@ public class BuildPlan {
if buildParameters.triple.isLinux() {
if product.type == .test {
- product.linuxMainTarget.map({ staticTargets.append($0) })
+ linuxMainTarget.map({ staticTargets.append($0) })
}
}
diff --git a/Sources/Build/ToolProtocol.swift b/Sources/Build/ToolProtocol.swift
index 07ad19b7861..aa7715de700 100644
--- a/Sources/Build/ToolProtocol.swift
+++ b/Sources/Build/ToolProtocol.swift
@@ -14,7 +14,7 @@ import SPMUtility
import class Foundation.ProcessInfo
/// Describes a tool which can be understood by llbuild's BuildSystem library.
-protocol ToolProtocol {
+public protocol ToolProtocol {
/// The list of inputs to declare.
var inputs: [String] { get }
@@ -38,6 +38,20 @@ struct PhonyTool: ToolProtocol {
}
}
+struct TestDiscoveryTool: ToolProtocol {
+
+ static let name: String = "test-discovery-tool"
+
+ let inputs: [String]
+ let outputs: [String]
+
+ func append(to stream: OutputByteStream) {
+ stream <<< " tool: \(Self.name)\n"
+ stream <<< " inputs: " <<< Format.asJSON(inputs) <<< "\n"
+ stream <<< " outputs: " <<< Format.asJSON(outputs) <<< "\n"
+ }
+}
+
struct ShellTool: ToolProtocol {
let description: String
let inputs: [String]
diff --git a/Sources/Build/llbuild.swift b/Sources/Build/llbuild.swift
index dd5b7861a68..5f2c589983f 100644
--- a/Sources/Build/llbuild.swift
+++ b/Sources/Build/llbuild.swift
@@ -14,7 +14,7 @@ import PackageModel
import PackageGraph
/// llbuild manifest file generator for a build plan.
-public struct LLBuildManifestGenerator {
+public final class LLBuildManifestGenerator {
/// The name of the llbuild target that builds all products and targets (excluding tests).
public static let llbuildMainTargetName = "main"
@@ -49,7 +49,7 @@ public struct LLBuildManifestGenerator {
}
/// All commands.
- private(set) var allCommands = SortedArray(areInIncreasingOrder: <)
+ var allCommands = SortedArray(areInIncreasingOrder: <)
/// Other targets.
private var otherTargets: [Target] = []
@@ -101,6 +101,8 @@ public struct LLBuildManifestGenerator {
}
}
+ addTestFileGeneration(&targets)
+
// Create command for all products in the plan.
for (product, description) in plan.productMap {
// Only build products by default if they are reachabe from a root target.
@@ -134,6 +136,40 @@ public struct LLBuildManifestGenerator {
try localFileSystem.writeFileContents(path, bytes: stream.bytes)
}
+ private func addTestFileGeneration(_ targets: inout Targets) {
+ var testTargets: [SwiftTargetBuildDescription] = []
+ var _testDiscoveryTarget: SwiftTargetBuildDescription?
+
+ for target in plan.targets {
+ switch target {
+ case .swift(let target) where target.isTestTarget:
+ if target.testDiscoveryTarget {
+ _testDiscoveryTarget = target
+ } else {
+ testTargets.append(target)
+ }
+ default:
+ break
+ }
+ }
+
+ // Nothing to do if we don't have the test discovery target.
+ guard let testDiscoveryTarget = _testDiscoveryTarget else {
+ return
+ }
+
+ let objectFiles = testTargets.flatMap{ $0.objects }.map{ $0.pathString }.sorted()
+ let outputs = testDiscoveryTarget.target.sources.paths
+ let tool = TestDiscoveryTool(inputs: objectFiles, outputs: outputs.map{ $0.pathString })
+
+ let cmdName = outputs.first{ $0.basename == "main.swift" }!.pathString
+ targets.allCommands.insert(Command(name: cmdName, tool: tool))
+ buildTimeCmdToolMap[cmdName] = tool
+ }
+
+ /// Map of command -> tool that is used during the build for in-process tools.
+ public private(set) var buildTimeCmdToolMap: [String: ToolProtocol] = [:]
+
/// Create a llbuild target for a product description.
private func createProductTarget(_ buildProduct: ProductBuildDescription) -> Target {
let tool: ToolProtocol
diff --git a/Sources/Commands/Options.swift b/Sources/Commands/Options.swift
index 7d812f820d0..93ee81b2d86 100644
--- a/Sources/Commands/Options.swift
+++ b/Sources/Commands/Options.swift
@@ -77,5 +77,8 @@ public class ToolOptions {
/// The number of jobs for llbuild to start (aka the number of schedulerLanes)
public var jobs: UInt32? = nil
+ /// Whether to enable test discovery on platforms without Objective-C runtime.
+ public var enableTestDiscovery: Bool = false
+
public required init() {}
}
diff --git a/Sources/Commands/SwiftPackageTool.swift b/Sources/Commands/SwiftPackageTool.swift
index 3610c6b0728..bee5ea65268 100644
--- a/Sources/Commands/SwiftPackageTool.swift
+++ b/Sources/Commands/SwiftPackageTool.swift
@@ -363,7 +363,7 @@ public class SwiftPackageTool: SwiftTool {
binder.bind(
option: initPackageParser.add(
option: "--type", kind: InitPackage.PackageType.self,
- usage: "empty|library|executable|system-module"),
+ usage: "empty|library|executable|system-module|manifest"),
to: { $0.initMode = $1 })
binder.bind(
diff --git a/Sources/Commands/SwiftTool.swift b/Sources/Commands/SwiftTool.swift
index ad96e2802f1..65a50684815 100644
--- a/Sources/Commands/SwiftTool.swift
+++ b/Sources/Commands/SwiftTool.swift
@@ -362,6 +362,11 @@ public class SwiftTool {
usage: "The number of jobs to spawn in parallel during the build process"),
to: { $0.jobs = UInt32($1) })
+ binder.bind(
+ option: parser.add(option: "--enable-test-discovery", kind: Bool.self,
+ usage: "Enable test discovery on platforms without Objective-C runtime"),
+ to: { $0.enableTestDiscovery = $1 })
+
// Let subclasses bind arguments.
type(of: self).defineArguments(parser: parser, binder: binder)
@@ -383,19 +388,23 @@ public class SwiftTool {
// Terminate all processes on receiving an interrupt signal.
processSet.terminate()
+ #if os(Windows)
+ // Exit as if by signal()
+ TerminateProcess(GetCurrentProcess(), 3)
+ #elseif os(macOS)
// Install the default signal handler.
var action = sigaction()
- #if os(macOS)
action.__sigaction_u.__sa_handler = SIG_DFL
+ sigaction(SIGINT, &action, nil)
+ kill(getpid(), SIGINT)
#else
+ var action = sigaction()
action.__sigaction_handler = unsafeBitCast(
SIG_DFL,
to: sigaction.__Unnamed_union___sigaction_handler.self)
- #endif
sigaction(SIGINT, &action, nil)
-
- // Die with sigint.
kill(getpid(), SIGINT)
+ #endif
}
self.processSet = processSet
@@ -579,13 +588,6 @@ public class SwiftTool {
return try subset.llbuildTargetName(for: loadPackageGraph(), diagnostics: diagnostics, config: buildParameters.configuration.dirname)
}
}
-
- func build(plan: BuildPlan, parameters: BuildParameters, subset: BuildSubset) throws {
- guard let llbuildTargetName = try computeLLBuildTargetName(for: subset, buildParameters: parameters) else {
- return
- }
- try runLLBuild(plan: plan, manifest: parameters.llbuildManifest, llbuildTarget: llbuildTargetName)
- }
/// Build a subset of products and targets using swift-build-tool.
func build(plan: BuildPlan, subset: BuildSubset) throws {
@@ -597,10 +599,11 @@ public class SwiftTool {
// Generate the llbuild manifest.
let llbuild = LLBuildManifestGenerator(plan, client: "basic")
try llbuild.generateManifest(at: manifest)
+ let bctx = BuildExecutionContext(plan, buildTimeCmdToolMap: llbuild.buildTimeCmdToolMap)
// Run llbuild.
assert(localFileSystem.isFile(manifest), "llbuild manifest not present: \(manifest)")
- try runLLBuild(plan: plan, manifest: manifest, llbuildTarget: llbuildTargetName)
+ try runLLBuild(plan: plan, bctx: bctx, manifest: manifest, llbuildTarget: llbuildTargetName)
// Create backwards-compatibilty symlink to old build path.
let oldBuildPath = buildPath.appending(component: options.configuration.dirname)
@@ -610,13 +613,14 @@ public class SwiftTool {
try createSymlink(oldBuildPath, pointingAt: plan.buildParameters.buildPath, relative: true)
}
- func runLLBuild(plan: BuildPlan, manifest: AbsolutePath, llbuildTarget: String) throws {
+ private func runLLBuild(plan: BuildPlan, bctx: BuildExecutionContext, manifest: AbsolutePath, llbuildTarget: String) throws {
// Setup the build delegate.
let isVerbose = verbosity != .concise
let progressAnimation: ProgressAnimationProtocol = isVerbose ?
MultiLineNinjaProgressAnimation(stream: stdoutStream) :
NinjaProgressAnimation(stream: stdoutStream)
let buildDelegate = BuildDelegate(
+ bctx: bctx,
plan: plan,
diagnostics: diagnostics,
outputStream: stdoutStream,
@@ -654,7 +658,8 @@ public class SwiftTool {
sanitizers: options.sanitizers,
enableCodeCoverage: options.shouldEnableCodeCoverage,
indexStoreMode: options.indexStoreMode,
- enableParseableModuleInterfaces: options.shouldEnableParseableModuleInterfaces
+ enableParseableModuleInterfaces: options.shouldEnableParseableModuleInterfaces,
+ enableTestDiscovery: options.enableTestDiscovery
)
})
}()
diff --git a/Sources/PackageDescription4/SupportedPlatforms.swift b/Sources/PackageDescription4/SupportedPlatforms.swift
index 22457514485..9e8398ddd5e 100644
--- a/Sources/PackageDescription4/SupportedPlatforms.swift
+++ b/Sources/PackageDescription4/SupportedPlatforms.swift
@@ -29,8 +29,6 @@ public struct Platform: Encodable {
/// A platform that the Swift package supports.
///
-/// # The Supported Platform
-///
/// By default, the Swift Package Manager assigns a predefined minimum deployment
/// version for each supported platforms unless you configure supported platforms using the `platforms`
/// API. This predefined deployment version is the oldest deployment target
diff --git a/Sources/PackageGraph/DependencyResolver.swift b/Sources/PackageGraph/DependencyResolver.swift
index 2182e283e76..afa464c0c3f 100644
--- a/Sources/PackageGraph/DependencyResolver.swift
+++ b/Sources/PackageGraph/DependencyResolver.swift
@@ -79,7 +79,7 @@ public enum DependencyResolverError: Error, Equatable, CustomStringConvertible {
case let .missingVersions(constraints):
let stream = BufferedOutputByteStream()
- stream <<< "the package dependency graph could not be resolved; unable find any available tag for the following requirements:\n"
+ stream <<< "the package dependency graph could not be resolved; unable to find any available tag for the following requirements:\n"
for (i, constraint) in constraints.enumerated() {
stream <<< " "
stream <<< "\(constraint.identifier.path)" <<< " @ "
diff --git a/Sources/PackageModel/Target.swift b/Sources/PackageModel/Target.swift
index ca9cbcdb584..7f346d33bc0 100644
--- a/Sources/PackageModel/Target.swift
+++ b/Sources/PackageModel/Target.swift
@@ -79,6 +79,19 @@ public class SwiftTarget: Target {
/// The file name of linux main file.
public static let linuxMainBasename = "LinuxMain.swift"
+ public init(testDiscoverySrc: Sources, name: String, dependencies: [Target]) {
+ self.swiftVersion = .v5
+
+ super.init(
+ name: name,
+ platforms: [],
+ type: .executable,
+ sources: testDiscoverySrc,
+ dependencies: dependencies,
+ buildSettings: .init()
+ )
+ }
+
/// Create an executable Swift target from linux main test manifest file.
init(linuxMain: AbsolutePath, name: String, dependencies: [Target]) {
// Look for the first swift test target and use the same swift version
diff --git a/Sources/SPMLLBuild/llbuild.swift b/Sources/SPMLLBuild/llbuild.swift
index 128f85a2461..065b0b5595d 100644
--- a/Sources/SPMLLBuild/llbuild.swift
+++ b/Sources/SPMLLBuild/llbuild.swift
@@ -95,7 +95,7 @@ public final class LLBuildEngine {
return T.BuildValue(value)
}
- public func attachDB(path: String, schemaVersion: Int = 0) throws {
+ public func attachDB(path: String, schemaVersion: Int = 1) throws {
try engine.attachDB(path: path, schemaVersion: schemaVersion)
}
diff --git a/Sources/SPMLibc/libc.swift b/Sources/SPMLibc/libc.swift
index 4f32b5a40d2..d7d964d5148 100644
--- a/Sources/SPMLibc/libc.swift
+++ b/Sources/SPMLibc/libc.swift
@@ -10,6 +10,9 @@
#if os(Linux)
@_exported import Glibc
+#elseif os(Windows)
+@_exported import MSVCRT
+@_exported import WinSDK
#else
@_exported import Darwin.C
#endif
diff --git a/Sources/SPMUtility/ArgumentParser.swift b/Sources/SPMUtility/ArgumentParser.swift
index 8ef3b3fe58d..a623ed6f0a3 100644
--- a/Sources/SPMUtility/ArgumentParser.swift
+++ b/Sources/SPMUtility/ArgumentParser.swift
@@ -16,7 +16,7 @@ import func SPMLibc.exit
public enum ArgumentParserError: Swift.Error {
/// An unknown option is encountered.
- case unknownOption(String)
+ case unknownOption(String, suggestion: String?)
/// The value of an argument is invalid.
case invalidValue(argument: String, error: ArgumentConversionError)
@@ -29,6 +29,9 @@ public enum ArgumentParserError: Swift.Error {
/// Expected these positional arguments but not found.
case expectedArguments(ArgumentParser, [String])
+
+ /// Expected a single argument but got multiple ones.
+ case duplicateArgument(String)
}
extension ArgumentParserError: LocalizedError {
@@ -40,8 +43,12 @@ extension ArgumentParserError: LocalizedError {
extension ArgumentParserError: CustomStringConvertible {
public var description: String {
switch self {
- case .unknownOption(let option):
- return "unknown option \(option); use --help to list available options"
+ case .unknownOption(let option, let suggestion):
+ var desc = "unknown option \(option); use --help to list available options"
+ if let suggestion = suggestion {
+ desc += "\nDid you mean \(suggestion)?"
+ }
+ return desc
case .invalidValue(let argument, let error):
return "\(error) for argument \(argument); use --help to print usage"
case .expectedValue(let option):
@@ -50,6 +57,8 @@ extension ArgumentParserError: CustomStringConvertible {
return "unexpected argument \(argument); use --help to list available arguments"
case .expectedArguments(_, let arguments):
return "expected arguments: \(arguments.joined(separator: ", "))"
+ case .duplicateArgument(let option):
+ return "expected single value for argument: \(option)"
}
}
}
@@ -556,6 +565,11 @@ public final class ArgumentParser {
assertionFailure()
return
}
+
+ guard results[argument.name] == nil else {
+ throw ArgumentParserError.duplicateArgument(argument.name)
+ }
+
results[argument.name] = value
}
}
@@ -837,7 +851,8 @@ public final class ArgumentParser {
let (argumentString, value) = argumentString.spm_split(around: "=")
// Get the corresponding option for the option argument.
guard let optionArgument = optionsMap[argumentString] else {
- throw ArgumentParserError.unknownOption(argumentString)
+ let suggestion = bestMatch(for: argumentString, from: Array(optionsMap.keys))
+ throw ArgumentParserError.unknownOption(argumentString, suggestion: suggestion)
}
argument = optionArgument
diff --git a/Sources/SPMUtility/IndexStore.swift b/Sources/SPMUtility/IndexStore.swift
new file mode 100644
index 00000000000..99814fba409
--- /dev/null
+++ b/Sources/SPMUtility/IndexStore.swift
@@ -0,0 +1,240 @@
+/*
+ This source file is part of the Swift.org open source project
+
+ Copyright (c) 2019 Apple Inc. and the Swift project authors
+ Licensed under Apache License v2.0 with Runtime Library Exception
+
+ See http://swift.org/LICENSE.txt for license information
+ See http://swift.org/CONTRIBUTORS.txt for Swift project authors
+ */
+
+import Basic
+import clibc
+
+public final class IndexStore {
+
+ public struct TestCaseClass {
+ public var name: String
+ public var module: String
+ public var methods: [String]
+ }
+
+ let api: IndexStoreAPI
+
+ var fn: indexstore_functions_t {
+ return api.fn
+ }
+
+ let store: indexstore_t
+
+ private init(store: indexstore_t, api: IndexStoreAPI) {
+ self.store = store
+ self.api = api
+ }
+
+ static public func open(store path: AbsolutePath, api: IndexStoreAPI) throws -> IndexStore {
+ if let store = try api.call({ api.fn.store_create(path.pathString, &$0) }) {
+ return IndexStore(store: store, api: api)
+ }
+ throw StringError("Unable to open store at \(path)")
+ }
+
+ public func listTests(inObjectFile object: AbsolutePath) throws -> [TestCaseClass] {
+ // Get the records of this object file.
+ let unitReader = try api.call{ fn.unit_reader_create(store, unitName(object: object), &$0) }
+ let records = try getRecords(unitReader: unitReader)
+
+ // Get the test classes.
+ let testCaseClasses = try records.flatMap{ try self.getTestCaseClasses(forRecord: $0) }
+
+ // Fill the module name and return.
+ let module = fn.unit_reader_get_module_name(unitReader).str
+ return testCaseClasses.map {
+ var c = $0
+ c.module = module
+ return c
+ }
+ }
+
+ private func getTestCaseClasses(forRecord record: String) throws -> [TestCaseClass] {
+ let recordReader = try api.call{ fn.record_reader_create(store, record, &$0) }
+
+ class TestCaseBuilder {
+ var classToMethods: [String: Set] = [:]
+
+ func add(klass: String, method: String) {
+ classToMethods[klass, default: []].insert(method)
+ }
+
+ func build() -> [TestCaseClass] {
+ return classToMethods.map {
+ TestCaseClass(name: $0.key, module: "", methods: $0.value.sorted())
+ }
+ }
+ }
+
+ let builder = Ref(TestCaseBuilder(), api: api)
+
+ let ctx = unsafeBitCast(Unmanaged.passUnretained(builder), to: UnsafeMutableRawPointer.self)
+ _ = fn.record_reader_occurrences_apply_f(recordReader, ctx) { ctx , occ -> Bool in
+ let builder = Unmanaged[>.fromOpaque(ctx!).takeUnretainedValue()
+ let fn = builder.api.fn
+
+ // Get the symbol.
+ let sym = fn.occurrence_get_symbol(occ)
+
+ // We only care about symbols that are marked unit tests and are instance methods.
+ if fn.symbol_get_properties(sym) != UInt64(INDEXSTORE_SYMBOL_PROPERTY_UNITTEST.rawValue) {
+ return true
+ }
+ if fn.symbol_get_kind(sym) != INDEXSTORE_SYMBOL_KIND_INSTANCEMETHOD {
+ return true
+ }
+
+ let className = Ref("", api: builder.api)
+ let ctx = unsafeBitCast(Unmanaged.passUnretained(className), to: UnsafeMutableRawPointer.self)
+
+ _ = fn.occurrence_relations_apply_f(occ!, ctx) { ctx, relation in
+ guard let relation = relation else { return true }
+ let className = Unmanaged][>.fromOpaque(ctx!).takeUnretainedValue()
+ let fn = className.api.fn
+
+ // Look for the class.
+ if fn.symbol_relation_get_roles(relation) != UInt64(INDEXSTORE_SYMBOL_ROLE_REL_CHILDOF.rawValue) {
+ return true
+ }
+
+ let sym = fn.symbol_relation_get_symbol(relation)
+ className.instance = fn.symbol_get_name(sym).str
+ return true
+ }
+
+ if !className.instance.isEmpty {
+ let testMethod = fn.symbol_get_name(sym).str
+ builder.instance.add(klass: className.instance, method: testMethod)
+ }
+
+ return true
+ }
+
+ return builder.instance.build()
+ }
+
+ private func getRecords(unitReader: indexstore_unit_reader_t?) throws -> [String] {
+ let builder = Ref([String](), api: api)
+
+ let ctx = unsafeBitCast(Unmanaged.passUnretained(builder), to: UnsafeMutableRawPointer.self)
+ _ = fn.unit_reader_dependencies_apply_f(unitReader, ctx) { ctx , unit -> Bool in
+ let store = Unmanaged][>.fromOpaque(ctx!).takeUnretainedValue()
+ let fn = store.api.fn
+ if fn.unit_dependency_get_kind(unit) == INDEXSTORE_UNIT_DEPENDENCY_RECORD {
+ store.instance.append(fn.unit_dependency_get_name(unit).str)
+ }
+ return true
+ }
+
+ return builder.instance
+ }
+
+ private func unitName(object: AbsolutePath) -> String {
+ let initialSize = 64
+ var buf = UnsafeMutablePointer.allocate(capacity: initialSize)
+ let len = fn.store_get_unit_name_from_output_path(store, object.pathString, buf, initialSize)
+
+ if len + 1 > initialSize {
+ buf.deallocate()
+ buf = UnsafeMutablePointer.allocate(capacity: len + 1)
+ _ = fn.store_get_unit_name_from_output_path(store, object.pathString, buf, len + 1)
+ }
+
+ defer {
+ buf.deallocate()
+ }
+
+ return String(cString: buf)
+ }
+}
+
+private class Ref {
+ let api: IndexStoreAPI
+ var instance: T
+ init(_ instance: T, api: IndexStoreAPI) {
+ self.instance = instance
+ self.api = api
+ }
+}
+
+public final class IndexStoreAPI {
+
+ /// The path of the index store dylib.
+ private let path: AbsolutePath
+
+ /// Handle of the dynamic library.
+ private let dylib: DLHandle
+
+ /// The index store API functions.
+ fileprivate let fn: indexstore_functions_t
+
+ fileprivate func call(_ fn: (inout indexstore_error_t?) -> T) throws -> T {
+ var error: indexstore_error_t? = nil
+ let ret = fn(&error)
+
+ if let error = error {
+ if let desc = self.fn.error_get_description(error) {
+ throw StringError(String(cString: desc))
+ }
+ throw StringError("Unable to get description for error: \(error)")
+ }
+
+ return ret
+ }
+
+ public init(dylib path: AbsolutePath) throws {
+ self.path = path
+ self.dylib = try dlopen(path.pathString, mode: [.lazy, .local, .first, .deepBind])
+
+ func dlsym_required(_ handle: DLHandle, symbol: String) throws -> T {
+ guard let sym: T = dlsym(handle, symbol: symbol) else {
+ throw StringError("Missing required symbol: \(symbol)")
+ }
+ return sym
+ }
+
+ var api = indexstore_functions_t()
+ api.store_create = try dlsym_required(dylib, symbol: "indexstore_store_create")
+ api.store_get_unit_name_from_output_path = try dlsym_required(dylib, symbol: "indexstore_store_get_unit_name_from_output_path")
+ api.unit_reader_create = try dlsym_required(dylib, symbol: "indexstore_unit_reader_create")
+ api.error_get_description = try dlsym_required(dylib, symbol: "indexstore_error_get_description")
+ api.unit_reader_dependencies_apply_f = try dlsym_required(dylib, symbol: "indexstore_unit_reader_dependencies_apply_f")
+ api.unit_reader_get_module_name = try dlsym_required(dylib, symbol: "indexstore_unit_reader_get_module_name")
+ api.unit_dependency_get_kind = try dlsym_required(dylib, symbol: "indexstore_unit_dependency_get_kind")
+ api.unit_dependency_get_name = try dlsym_required(dylib, symbol: "indexstore_unit_dependency_get_name")
+ api.record_reader_create = try dlsym_required(dylib, symbol: "indexstore_record_reader_create")
+ api.symbol_get_name = try dlsym_required(dylib, symbol: "indexstore_symbol_get_name")
+ api.symbol_get_properties = try dlsym_required(dylib, symbol: "indexstore_symbol_get_properties")
+ api.symbol_get_kind = try dlsym_required(dylib, symbol: "indexstore_symbol_get_kind")
+ api.record_reader_occurrences_apply_f = try dlsym_required(dylib, symbol: "indexstore_record_reader_occurrences_apply_f")
+ api.occurrence_get_symbol = try dlsym_required(dylib, symbol: "indexstore_occurrence_get_symbol")
+ api.occurrence_relations_apply_f = try dlsym_required(dylib, symbol: "indexstore_occurrence_relations_apply_f")
+ api.symbol_relation_get_symbol = try dlsym_required(dylib, symbol: "indexstore_symbol_relation_get_symbol")
+ api.symbol_relation_get_roles = try dlsym_required(dylib, symbol: "indexstore_symbol_relation_get_roles")
+
+ self.fn = api
+ }
+
+ deinit {
+ // FIXME: is it safe to dlclose() indexstore? If so, do that here. For now, let the handle leak.
+ dylib.leak()
+ }
+}
+
+extension indexstore_string_ref_t {
+ fileprivate var str: String {
+ return String(
+ bytesNoCopy: UnsafeMutableRawPointer(mutating: data),
+ length: length,
+ encoding: .utf8,
+ freeWhenDone: false
+ )!
+ }
+}
diff --git a/Sources/SPMUtility/InterruptHandler.swift b/Sources/SPMUtility/InterruptHandler.swift
index 3eb32a29054..b7dd78b063b 100644
--- a/Sources/SPMUtility/InterruptHandler.swift
+++ b/Sources/SPMUtility/InterruptHandler.swift
@@ -14,8 +14,12 @@ import Basic
/// Interrupt signal handling global variables
private var wasInterrupted = false
private var wasInterruptedLock = Lock()
+#if os(Windows)
+private var signalWatchingPipe: [HANDLE] = [INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE]
+#else
private var signalWatchingPipe: [Int32] = [0, 0]
private var oldAction = sigaction()
+#endif
/// This class can be used by command line tools to install a handler which
/// should be called when a interrupt signal is delivered to the process.
@@ -23,19 +27,41 @@ public final class InterruptHandler {
/// The thread which waits to be notified when a signal is received.
let thread: Thread
+ #if os(Windows)
+ let signalHandler: @convention(c)(UInt32) -> Int32
+ #else
+ let signalHandler: @convention(c)(Int32) -> Void
+ #endif
/// Start watching for interrupt signal and call the handler whenever the signal is received.
public init(_ handler: @escaping () -> Void) throws {
// Create a signal handler.
- let signalHandler: @convention(c)(Int32) -> Void = { _ in
+ signalHandler = { _ in
// Turn on the interrupt bool.
wasInterruptedLock.withLock {
wasInterrupted = true
}
// Write on pipe to notify the watching thread.
var byte: UInt8 = 0
+ #if os(Windows)
+ var bytesWritten: DWORD = 0
+ WriteFile(signalWatchingPipe[1], &byte, 1, &bytesWritten, nil)
+ return TRUE
+ #else
write(signalWatchingPipe[1], &byte, 1)
+ #endif
}
+ #if os(Windows)
+ SetConsoleCtrlHandler(signalHandler, TRUE)
+
+ var readPipe: HANDLE?
+ var writePipe: HANDLE?
+ let rv = CreatePipe(&readPipe, &writePipe, nil, 1)
+ signalWatchingPipe = [readPipe!, writePipe!]
+ guard rv != FALSE else {
+ throw SystemError.pipe(rv)
+ }
+ #else
var action = sigaction()
#if canImport(Darwin)
action.__sigaction_u.__sa_handler = signalHandler
@@ -51,13 +77,19 @@ public final class InterruptHandler {
guard rv == 0 else {
throw SystemError.pipe(rv)
}
+ #endif
// This thread waits to be notified via pipe. If something is read from pipe, check the interrupt bool
// and send termination signal to all spawned processes in the process group.
thread = Thread {
while true {
var buf: Int8 = 0
+ #if os(Windows)
+ var n: DWORD = 0
+ ReadFile(signalWatchingPipe[1], &buf, 1, &n, nil)
+ #else
let n = read(signalWatchingPipe[0], &buf, 1)
+ #endif
// Pipe closed, nothing to do.
if n == 0 { break }
// Read the value of wasInterrupted and set it to false.
@@ -71,15 +103,24 @@ public final class InterruptHandler {
handler()
}
}
+ #if os(Windows)
+ CloseHandle(signalWatchingPipe[0])
+ #else
close(signalWatchingPipe[0])
+ #endif
}
thread.start()
}
deinit {
+ #if os(Windows)
+ SetConsoleCtrlHandler(signalHandler, FALSE)
+ CloseHandle(signalWatchingPipe[1])
+ #else
// Restore the old action and close the write end of pipe.
sigaction(SIGINT, &oldAction, nil)
close(signalWatchingPipe[1])
+ #endif
thread.join()
}
}
diff --git a/Sources/SPMUtility/dlopen.swift b/Sources/SPMUtility/dlopen.swift
new file mode 100644
index 00000000000..a36b00522a2
--- /dev/null
+++ b/Sources/SPMUtility/dlopen.swift
@@ -0,0 +1,116 @@
+/*
+ This source file is part of the Swift.org open source project
+
+ Copyright (c) 2019 Apple Inc. and the Swift project authors
+ Licensed under Apache License v2.0 with Runtime Library Exception
+
+ See http://swift.org/LICENSE.txt for license information
+ See http://swift.org/CONTRIBUTORS.txt for Swift project authors
+*/
+
+import SPMLibc
+
+public final class DLHandle {
+ #if os(Windows)
+ typealias Handle = HMODULE
+ #else
+ typealias Handle = UnsafeMutableRawPointer
+ #endif
+ var rawValue: Handle? = nil
+
+ init(rawValue: Handle) {
+ self.rawValue = rawValue
+ }
+
+ deinit {
+ precondition(rawValue == nil, "DLHandle must be closed or explicitly leaked before destroying")
+ }
+
+ public func close() throws {
+ if let handle = rawValue {
+ #if os(Windows)
+ guard FreeLibrary(handle) != 0 else {
+ throw DLError.close("Failed to FreeLibrary: \(GetLastError())")
+ }
+ #else
+ guard dlclose(handle) == 0 else {
+ throw DLError.close(dlerror() ?? "unknown error")
+ }
+ #endif
+ }
+ rawValue = nil
+ }
+
+ public func leak() {
+ rawValue = nil
+ }
+}
+
+public struct DLOpenFlags: RawRepresentable, OptionSet {
+
+ #if !os(Windows)
+ public static let lazy: DLOpenFlags = DLOpenFlags(rawValue: RTLD_LAZY)
+ public static let now: DLOpenFlags = DLOpenFlags(rawValue: RTLD_NOW)
+ public static let local: DLOpenFlags = DLOpenFlags(rawValue: RTLD_LOCAL)
+ public static let global: DLOpenFlags = DLOpenFlags(rawValue: RTLD_GLOBAL)
+
+ // Platform-specific flags.
+ #if os(macOS)
+ public static let first: DLOpenFlags = DLOpenFlags(rawValue: RTLD_FIRST)
+ public static let deepBind: DLOpenFlags = DLOpenFlags(rawValue: 0)
+ #else
+ public static let first: DLOpenFlags = DLOpenFlags(rawValue: 0)
+ public static let deepBind: DLOpenFlags = DLOpenFlags(rawValue: RTLD_DEEPBIND)
+ #endif
+ #endif
+
+ public var rawValue: Int32
+
+ public init(rawValue: Int32) {
+ self.rawValue = rawValue
+ }
+}
+
+public enum DLError: Swift.Error {
+ case `open`(String)
+ case close(String)
+}
+
+public func dlopen(_ path: String?, mode: DLOpenFlags) throws -> DLHandle {
+ #if os(Windows)
+ guard let handle = path?.withCString(encodedAs: UTF16.self, LoadLibraryW) else {
+ throw DLError.open("LoadLibraryW failed: \(GetLastError())")
+ }
+ #else
+ guard let handle = SPMLibc.dlopen(path, mode.rawValue) else {
+ throw DLError.open(dlerror() ?? "unknown error")
+ }
+ #endif
+ return DLHandle(rawValue: handle)
+}
+
+public func dlsym(_ handle: DLHandle, symbol: String) -> T? {
+ #if os(Windows)
+ guard let ptr = GetProcAddress(handle.rawValue!, symbol) else {
+ return nil
+ }
+ #else
+ guard let ptr = dlsym(handle.rawValue!, symbol) else {
+ return nil
+ }
+ #endif
+ return unsafeBitCast(ptr, to: T.self)
+}
+
+public func dlclose(_ handle: DLHandle) throws {
+ try handle.close()
+}
+
+#if !os(Windows)
+public func dlerror() -> String? {
+ if let err: UnsafeMutablePointer = dlerror() {
+ return String(cString: err)
+ }
+ return nil
+}
+#endif
diff --git a/Sources/Workspace/UserToolchain.swift b/Sources/Workspace/UserToolchain.swift
index 592a1d3bba6..6d7ada88bfd 100644
--- a/Sources/Workspace/UserToolchain.swift
+++ b/Sources/Workspace/UserToolchain.swift
@@ -19,6 +19,11 @@ private let whichArgs: [String] = ["xcrun", "--find"]
#else
private let whichArgs = ["which"]
#endif
+#if os(Windows)
+private let hostExecutableSuffix = ".exe"
+#else
+private let hostExecutableSuffix = ""
+#endif
/// Concrete object for manifest resource provider.
public struct UserManifestResources: ManifestResourceProvider {
@@ -56,7 +61,7 @@ public final class UserToolchain: Toolchain {
/// Path of the `swift` interpreter.
public var swiftInterpreter: AbsolutePath {
- return swiftCompiler.parentDirectory.appending(component: "swift")
+ return swiftCompiler.parentDirectory.appending(component: "swift" + hostExecutableSuffix)
}
/// Path to the xctest utility.
@@ -94,7 +99,7 @@ public final class UserToolchain: Toolchain {
func validateCompiler(at path: AbsolutePath?) throws {
guard let path = path else { return }
guard localFileSystem.isExecutableFile(path) else {
- throw InvalidToolchainDiagnostic("could not find the `swiftc` at expected path \(path)")
+ throw InvalidToolchainDiagnostic("could not find the `swiftc\(hostExecutableSuffix)` at expected path \(path)")
}
}
@@ -109,13 +114,13 @@ public final class UserToolchain: Toolchain {
// We require there is at least one valid swift compiler, either in the
// bin dir or SWIFT_EXEC.
let resolvedBinDirCompiler: AbsolutePath
- let binDirCompiler = binDir.appending(component: "swiftc")
+ let binDirCompiler = binDir.appending(component: "swiftc" + hostExecutableSuffix)
if localFileSystem.isExecutableFile(binDirCompiler) {
resolvedBinDirCompiler = binDirCompiler
} else if let SWIFT_EXEC = SWIFT_EXEC {
resolvedBinDirCompiler = SWIFT_EXEC
} else {
- throw InvalidToolchainDiagnostic("could not find the `swiftc` at expected path \(binDirCompiler)")
+ throw InvalidToolchainDiagnostic("could not find the `swiftc\(hostExecutableSuffix)` at expected path \(binDirCompiler)")
}
// The compiler for compilation tasks is SWIFT_EXEC or the bin dir compiler.
@@ -143,30 +148,35 @@ public final class UserToolchain: Toolchain {
return toolPath
}
- // Otherwise, lookup the tool on the system.
+ // Then, check the toolchain.
+ do {
+ let toolPath = destination.binDir.appending(component: "clang" + hostExecutableSuffix)
+ if localFileSystem.exists(toolPath) {
+ _clangCompiler = toolPath
+ return toolPath
+ }
+ }
+
+ // Otherwise, lookup it up on the system.
let arguments = whichArgs + ["clang"]
let foundPath = try Process.checkNonZeroExit(arguments: arguments, environment: processEnvironment).spm_chomp()
guard !foundPath.isEmpty else {
throw InvalidToolchainDiagnostic("could not find clang")
}
let toolPath = try AbsolutePath(validating: foundPath)
-
- // If we found clang using xcrun, assume the vendor is Apple.
- // FIXME: This might not be the best way to determine this.
- #if os(macOS)
- __isClangCompilerVendorApple = true
- #endif
-
_clangCompiler = toolPath
return toolPath
}
private var _clangCompiler: AbsolutePath?
- private var __isClangCompilerVendorApple: Bool?
public func _isClangCompilerVendorApple() throws -> Bool? {
- // The boolean gets computed as a side-effect of lookup for clang compiler.
- _ = try getClangCompiler()
- return __isClangCompilerVendorApple
+ // Assume the vendor is Apple on macOS.
+ // FIXME: This might not be the best way to determine this.
+ #if os(macOS)
+ return true
+ #else
+ return false
+ #endif
}
/// Returns the path to llvm-cov tool.
diff --git a/Sources/clibc/include/clibc.h b/Sources/clibc/include/clibc.h
index 7cf808c182a..8a90bffafd1 100644
--- a/Sources/clibc/include/clibc.h
+++ b/Sources/clibc/include/clibc.h
@@ -1,5 +1,3 @@
-#include
-
#if defined(__linux__)
#include
#endif
diff --git a/Sources/clibc/include/indexstore_functions.h b/Sources/clibc/include/indexstore_functions.h
new file mode 100644
index 00000000000..cc2ca2acbe1
--- /dev/null
+++ b/Sources/clibc/include/indexstore_functions.h
@@ -0,0 +1,561 @@
+/*===-- indexstore/indexstore_functions.h - Index Store C API ------- C -*-===*\
+|* *|
+|* The LLVM Compiler Infrastructure *|
+|* *|
+|* This file is distributed under the University of Illinois Open Source *|
+|* License. See LICENSE.TXT for details. *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* Shim version of indexstore.h suitable for using with dlopen. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef INDEXSTOREDB_INDEXSTORE_INDEXSTORE_FUNCTIONS_H
+#define INDEXSTOREDB_INDEXSTORE_INDEXSTORE_FUNCTIONS_H
+
+#include
+#include
+#include
+#include
+
+/**
+ * \brief The version constants for the Index Store C API.
+ * INDEXSTORE_VERSION_MINOR should increase when there are API additions.
+ * INDEXSTORE_VERSION_MAJOR is intended for "major" source/ABI breaking changes.
+ */
+#define INDEXSTORE_VERSION_MAJOR 0
+#define INDEXSTORE_VERSION_MINOR 11
+
+#define INDEXSTORE_VERSION_ENCODE(major, minor) ( \
+ ((major) * 10000) \
+ + ((minor) * 1))
+
+#define INDEXSTORE_VERSION INDEXSTORE_VERSION_ENCODE( \
+ INDEXSTORE_VERSION_MAJOR, \
+ INDEXSTORE_VERSION_MINOR )
+
+#define INDEXSTORE_VERSION_STRINGIZE_(major, minor) \
+ #major"."#minor
+#define INDEXSTORE_VERSION_STRINGIZE(major, minor) \
+ INDEXSTORE_VERSION_STRINGIZE_(major, minor)
+
+#define INDEXSTORE_VERSION_STRING INDEXSTORE_VERSION_STRINGIZE( \
+ INDEXSTORE_VERSION_MAJOR, \
+ INDEXSTORE_VERSION_MINOR)
+
+// Workaround a modules issue with time_t on linux.
+#if __has_include()
+#include
+#endif
+
+#ifdef __cplusplus
+# define INDEXSTORE_BEGIN_DECLS extern "C" {
+# define INDEXSTORE_END_DECLS }
+#else
+# define INDEXSTORE_BEGIN_DECLS
+# define INDEXSTORE_END_DECLS
+#endif
+
+#ifndef INDEXSTORE_PUBLIC
+# if defined (_MSC_VER)
+# define INDEXSTORE_PUBLIC __declspec(dllimport)
+# else
+# define INDEXSTORE_PUBLIC
+# endif
+#endif
+
+#ifndef __has_feature
+# define __has_feature(x) 0
+#endif
+
+// FIXME: we need a runtime check as well since the library may have been built
+// without blocks support.
+#if __has_feature(blocks) && defined(__APPLE__)
+# define INDEXSTORE_HAS_BLOCKS 1
+#else
+# define INDEXSTORE_HAS_BLOCKS 0
+#endif
+
+INDEXSTORE_BEGIN_DECLS
+
+typedef void *indexstore_error_t;
+
+typedef struct {
+ const char *data;
+ size_t length;
+} indexstore_string_ref_t;
+
+typedef void *indexstore_t;
+
+typedef void *indexstore_unit_event_notification_t;
+typedef void *indexstore_unit_event_t;
+
+typedef enum {
+ INDEXSTORE_UNIT_EVENT_ADDED = 1,
+ INDEXSTORE_UNIT_EVENT_REMOVED = 2,
+ INDEXSTORE_UNIT_EVENT_MODIFIED = 3,
+ INDEXSTORE_UNIT_EVENT_DIRECTORY_DELETED = 4,
+} indexstore_unit_event_kind_t;
+
+typedef struct {
+ /// If true, \c indexstore_store_start_unit_event_listening will block until
+ /// the initial set of units is passed to the unit event handler, otherwise
+ /// the function will return and the initial set will be passed asynchronously.
+ bool wait_initial_sync;
+} indexstore_unit_event_listen_options_t;
+
+typedef void *indexstore_symbol_t;
+
+typedef enum {
+ INDEXSTORE_SYMBOL_KIND_UNKNOWN = 0,
+ INDEXSTORE_SYMBOL_KIND_MODULE = 1,
+ INDEXSTORE_SYMBOL_KIND_NAMESPACE = 2,
+ INDEXSTORE_SYMBOL_KIND_NAMESPACEALIAS = 3,
+ INDEXSTORE_SYMBOL_KIND_MACRO = 4,
+ INDEXSTORE_SYMBOL_KIND_ENUM = 5,
+ INDEXSTORE_SYMBOL_KIND_STRUCT = 6,
+ INDEXSTORE_SYMBOL_KIND_CLASS = 7,
+ INDEXSTORE_SYMBOL_KIND_PROTOCOL = 8,
+ INDEXSTORE_SYMBOL_KIND_EXTENSION = 9,
+ INDEXSTORE_SYMBOL_KIND_UNION = 10,
+ INDEXSTORE_SYMBOL_KIND_TYPEALIAS = 11,
+ INDEXSTORE_SYMBOL_KIND_FUNCTION = 12,
+ INDEXSTORE_SYMBOL_KIND_VARIABLE = 13,
+ INDEXSTORE_SYMBOL_KIND_FIELD = 14,
+ INDEXSTORE_SYMBOL_KIND_ENUMCONSTANT = 15,
+ INDEXSTORE_SYMBOL_KIND_INSTANCEMETHOD = 16,
+ INDEXSTORE_SYMBOL_KIND_CLASSMETHOD = 17,
+ INDEXSTORE_SYMBOL_KIND_STATICMETHOD = 18,
+ INDEXSTORE_SYMBOL_KIND_INSTANCEPROPERTY = 19,
+ INDEXSTORE_SYMBOL_KIND_CLASSPROPERTY = 20,
+ INDEXSTORE_SYMBOL_KIND_STATICPROPERTY = 21,
+ INDEXSTORE_SYMBOL_KIND_CONSTRUCTOR = 22,
+ INDEXSTORE_SYMBOL_KIND_DESTRUCTOR = 23,
+ INDEXSTORE_SYMBOL_KIND_CONVERSIONFUNCTION = 24,
+ INDEXSTORE_SYMBOL_KIND_PARAMETER = 25,
+ INDEXSTORE_SYMBOL_KIND_USING = 26,
+
+ INDEXSTORE_SYMBOL_KIND_COMMENTTAG = 1000,
+} indexstore_symbol_kind_t;
+
+typedef enum {
+ INDEXSTORE_SYMBOL_SUBKIND_NONE = 0,
+ INDEXSTORE_SYMBOL_SUBKIND_CXXCOPYCONSTRUCTOR = 1,
+ INDEXSTORE_SYMBOL_SUBKIND_CXXMOVECONSTRUCTOR = 2,
+ INDEXSTORE_SYMBOL_SUBKIND_ACCESSORGETTER = 3,
+ INDEXSTORE_SYMBOL_SUBKIND_ACCESSORSETTER = 4,
+ INDEXSTORE_SYMBOL_SUBKIND_USINGTYPENAME = 5,
+ INDEXSTORE_SYMBOL_SUBKIND_USINGVALUE = 6,
+
+ INDEXSTORE_SYMBOL_SUBKIND_SWIFTACCESSORWILLSET = 1000,
+ INDEXSTORE_SYMBOL_SUBKIND_SWIFTACCESSORDIDSET = 1001,
+ INDEXSTORE_SYMBOL_SUBKIND_SWIFTACCESSORADDRESSOR = 1002,
+ INDEXSTORE_SYMBOL_SUBKIND_SWIFTACCESSORMUTABLEADDRESSOR = 1003,
+ INDEXSTORE_SYMBOL_SUBKIND_SWIFTEXTENSIONOFSTRUCT = 1004,
+ INDEXSTORE_SYMBOL_SUBKIND_SWIFTEXTENSIONOFCLASS = 1005,
+ INDEXSTORE_SYMBOL_SUBKIND_SWIFTEXTENSIONOFENUM = 1006,
+ INDEXSTORE_SYMBOL_SUBKIND_SWIFTEXTENSIONOFPROTOCOL = 1007,
+ INDEXSTORE_SYMBOL_SUBKIND_SWIFTPREFIXOPERATOR = 1008,
+ INDEXSTORE_SYMBOL_SUBKIND_SWIFTPOSTFIXOPERATOR = 1009,
+ INDEXSTORE_SYMBOL_SUBKIND_SWIFTINFIXOPERATOR = 1010,
+ INDEXSTORE_SYMBOL_SUBKIND_SWIFTSUBSCRIPT = 1011,
+ INDEXSTORE_SYMBOL_SUBKIND_SWIFTASSOCIATEDTYPE = 1012,
+ INDEXSTORE_SYMBOL_SUBKIND_SWIFTGENERICTYPEPARAM = 1013,
+ INDEXSTORE_SYMBOL_SUBKIND_SWIFTACCESSORREAD = 1014,
+ INDEXSTORE_SYMBOL_SUBKIND_SWIFTACCESSORMODIFY = 1015,
+} indexstore_symbol_subkind_t;
+
+typedef enum {
+ INDEXSTORE_SYMBOL_PROPERTY_GENERIC = 1 << 0,
+ INDEXSTORE_SYMBOL_PROPERTY_TEMPLATE_PARTIAL_SPECIALIZATION = 1 << 1,
+ INDEXSTORE_SYMBOL_PROPERTY_TEMPLATE_SPECIALIZATION = 1 << 2,
+ INDEXSTORE_SYMBOL_PROPERTY_UNITTEST = 1 << 3,
+ INDEXSTORE_SYMBOL_PROPERTY_IBANNOTATED = 1 << 4,
+ INDEXSTORE_SYMBOL_PROPERTY_IBOUTLETCOLLECTION = 1 << 5,
+ INDEXSTORE_SYMBOL_PROPERTY_GKINSPECTABLE = 1 << 6,
+ INDEXSTORE_SYMBOL_PROPERTY_LOCAL = 1 << 7,
+ INDEXSTORE_SYMBOL_PROPERTY_PROTOCOL_INTERFACE = 1 << 8,
+} indexstore_symbol_property_t;
+
+typedef enum {
+ INDEXSTORE_SYMBOL_LANG_C = 0,
+ INDEXSTORE_SYMBOL_LANG_OBJC = 1,
+ INDEXSTORE_SYMBOL_LANG_CXX = 2,
+
+ INDEXSTORE_SYMBOL_LANG_SWIFT = 100,
+} indexstore_symbol_language_t;
+
+typedef enum {
+ INDEXSTORE_SYMBOL_ROLE_DECLARATION = 1 << 0,
+ INDEXSTORE_SYMBOL_ROLE_DEFINITION = 1 << 1,
+ INDEXSTORE_SYMBOL_ROLE_REFERENCE = 1 << 2,
+ INDEXSTORE_SYMBOL_ROLE_READ = 1 << 3,
+ INDEXSTORE_SYMBOL_ROLE_WRITE = 1 << 4,
+ INDEXSTORE_SYMBOL_ROLE_CALL = 1 << 5,
+ INDEXSTORE_SYMBOL_ROLE_DYNAMIC = 1 << 6,
+ INDEXSTORE_SYMBOL_ROLE_ADDRESSOF = 1 << 7,
+ INDEXSTORE_SYMBOL_ROLE_IMPLICIT = 1 << 8,
+ INDEXSTORE_SYMBOL_ROLE_UNDEFINITION = 1 << 19,
+
+ // Relation roles.
+ INDEXSTORE_SYMBOL_ROLE_REL_CHILDOF = 1 << 9,
+ INDEXSTORE_SYMBOL_ROLE_REL_BASEOF = 1 << 10,
+ INDEXSTORE_SYMBOL_ROLE_REL_OVERRIDEOF = 1 << 11,
+ INDEXSTORE_SYMBOL_ROLE_REL_RECEIVEDBY = 1 << 12,
+ INDEXSTORE_SYMBOL_ROLE_REL_CALLEDBY = 1 << 13,
+ INDEXSTORE_SYMBOL_ROLE_REL_EXTENDEDBY = 1 << 14,
+ INDEXSTORE_SYMBOL_ROLE_REL_ACCESSOROF = 1 << 15,
+ INDEXSTORE_SYMBOL_ROLE_REL_CONTAINEDBY = 1 << 16,
+ INDEXSTORE_SYMBOL_ROLE_REL_IBTYPEOF = 1 << 17,
+ INDEXSTORE_SYMBOL_ROLE_REL_SPECIALIZATIONOF = 1 << 18,
+} indexstore_symbol_role_t;
+
+typedef void *indexstore_unit_dependency_t;
+typedef void *indexstore_unit_include_t;
+
+typedef enum {
+ INDEXSTORE_UNIT_DEPENDENCY_UNIT = 1,
+ INDEXSTORE_UNIT_DEPENDENCY_RECORD = 2,
+ INDEXSTORE_UNIT_DEPENDENCY_FILE = 3,
+} indexstore_unit_dependency_kind_t;
+
+typedef void *indexstore_symbol_relation_t;
+
+typedef void *indexstore_occurrence_t;
+
+typedef void *indexstore_record_reader_t;
+
+typedef void *indexstore_unit_reader_t;
+
+#if INDEXSTORE_HAS_BLOCKS
+typedef void (^indexstore_unit_event_handler_t)(indexstore_unit_event_notification_t);
+#endif
+
+typedef struct {
+ INDEXSTORE_PUBLIC const char *
+ (*error_get_description)(indexstore_error_t);
+
+ INDEXSTORE_PUBLIC void
+ (*error_dispose)(indexstore_error_t);
+
+ INDEXSTORE_PUBLIC unsigned
+ (*format_version)(void);
+
+ INDEXSTORE_PUBLIC indexstore_t
+ (*store_create)(const char *store_path, indexstore_error_t *error);
+
+ INDEXSTORE_PUBLIC void
+ (*store_dispose)(indexstore_t);
+
+ #if INDEXSTORE_HAS_BLOCKS
+ INDEXSTORE_PUBLIC bool
+ (*store_units_apply)(indexstore_t, unsigned sorted,
+ bool(^applier)(indexstore_string_ref_t unit_name));
+ #endif
+
+ INDEXSTORE_PUBLIC bool
+ (*store_units_apply_f)(indexstore_t, unsigned sorted,
+ void *context,
+ bool(*applier)(void *context, indexstore_string_ref_t unit_name));
+
+ INDEXSTORE_PUBLIC size_t
+ (*unit_event_notification_get_events_count)(indexstore_unit_event_notification_t);
+
+ INDEXSTORE_PUBLIC indexstore_unit_event_t
+ (*unit_event_notification_get_event)(indexstore_unit_event_notification_t, size_t index);
+
+ INDEXSTORE_PUBLIC bool
+ (*unit_event_notification_is_initial)(indexstore_unit_event_notification_t);
+
+ INDEXSTORE_PUBLIC indexstore_unit_event_kind_t
+ (*unit_event_get_kind)(indexstore_unit_event_t);
+
+ INDEXSTORE_PUBLIC indexstore_string_ref_t
+ (*unit_event_get_unit_name)(indexstore_unit_event_t);
+
+ INDEXSTORE_PUBLIC struct timespec
+ (*unit_event_get_modification_time)(indexstore_unit_event_t);
+
+
+ #if INDEXSTORE_HAS_BLOCKS
+ INDEXSTORE_PUBLIC void
+ (*store_set_unit_event_handler)(indexstore_t,
+ indexstore_unit_event_handler_t handler);
+ #endif
+
+ INDEXSTORE_PUBLIC void
+ (*store_set_unit_event_handler_f)(indexstore_t, void *context,
+ void(*handler)(void *context, indexstore_unit_event_notification_t),
+ void(*finalizer)(void *context));
+
+ INDEXSTORE_PUBLIC bool
+ (*store_start_unit_event_listening)(indexstore_t,
+ indexstore_unit_event_listen_options_t *,
+ size_t listen_options_struct_size,
+ indexstore_error_t *error);
+
+ INDEXSTORE_PUBLIC void
+ (*store_stop_unit_event_listening)(indexstore_t);
+
+ INDEXSTORE_PUBLIC void
+ (*store_discard_unit)(indexstore_t, const char *unit_name);
+
+ INDEXSTORE_PUBLIC void
+ (*store_discard_record)(indexstore_t, const char *record_name);
+
+ INDEXSTORE_PUBLIC void
+ (*store_purge_stale_data)(indexstore_t);
+
+ /// Determines the unit name from the \c output_path and writes it out in the
+ /// \c name_buf buffer. It doesn't write more than \c buf_size.
+ /// \returns the length of the name. If this is larger than \c buf_size, the
+ /// caller should call the function again with a buffer of the appropriate size.
+ INDEXSTORE_PUBLIC size_t
+ (*store_get_unit_name_from_output_path)(indexstore_t store,
+ const char *output_path,
+ char *name_buf,
+ size_t buf_size);
+
+ /// \returns true if an error occurred, false otherwise.
+ INDEXSTORE_PUBLIC bool
+ (*store_get_unit_modification_time)(indexstore_t store,
+ const char *unit_name,
+ int64_t *seconds,
+ int64_t *nanoseconds,
+ indexstore_error_t *error);
+
+
+ INDEXSTORE_PUBLIC indexstore_symbol_language_t
+ (*symbol_get_language)(indexstore_symbol_t);
+
+ INDEXSTORE_PUBLIC indexstore_symbol_kind_t
+ (*symbol_get_kind)(indexstore_symbol_t);
+
+ INDEXSTORE_PUBLIC indexstore_symbol_subkind_t
+ (*symbol_get_subkind)(indexstore_symbol_t);
+
+ INDEXSTORE_PUBLIC uint64_t
+ (*symbol_get_properties)(indexstore_symbol_t);
+
+ INDEXSTORE_PUBLIC uint64_t
+ (*symbol_get_roles)(indexstore_symbol_t);
+
+ INDEXSTORE_PUBLIC uint64_t
+ (*symbol_get_related_roles)(indexstore_symbol_t);
+
+ INDEXSTORE_PUBLIC indexstore_string_ref_t
+ (*symbol_get_name)(indexstore_symbol_t);
+
+ INDEXSTORE_PUBLIC indexstore_string_ref_t
+ (*symbol_get_usr)(indexstore_symbol_t);
+
+ INDEXSTORE_PUBLIC indexstore_string_ref_t
+ (*symbol_get_codegen_name)(indexstore_symbol_t);
+
+ INDEXSTORE_PUBLIC uint64_t
+ (*symbol_relation_get_roles)(indexstore_symbol_relation_t);
+
+ INDEXSTORE_PUBLIC indexstore_symbol_t
+ (*symbol_relation_get_symbol)(indexstore_symbol_relation_t);
+
+ INDEXSTORE_PUBLIC indexstore_symbol_t
+ (*occurrence_get_symbol)(indexstore_occurrence_t);
+
+ #if INDEXSTORE_HAS_BLOCKS
+ INDEXSTORE_PUBLIC bool
+ (*occurrence_relations_apply)(indexstore_occurrence_t,
+ bool(^applier)(indexstore_symbol_relation_t symbol_rel));
+ #endif
+
+ INDEXSTORE_PUBLIC bool
+ (*occurrence_relations_apply_f)(indexstore_occurrence_t,
+ void *context,
+ bool(*applier)(void *context, indexstore_symbol_relation_t symbol_rel));
+
+ INDEXSTORE_PUBLIC uint64_t
+ (*occurrence_get_roles)(indexstore_occurrence_t);
+
+ INDEXSTORE_PUBLIC void
+ (*occurrence_get_line_col)(indexstore_occurrence_t,
+ unsigned *line, unsigned *column);
+
+ INDEXSTORE_PUBLIC indexstore_record_reader_t
+ (*record_reader_create)(indexstore_t store, const char *record_name,
+ indexstore_error_t *error);
+
+ INDEXSTORE_PUBLIC void
+ (*record_reader_dispose)(indexstore_record_reader_t);
+
+ #if INDEXSTORE_HAS_BLOCKS
+ /// Goes through the symbol data and passes symbols to \c receiver, for the
+ /// symbol data that \c filter returns true on.
+ ///
+ /// This allows allocating memory only for the record symbols that the caller is
+ /// interested in.
+ INDEXSTORE_PUBLIC bool
+ (*record_reader_search_symbols)(indexstore_record_reader_t,
+ bool(^filter)(indexstore_symbol_t symbol, bool *stop),
+ void(^receiver)(indexstore_symbol_t symbol));
+
+ /// \param nocache if true, avoids allocating memory for the symbols.
+ /// Useful when the caller does not intend to keep \c indexstore_record_reader_t
+ /// for more queries.
+ INDEXSTORE_PUBLIC bool
+ (*record_reader_symbols_apply)(indexstore_record_reader_t,
+ bool nocache,
+ bool(^applier)(indexstore_symbol_t symbol));
+
+ INDEXSTORE_PUBLIC bool
+ (*record_reader_occurrences_apply)(indexstore_record_reader_t,
+ bool(^applier)(indexstore_occurrence_t occur));
+
+ INDEXSTORE_PUBLIC bool
+ (*record_reader_occurrences_in_line_range_apply)(indexstore_record_reader_t,
+ unsigned line_start,
+ unsigned line_count,
+ bool(^applier)(indexstore_occurrence_t occur));
+
+ /// \param symbols if non-zero \c symbols_count, indicates the list of symbols
+ /// that we want to get occurrences for. An empty array indicates that we want
+ /// occurrences for all symbols.
+ /// \param related_symbols Same as \c symbols but for related symbols.
+ INDEXSTORE_PUBLIC bool
+ (*record_reader_occurrences_of_symbols_apply)(indexstore_record_reader_t,
+ indexstore_symbol_t *symbols, size_t symbols_count,
+ indexstore_symbol_t *related_symbols, size_t related_symbols_count,
+ bool(^applier)(indexstore_occurrence_t occur));
+ #endif
+
+ INDEXSTORE_PUBLIC bool
+ (*record_reader_search_symbols_f)(indexstore_record_reader_t,
+ void *filter_ctx,
+ bool(*filter)(void *filter_ctx, indexstore_symbol_t symbol, bool *stop),
+ void *receiver_ctx,
+ void(*receiver)(void *receiver_ctx, indexstore_symbol_t symbol));
+
+ INDEXSTORE_PUBLIC bool
+ (*record_reader_symbols_apply_f)(indexstore_record_reader_t,
+ bool nocache,
+ void *context,
+ bool(*applier)(void *context, indexstore_symbol_t symbol));
+
+ INDEXSTORE_PUBLIC bool
+ (*record_reader_occurrences_apply_f)(indexstore_record_reader_t,
+ void *context,
+ bool(*applier)(void *context, indexstore_occurrence_t occur));
+
+ INDEXSTORE_PUBLIC bool
+ (*record_reader_occurrences_in_line_range_apply_f)(indexstore_record_reader_t,
+ unsigned line_start,
+ unsigned line_count,
+ void *context,
+ bool(*applier)(void *context, indexstore_occurrence_t occur));
+
+ INDEXSTORE_PUBLIC bool
+ (*record_reader_occurrences_of_symbols_apply_f)(indexstore_record_reader_t,
+ indexstore_symbol_t *symbols, size_t symbols_count,
+ indexstore_symbol_t *related_symbols, size_t related_symbols_count,
+ void *context,
+ bool(*applier)(void *context, indexstore_occurrence_t occur));
+
+
+ INDEXSTORE_PUBLIC indexstore_unit_reader_t
+ (*unit_reader_create)(indexstore_t store, const char *unit_name,
+ indexstore_error_t *error);
+
+ void
+ (*unit_reader_dispose)(indexstore_unit_reader_t);
+
+ INDEXSTORE_PUBLIC indexstore_string_ref_t
+ (*unit_reader_get_provider_identifier)(indexstore_unit_reader_t);
+
+ INDEXSTORE_PUBLIC indexstore_string_ref_t
+ (*unit_reader_get_provider_version)(indexstore_unit_reader_t);
+
+ INDEXSTORE_PUBLIC void
+ (*unit_reader_get_modification_time)(indexstore_unit_reader_t,
+ int64_t *seconds,
+ int64_t *nanoseconds);
+
+ INDEXSTORE_PUBLIC bool
+ (*unit_reader_is_system_unit)(indexstore_unit_reader_t);
+
+ INDEXSTORE_PUBLIC bool
+ (*unit_reader_is_module_unit)(indexstore_unit_reader_t);
+
+ INDEXSTORE_PUBLIC bool
+ (*unit_reader_is_debug_compilation)(indexstore_unit_reader_t);
+
+ INDEXSTORE_PUBLIC bool
+ (*unit_reader_has_main_file)(indexstore_unit_reader_t);
+
+ INDEXSTORE_PUBLIC indexstore_string_ref_t
+ (*unit_reader_get_main_file)(indexstore_unit_reader_t);
+
+ INDEXSTORE_PUBLIC indexstore_string_ref_t
+ (*unit_reader_get_module_name)(indexstore_unit_reader_t);
+
+ INDEXSTORE_PUBLIC indexstore_string_ref_t
+ (*unit_reader_get_working_dir)(indexstore_unit_reader_t);
+
+ INDEXSTORE_PUBLIC indexstore_string_ref_t
+ (*unit_reader_get_output_file)(indexstore_unit_reader_t);
+
+ INDEXSTORE_PUBLIC indexstore_string_ref_t
+ (*unit_reader_get_sysroot_path)(indexstore_unit_reader_t);
+
+ INDEXSTORE_PUBLIC indexstore_string_ref_t
+ (*unit_reader_get_target)(indexstore_unit_reader_t);
+
+
+ INDEXSTORE_PUBLIC indexstore_unit_dependency_kind_t
+ (*unit_dependency_get_kind)(indexstore_unit_dependency_t);
+
+ INDEXSTORE_PUBLIC bool
+ (*unit_dependency_is_system)(indexstore_unit_dependency_t);
+
+ INDEXSTORE_PUBLIC indexstore_string_ref_t
+ (*unit_dependency_get_filepath)(indexstore_unit_dependency_t);
+
+ INDEXSTORE_PUBLIC indexstore_string_ref_t
+ (*unit_dependency_get_modulename)(indexstore_unit_dependency_t);
+
+ INDEXSTORE_PUBLIC indexstore_string_ref_t
+ (*unit_dependency_get_name)(indexstore_unit_dependency_t);
+
+ INDEXSTORE_PUBLIC indexstore_string_ref_t
+ (*unit_include_get_source_path)(indexstore_unit_include_t);
+
+ INDEXSTORE_PUBLIC indexstore_string_ref_t
+ (*unit_include_get_target_path)(indexstore_unit_include_t);
+
+ INDEXSTORE_PUBLIC unsigned
+ (*unit_include_get_source_line)(indexstore_unit_include_t);
+
+ #if INDEXSTORE_HAS_BLOCKS
+ INDEXSTORE_PUBLIC bool
+ (*unit_reader_dependencies_apply)(indexstore_unit_reader_t,
+ bool(^applier)(indexstore_unit_dependency_t));
+
+ INDEXSTORE_PUBLIC bool
+ (*unit_reader_includes_apply)(indexstore_unit_reader_t,
+ bool(^applier)(indexstore_unit_include_t));
+ #endif
+
+ INDEXSTORE_PUBLIC bool
+ (*unit_reader_dependencies_apply_f)(indexstore_unit_reader_t,
+ void *context,
+ bool(*applier)(void *context, indexstore_unit_dependency_t));
+
+ INDEXSTORE_PUBLIC bool
+ (*unit_reader_includes_apply_f)(indexstore_unit_reader_t,
+ void *context,
+ bool(*applier)(void *context, indexstore_unit_include_t));
+
+} indexstore_functions_t;
+
+
+INDEXSTORE_END_DECLS
+
+#endif
diff --git a/Sources/clibc/include/module.modulemap b/Sources/clibc/include/module.modulemap
index b276387c7a1..2f908650dde 100644
--- a/Sources/clibc/include/module.modulemap
+++ b/Sources/clibc/include/module.modulemap
@@ -1,4 +1,5 @@
module clibc {
header "clibc.h"
+ header "indexstore_functions.h"
export *
}
diff --git a/Tests/BasicTests/FileSystemTests.swift b/Tests/BasicTests/FileSystemTests.swift
index f440cb7d699..7d6bc49a69c 100644
--- a/Tests/BasicTests/FileSystemTests.swift
+++ b/Tests/BasicTests/FileSystemTests.swift
@@ -29,7 +29,7 @@ class FileSystemTests: XCTestCase {
let file = try! TemporaryFile()
XCTAssertTrue(fs.exists(file.path))
XCTAssertTrue(fs.isFile(file.path))
- XCTAssertEqual(try fs.getFileInfo(file.path).kind, .file)
+ XCTAssertEqual(try fs.getFileInfo(file.path).fileType, .typeRegular)
XCTAssertFalse(fs.isDirectory(file.path))
XCTAssertFalse(fs.isFile(AbsolutePath("/does-not-exist")))
XCTAssertFalse(fs.isSymlink(AbsolutePath("/does-not-exist")))
@@ -41,7 +41,7 @@ class FileSystemTests: XCTestCase {
try! createSymlink(sym, pointingAt: file.path)
XCTAssertTrue(fs.isSymlink(sym))
XCTAssertTrue(fs.isFile(sym))
- XCTAssertEqual(try fs.getFileInfo(sym).kind, .file)
+ XCTAssertEqual(try fs.getFileInfo(sym).fileType, .typeSymbolicLink)
XCTAssertFalse(fs.isDirectory(sym))
// isExecutableFile
@@ -388,7 +388,7 @@ class FileSystemTests: XCTestCase {
}
func testSetAttribute() throws {
- #if os(macOS)
+ #if os(macOS) || os(Linux)
mktmpdir { path in
let fs = Basic.localFileSystem
diff --git a/Tests/UtilityTests/ArgumentParserTests.swift b/Tests/UtilityTests/ArgumentParserTests.swift
index b440794517f..eaffcd1ae7a 100644
--- a/Tests/UtilityTests/ArgumentParserTests.swift
+++ b/Tests/UtilityTests/ArgumentParserTests.swift
@@ -120,8 +120,24 @@ class ArgumentParserTests: XCTestCase {
do {
_ = try parser.parse(["foo", "--bar"])
XCTFail("unexpected success")
- } catch ArgumentParserError.unknownOption(let option) {
+ } catch ArgumentParserError.unknownOption(let option, let suggestion) {
XCTAssertEqual(option, "--bar")
+ XCTAssertNil(suggestion)
+ }
+
+ do {
+ _ = try parser.parse(["--food"])
+ XCTFail("unexpected success")
+ } catch ArgumentParserError.unknownOption(let option, let suggestion) {
+ XCTAssertEqual(option, "--food")
+ XCTAssertEqual(suggestion, "--foo")
+ }
+ do {
+ _ = try parser.parse(["--verb"])
+ XCTFail("unexpected success")
+ } catch ArgumentParserError.unknownOption(let option, let suggestion) {
+ XCTAssertEqual(option, "--verb")
+ XCTAssertNil(suggestion)
}
do {
@@ -286,19 +302,19 @@ class ArgumentParserTests: XCTestCase {
do {
args = try parser.parse(["--foo", "foo", "b", "--no-fly", "--branch", "bugfix"])
- } catch ArgumentParserError.unknownOption(let arg) {
+ } catch ArgumentParserError.unknownOption(let arg, _) {
XCTAssertEqual(arg, "--branch")
}
do {
args = try parser.parse(["--foo", "foo", "a", "--branch", "bugfix", "--no-fly"])
- } catch ArgumentParserError.unknownOption(let arg) {
+ } catch ArgumentParserError.unknownOption(let arg, _) {
XCTAssertEqual(arg, "--no-fly")
}
do {
args = try parser.parse(["a", "--branch", "bugfix", "--foo"])
- } catch ArgumentParserError.unknownOption(let arg) {
+ } catch ArgumentParserError.unknownOption(let arg, _) {
XCTAssertEqual(arg, "--foo")
}
@@ -374,7 +390,7 @@ class ArgumentParserTests: XCTestCase {
do {
args = try parser.parse(["foo", "bar", "--no-fly"])
- } catch ArgumentParserError.unknownOption(let arg) {
+ } catch ArgumentParserError.unknownOption(let arg, _) {
XCTAssertEqual(arg, "--no-fly")
}
}
@@ -717,11 +733,23 @@ class ArgumentParserTests: XCTestCase {
do {
_ = try parser.parse(["-18"])
XCTFail("unexpected success")
- } catch ArgumentParserError.unknownOption(let option) {
+ } catch ArgumentParserError.unknownOption(let option, _) {
XCTAssertEqual(option, "-18")
}
args = try parser.parse(["0"])
XCTAssertEqual(args.get(positional), 0)
}
+
+ func testSingleValueMultipleTimes() throws {
+ let parser = ArgumentParser(usage: "sample", overview: "sample")
+ _ = parser.add(option: "--verbosity", kind: Int.self)
+
+ do {
+ _ = try parser.parse(["--verbosity", "5", "--verbosity", "6"])
+ XCTFail("unexpected success")
+ } catch ArgumentParserError.duplicateArgument(let argument) {
+ XCTAssertEqual(argument, "--verbosity")
+ }
+ }
}
diff --git a/Tests/UtilityTests/XCTestManifests.swift b/Tests/UtilityTests/XCTestManifests.swift
index 58841b468e0..58f489e9241 100644
--- a/Tests/UtilityTests/XCTestManifests.swift
+++ b/Tests/UtilityTests/XCTestManifests.swift
@@ -16,6 +16,7 @@ extension ArgumentParserTests {
("testPathArgument", testPathArgument),
("testRemainingStrategy", testRemainingStrategy),
("testShellCompletionGeneration", testShellCompletionGeneration),
+ ("testSingleValueMultipleTimes", testSingleValueMultipleTimes),
("testSubparser", testSubparser),
("testSubparserBinder", testSubparserBinder),
("testSubsubparser", testSubsubparser),
diff --git a/Utilities/bootstrap b/Utilities/bootstrap
index 3f29d57f143..b6343c3f8f9 100755
--- a/Utilities/bootstrap
+++ b/Utilities/bootstrap
@@ -306,7 +306,7 @@ class Target(object):
link_input_nodes.append(object_path)
- args = ["clang"]
+ args = [args.clang_path]
args.extend(common_args)
args.extend([deps_path, "-c", source,"-o", object_path])
@@ -734,6 +734,20 @@ def get_llbuild_source_path():
note("clone llbuild next to swiftpm directory; see development docs: https://github.com/apple/swift-package-manager/blob/master/Documentation/Development.md#using-trunk-snapshot")
error("unable to find llbuild source directory at %s" % llbuild_path)
+def get_clang_path():
+ try:
+ if os.getenv("CC"):
+ clang_path=os.path.realpath(os.getenv("CC"))
+ return clang_path
+ elif platform.system() == 'Darwin':
+ return subprocess.check_output(["xcrun", "--find", "clang"],
+ stderr=subprocess.PIPE, universal_newlines=True).strip()
+ else:
+ return subprocess.check_output(["which", "clang"],
+ universal_newlines=True).strip()
+ except:
+ error("unable to find 'clang' tool for bootstrap build")
+
def get_swiftc_path():
try:
if os.getenv("SWIFT_EXEC"):
@@ -979,6 +993,7 @@ def main():
if not args.swiftc_path:
args.swiftc_path = get_swiftc_path()
+ args.clang_path = get_clang_path()
args.swift_stdlib_path = os.path.normpath(
os.path.join(os.path.dirname(os.path.realpath(args.swiftc_path)), "..",
@@ -1129,6 +1144,7 @@ def main():
def make_fake_toolchain():
symlink_force(args.swiftc_path, os.path.join(bindir, "swift"))
symlink_force(args.swiftc_path, os.path.join(bindir, "swiftc"))
+ symlink_force(args.clang_path, os.path.join(bindir, "clang"))
symlink_force(args.sbt_path, os.path.join(bindir, "swift-build-tool"))
symlink_force(os.path.join(sandbox_path, "bin", "swift-build"),
bootstrapped_product)
]