dabrahams / SPMBuildToolSupport

Provides (and demonstrates) workarounds for Swift Package Manager bugs and limitations.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

SPMBuildToolSupport

This code allows your build tool plugins to easily and portably run executable targets, executable files by their path, commands that can be invoked from a shell, or Swift script files.

This package provides (and demonstrates) workarounds for Swift Package Manager bugs and limitations.

What bugs and limitations?

This is just a partial list:

  • Bugs:

    • Plugin outputs are not automatically rebuilt when a plugin's executable changes (SPM issue #6936)
    • Broken file system path handling on Windows (SPM issue #6994)
    • If you use a plugin to generate tests or source for an executable, on Windows, SPM will try to link the plugin itself into the executable, resulting in “duplicate main” link errors (SPM issue #6859).
    • swift SomeFile.swift doesn't work on Windows.
  • Limitations:

    • No easy way to reentrantly invoke SPM from within a build tool plugin, a key to working around many of the other bugs and limitations described here.
    • No easy way to find the source files on which an executable product depends.
    • SPM's Path type doesn't interoperate well with Foundation's URL.
    • The released version of the API docs for build tool plugins is inaccurate and confusing (fixes here).

Note: Plugin outputs are not automatically rebuilt when a plugin's source changes (SPM issue #6936). We don't have a workaround for this problem.

How do I use this package?

  1. SPM build tool plugins cannot have any dependencies on libraries, so you must arrange for your plugin's source to include SPMBuildToolSupport.swift. One way to do that if you want to stay up-to-date with improvements here, and especially if your project contains multiple plugins, is to make this repository a submodule of yours, and symlink the file into each subdirectory of your Plugins/ directory (assuming standard SPM layout).

  2. Make your plugin inherit from SPMBuildToolPlugin and implement its buildCommands method (instead of inheriting from BuildToolPlugin and implementing createBuildCommands). This project contains several examples. Executables that can run build commands are divided into the following cases:

    • .targetInThisPackage: an executable target in the same package as the plugin.
    • .file: a specific executable file.
    • .command: an executable found in the environment's executable search path, given the name you'd use to invoke it in a shell (e.g. "find").
    • .swiftScript: the executable produced by building a single specific .swift file, almost as though the file was passed as a parameter to the swift command.
    • .swiftToolchainCommand: an executable from the currently-running Swift toolchain, given the name you'd use to invoke it in a shell (e.g. "swift", "swiftc", "clang").
  3. To turn a PackagePlugin.Path or a Foundation.URL into a string that will be recognized by the host OS (say, to pass on a command line), use its .platformString property. Do not use URL's other properties (e.g. .path) for this purpose, as tempting as it may be.

  4. Avoid naïve path manipulations on a PackagePlugin.Path directly, which is buggy on some platforms. Consider using its url property and then, if necessary, converting the result back to a PackagePlugin.Path.

  5. To avoid spurious warnings from SPM about unhandled sources, do not use SPM's .sourceFiles(withSuffix: ".in") to find the input files to your build plugin. Instead, exclude them from the target in Package.swift and in your plugin, locate them relative to other directories in your project. LocalTargetCommandDemoPlugin.swift shows an example.

  6. On Windows:

About

Provides (and demonstrates) workarounds for Swift Package Manager bugs and limitations.

License:Boost Software License 1.0


Languages

Language:Swift 98.9%Language:Emacs Lisp 0.5%Language:C 0.3%Language:Dockerfile 0.1%Language:Shell 0.1%Language:Batchfile 0.1%