|
| 1 | +#!/bin/sh -e |
| 2 | +# |
| 3 | +# Builds a FreeBSD package out of a toolchain. |
| 4 | +# Usage: makePackage /path/to/toolchain /path/to/final/package |
| 5 | + |
| 6 | +# Validate the command line arguments. |
| 7 | +if [ "$#" -ne 2 ]; then |
| 8 | + echo "Usage: $0 /path/to/toolchain /path/to/final/package" >/dev/stderr |
| 9 | + exit 1 |
| 10 | +fi |
| 11 | + |
| 12 | +# Create some variables for ease of use. |
| 13 | +PLATFORM="$(uname)" |
| 14 | +CURRENT_DIRECTORY="$(pwd)" |
| 15 | +TOOLCHAIN_PATH="$1" |
| 16 | +PACKAGE_PATH="$2" |
| 17 | +PACKAGE_STAGING="$(mktemp -d)" |
| 18 | +METADATA_STAGING="$(mktemp -d)" |
| 19 | +SWIFT_TOOLCHAIN_HOME="$PACKAGE_STAGING/usr/local/swift" |
| 20 | + |
| 21 | +# Check the platform and exit if we aren't running on FreeBSD. |
| 22 | +if [ ! "$PLATFORM" = "FreeBSD" ]; then |
| 23 | + echo "Platform $PLATFORM is not supported" >/dev/stderr |
| 24 | + exit 1 |
| 25 | +fi |
| 26 | + |
| 27 | +# Create necessary directories on disk. |
| 28 | +mkdir -p "$METADATA_STAGING" |
| 29 | +mkdir -p "$PACKAGE_STAGING/usr/local/bin" |
| 30 | +echo "Staging Swift package files in $PACKAGE_STAGING..." |
| 31 | + |
| 32 | +# Check the path that we were provided. We want to ensure that the |
| 33 | +# path that we were given is the root of the produced toolchain. |
| 34 | +# In other words, directly below the directory that we were passed |
| 35 | +# should be another directory named `usr`. |
| 36 | +if [ ! -d "$TOOLCHAIN_PATH/usr" ]; then |
| 37 | + echo "error: Directory provided was not the root directory of a toolchain" >/dev/stderr |
| 38 | + exit 1 |
| 39 | +fi |
| 40 | + |
| 41 | +# Stage the package files, dropping the initial usr/ directory |
| 42 | +# that is at the root of the provided toolchain from the path |
| 43 | +# but keeping everything after it. |
| 44 | +# So, the directory structure relative to the root of the staging |
| 45 | +# area will be |
| 46 | +# - ./usr/local/swift/bin |
| 47 | +# - ./usr/local/swift/lib |
| 48 | +# and so on. |
| 49 | +mkdir -p "$SWIFT_TOOLCHAIN_HOME" |
| 50 | +cp -R "$TOOLCHAIN_PATH/usr/" "$SWIFT_TOOLCHAIN_HOME" |
| 51 | +echo "Copied toolchain into $SWIFT_TOOLCHAIN_HOME." |
| 52 | + |
| 53 | +# Because the Swift toolchain will be installed to /usr/local/swift, |
| 54 | +# we need to create symlinks to the actual Swift binaries. This is |
| 55 | +# because users expect the installed binaries to be in the path at |
| 56 | +# /usr/local/bin. |
| 57 | +echo "Creating symlinks to Swift tools..." |
| 58 | +echo "Entering $PACKAGE_STAGING/usr/local/bin" |
| 59 | +cd "$PACKAGE_STAGING/usr/local/bin" |
| 60 | +ln -s "../swift/bin/swift" "swift" |
| 61 | +ln -s "../swift/bin/swiftc" "swiftc" |
| 62 | +echo "Returning to $CURRENT_DIRECTORY" |
| 63 | + |
| 64 | +# Once the symlink structure has been created, then we must generate |
| 65 | +# the list of files to store in the package. To do so, we iterate over |
| 66 | +# the staging area, and generate the list of files. These paths need |
| 67 | +# to be relative to ./usr/local since that is the prefix that we indicate |
| 68 | +# below in the manifest file. |
| 69 | +# |
| 70 | +# When the package is created using `pkg create`, pkg will handle the |
| 71 | +# process of generating the file hashes, etc. for everything here. |
| 72 | +echo "Generate package list..." |
| 73 | +cd "$PACKAGE_STAGING/usr/local" |
| 74 | +find "." -type l > "$METADATA_STAGING/pkg-plist" |
| 75 | +find "." -type f >> "$METADATA_STAGING/pkg-plist" |
| 76 | +cd "$CURRENT_DIRECTORY" |
| 77 | + |
| 78 | +SWIFT_VERSION="$("$SWIFT_TOOLCHAIN_HOME/bin/swift" --version | grep -Eo 'version [0-9.]+' | sed 's/version //')" |
| 79 | +echo "Swift version being packaged is $SWIFT_VERSION" |
| 80 | + |
| 81 | +# Create the manifest file. All fields below are required. pkg_create(3) |
| 82 | +# will add additional fields as part of generating the package. |
| 83 | +echo "Generating manifest..." |
| 84 | +cat > "$METADATA_STAGING/manifest" <<EOF |
| 85 | +{ |
| 86 | + "name": "swift", |
| 87 | + "version": "$SWIFT_VERSION", |
| 88 | + "desc": "The Swift programming language", |
| 89 | + "arch": "$(uname -m)", |
| 90 | + "prefix": "/usr/local", |
| 91 | + "origin": "", |
| 92 | + "comment": "", |
| 93 | + "maintainer": "Apple Inc.", |
| 94 | + "www": "https://www.swift.org" |
| 95 | +} |
| 96 | +EOF |
| 97 | + |
| 98 | +# Log where we wrote the metadata files. |
| 99 | +echo "Wrote manifest file to $METADATA_STAGING/manifest" |
| 100 | +echo "Wrote package file list to $METADATA_STAGING/pkg-plist" |
| 101 | + |
| 102 | +# Generate the package. FreeBSD will helpfully determine the required |
| 103 | +# dependencies for us based on the shared libraries that the binaries |
| 104 | +# in the toolchain require. We should call `pkg update` beforehand to |
| 105 | +# ensure this package database of dependencies is updated, just for |
| 106 | +# good measure. |
| 107 | +echo "Building package..." |
| 108 | +PACKAGE_FILE_NAME="$METADATA_STAGING/swift-$SWIFT_VERSION.pkg" |
| 109 | +mkdir -p "$(dirname $PACKAGE_PATH)" |
| 110 | +pkg update |
| 111 | +pkg create -f tzst -M "$METADATA_STAGING/manifest" -r "$PACKAGE_STAGING" -p "$METADATA_STAGING/pkg-plist" -o "$METADATA_STAGING" |
| 112 | +mv "$PACKAGE_FILE_NAME" "$PACKAGE_PATH" |
| 113 | + |
| 114 | +# Cleanup. |
| 115 | +rm -rf "$PACKAGE_STAGING" "$METADATA_STAGING" |
0 commit comments