Skip to content

Instantly share code, notes, and snippets.

@SDGGiesbrecht SDGGiesbrecht/
Last active Apr 3, 2019

What would you like to do?
Install or update executables from a Swift package.
# Copyright ©2017 Jeremy David Giesbrecht.
# Soli Deo gloria.
# Licensed under the Apache Licence, Version 2.0.
# See for licence information.
# ••••••• ••••••• ••••••• ••••••• ••••••• ••••••• •••••••
# Use this script to install or update executables from a Swift package.
# Works on both macOS and Linux.
# Tools will be registered for use in bash, zsh, and fish.
# For the required arguments, see the “Collect arguments.” section below.
# See for an example.
# ••••••• ••••••• ••••••• ••••••• ••••••• ••••••• •••••••
# Stop if a command fails.
set -e
# Collect arguments.
package_name="$1" # The package name.
package_url="$2" # The package URL.
version="$3" # The version to install.
help_command="$4" # An initial help command to get users started.
tools="${@:5}" # The name of the tool(s). Supply each one as a separate argument if the package supplies more than one.
# Unique installation directory.
# Clone and build in a temporary directory.
# Determine project install location
# Reset, clone and enter project.
rm -rf "${build_directory}"
git clone "${package_url}" "${build_directory}" --branch "${version}" --depth 1 --config advice.detachedHead=false
cd "${build_directory}"
# Build
swift build --configuration release
# Clean out irrelevant build artifacts.
rm -rf "${product_directory}"/ModuleCache
rm -rf "${product_directory}"/*.product
rm -rf "${product_directory}"/*.build
rm -rf "${product_directory}"/*.swiftdoc
rm -rf "${product_directory}"/*.swiftmodule
# Resolve product location.
cd "${product_directory}"
resolved_product_directory=$(pwd -P)
cd "${build_directory}"
if [[ "$OSTYPE" == "darwin"* ]]; then
# Fix dynamic linking.
cd "${resolved_product_directory}"
if ls *.dylib 1> /dev/null 2>&1; then
dynamic_libraries=($(ls *.dylib))
for dynamic_library in "${dynamic_libraries[@]}" ; do
for tool in $tools ; do
install_name_tool -change "${resolved_product_directory}/${dynamic_library}" "@executable_path/${dynamic_library}" "${tool}"
cd "${build_directory}"
# Install/re‐install the products.
mkdir -p "${installation_directory}"
rm -rf "${install_location}"
mv -fv "${resolved_product_directory}" "${install_location}"
# Register the products.
for tool in $tools ; do
mkdir -p "${registry_directory}"
rm -rf "${registry_directory}/${tool}"
ln -s "${install_location}/${tool}" "${registry_directory}/${tool}"
# Clean up
rm -rf "${build_directory}"
# Register with system.
add_path=$'export PATH="$HOME/.SDG/Registry:$PATH"'
comment=$'\n\n# Register installed Swift packages\n'
register() {
grep -qF "${add_path}" "${HOME}/$1" || echo "${comment}${add_path}${trailing_space}" >> "${HOME}/$1"
register .bash_profile
register .bashrc
register .zshenv
eval "${add_path}"
add_path=$'set -gx PATH $PATH "$HOME/.SDG/Registry"'
mkdir -p "${HOME}/.config/fish"
register .config/fish/
# Note success.
echo ""
echo "${package_name} was installed successfully."
echo ""
# Show help.
echo "$ ${help_command}"
eval "${help_command}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.