Swift Package Installation
Introduction
It would be desirable to simplify the use of executables that have been compiled with swift build
and installing the binary, payloads and other requirements into either a global location usable by all users on the system, or make it available only to the current user.
This would simplify the distribution and usage of Swift-authored tools, as instructions for installing the software would be as simple as directing the user to type swift tool install
.
Other ecosystems like Node and .NET have made it easy for consumers of software to grab software and make it accessible with a single command. In the Node/NPM world this is achieved with the npm install
tool and in .NET with the dotnet tool install
command.
Motivation
Today when you build a Swift application using swift build
, the resulting executable and satellite dependencies are deposited in a platform and configuration specific way. Today the result of swift build
is deposited into the .build
directory, in itself, not entirely obvious, and inside there is a platform specific directory, as well as a debug
or release
directories that contain the executable.
If would be ideal if the instructions shared with the world were as simple as instruction users to install a program with: swift build install
--``global
and this would take care of installing the executable in the right location, and any dynamic library dependencies that are part of the project.
This command line tool could be used to install a Swift-version of the cron
command line tool into /usr/local/bin
:
$ swift build --target swift-cron
$ swift build install --global
$ ls /usr/local/bin/swift-cron
-rwxr-xr-x 1 miguel wheel 518886 Apr 6 16:39 /usr/local/bin/swift-cron
Linux distributions that compile binaries and distribute those additionally require the installation step to be done to a special installation root directory, and often configure the location for files. For example, configuration files go into $sysconfdir
which is /etc
and we would likely want our software to be installed into /usr
, so an RPM build file could look like this:
swift build --target swift-cron
swift build install --prefix=/usr --prefix-sysconf=/etc
The above sets the prefix for all the assets to be /usr
, so binaries would go into /usr/bin
, and libraries into /usr/lib
, but any configuration files would go into /etc
via.
Proposed Solution
Given that swift build
can build either products or individual targets that can include more than executables, the installation would handle installing executables, libraries and shared libraries.
Additionally, to make it so that Swift software that is installed in ways that conform to the macOS, Linux file system standards or BSD standards, we borrow the concept of prefix-based software installation where various installation subdirectories are derived from the prefix directory, but can also be overwritten on a case by case basis.
also for Linux distributions to package and , as well as to make it simpler to use Linux packaging technologies that both require custom directory installations ($sysconfdir
, $libdir
and so on), as well support for RPM-build
The following options would be added:
-
--install
would instruct the build process to install the assets, this option by default would default to installing to the user home directory (for example on Linux, this would be in$HOME
). The--install
flag additionally would have:-
--global
would direct the installation to install these into the appropriate system-wide directory (for example, on Linux this would be/usr/local/bin
for the executable, and/usr/local/lib
for libraries) -
--prefix
and--prefix-xxxx
flags would override the directory prefixes set either by the default, or the--global
option, to ensure that different assets can be installed in the proper locations
-
-
--uninstall
would instruct the build process to remove the files that would have previously been installed with the--install
flag, and like--install
, this would also take the--global
flag and the various--prefix
flags.
These are the various directories that could be configured for different assets, the following shows a some defaults that would make sense on Linux, but would
- Executable target: goes into
--prefix-bin
, this is computed as:$prefix/bin
- Library targets: goes into
--prefix-lib
, this is computed as$prefix/lib
Additionally, we could
And on the systems where this makes sense, we could additionally install a pkg-config
file that would allow the Swift library to be easily referenced by other ecosystems.
Open Topics
Directory Configuration
While not necessary to support these, it would be nice if these capabilities were supported in Swift out of the box.
For system-wide tools, it might make sense to define a global variable that describes where to fetch assets from, in the example I showed above, the imaginary swift-cron
command would likely expect a cron.config
file on /etc
.
Historically on Unix this has been handled by using compiler level defines, or hardcoding the contents on a config.h
file. For Swift Build, these paths could be generated as a global class or module containing the paths, for example:
public struct SwiftPackageConfiguration {
public let prefix = "/usr"
public let sysconfdir = "/etc"
public let bindir = "/bin"
}
Versioning Support
One thing that I did not considered in this proposal is a versioning story - the heart of this proposal is really the binary tool installation, and not the library assets.
I suspect that there is no need to version the binary for a tool (chances of me needing swift-cron-1
, swift-cron-1.2
, swift-cron-3.2
installed in parallel is not likely high).
Libraries are a different story, those could either be versioned as they tend to be in Unix (libSwifcron.so.1.0
, libSwiftcron.so.1.2
), or they could be versioned by using a different directory for each version (/usr/lib/libSwiftCron/1.2/libSwiftCron.so
).
The former has the advantage that it would work with existing idioms and would be picked up by the system dynamic linker without additional system configuration.