diff --git a/README.md b/README.md index c18a996a..dd23647e 100644 --- a/README.md +++ b/README.md @@ -85,10 +85,37 @@ $ heroku config:set SWIFT_BUILD_CONFIGURATION=debug $ git commit -m "Change to debug configuration on Heroku" --allow-empty $ git push heroku master ... -remote: -----> Building package (debug configuration) +remote: -----> Building package (debug configuration, static stdlib) ... ``` +### Statically linked standard library + +Swift supports static linkage for its standard library and Foundation, which has two advantages: + +1. The resulting binary is more self-contained, and can run on other machines running the same version of the same distribution _without having to install the Swift toolchain._ +1. As only the relevant parts of the standard library/Foundation are copied into the binary, the resulting image will be smaller. A smaller image deploys faster too. + +The buildpack uses static linkage by default. + +However, if your project does not build, throwing errors about missing symbols for example, you can opt-in for the previous, dynamic linkage. + +Define a configuration variable called `SWIFT_DYNAMIC_STDLIB` with any non-empty value, then deploy again. + +```shell +$ heroku config:set SWIFT_DYNAMIC_STDLIB=true +$ git commit -m "Change to dynamic stdlib on Heroku" --allow-empty +$ git push heroku master +``` + +To use static linkage again, _unset_ the configuration variable and deploy again. + +```shell +$ heroku config:unset SWIFT_DYNAMIC_STDLIB +$ git commit -m "Change to dynamic stdlib on Heroku" --allow-empty +$ git push heroku master +``` + ### Other build arguments If you want to pass extra flags to the `swift build` command, you can do so by setting the `SWIFT_BUILD_FLAGS` config variable. diff --git a/bin/compile b/bin/compile index 63013683..48c72517 100755 --- a/bin/compile +++ b/bin/compile @@ -36,6 +36,13 @@ if [ -f "$ENV_DIR/SWIFT_BUILD_FLAGS" ]; then SWIFT_BUILD_FLAGS=`cat "$ENV_DIR/SWIFT_BUILD_FLAGS"` fi +if [ -f "$ENV_DIR/SWIFT_DYNAMIC_STDLIB" ]; then + SWIFT_DYNAMIC_STDLIB=`cat "$ENV_DIR/SWIFT_DYNAMIC_STDLIB" | tr -d '[[:space:]]'` + SWIFT_BACKTRACE_EXECUTABLE="swift-backtrace" +else + SWIFT_BACKTRACE_EXECUTABLE="swift-backtrace-static" +fi + mkdir -p "$CACHE_DIR/$STACK" source "$BIN_DIR/steps/swiftenv" @@ -55,4 +62,4 @@ mkdir -p $BUILD_DIR/.profile.d set-env PATH '$HOME/.swift-bin:$PATH' set-env LD_LIBRARY_PATH '$LD_LIBRARY_PATH:$HOME/.swift-lib' -set-env SWIFT_BACKTRACE 'enable=yes,sanitize=yes,threads=all,images=all,interactive=no,output-to=stderr,symbolicate=fast,swift-backtrace=.swift-bin/swift-backtrace-static' +set-env SWIFT_BACKTRACE "enable=yes,sanitize=yes,threads=all,images=all,interactive=no,output-to=stderr,symbolicate=fast,swift-backtrace=.swift-bin/$SWIFT_BACKTRACE_EXECUTABLE" diff --git a/bin/steps/swift-build b/bin/steps/swift-build index ba0820db..13b760a9 100644 --- a/bin/steps/swift-build +++ b/bin/steps/swift-build @@ -1,2 +1,7 @@ -puts-step "Building package ($SWIFT_BUILD_CONFIGURATION configuration)" -swift build $SWIFT_BUILD_FLAGS -c "$SWIFT_BUILD_CONFIGURATION" --static-swift-stdlib \ No newline at end of file +if [ ! -z "$SWIFT_DYNAMIC_STDLIB" ]; then + puts-step "Building package ($SWIFT_BUILD_CONFIGURATION configuration, dynamic stdlib)" + swift build $SWIFT_BUILD_FLAGS -c "$SWIFT_BUILD_CONFIGURATION" +else + puts-step "Building package ($SWIFT_BUILD_CONFIGURATION configuration, static stdlib)" + swift build $SWIFT_BUILD_FLAGS -c "$SWIFT_BUILD_CONFIGURATION" --static-swift-stdlib +fi diff --git a/bin/steps/swift-install b/bin/steps/swift-install index 39a2912c..a6e4fb29 100644 --- a/bin/steps/swift-install +++ b/bin/steps/swift-install @@ -5,10 +5,14 @@ puts-step "Installing dynamic libraries" mkdir -p $BUILD_DIR/.swift-lib find -L .build/$SWIFT_BUILD_CONFIGURATION -regex "$DYNAMIC_LIBRARY_REGEX" -type f -exec cp -a {} $BUILD_DIR/.swift-lib \; || true 2>/dev/null +if [ ! -z "$SWIFT_DYNAMIC_STDLIB" ]; then + find -L $SWIFT_PREFIX/usr/lib/swift/linux -regex "$DYNAMIC_LIBRARY_REGEX" -type f -exec cp -a {} $BUILD_DIR/.swift-lib \; || true 2>/dev/null +fi + puts-step "Installing binaries" mkdir -p $BUILD_DIR/.swift-bin find -L .build/$SWIFT_BUILD_CONFIGURATION ! -regex "$DYNAMIC_LIBRARY_REGEX" -type f -perm /a+x -exec cp -a {} $BUILD_DIR/.swift-bin \; || true 2>/dev/null -cp -a $SWIFT_PREFIX/usr/libexec/swift/linux/swift-backtrace-static $BUILD_DIR/.swift-bin +cp -a $SWIFT_PREFIX/usr/libexec/swift/linux/$SWIFT_BACKTRACE_EXECUTABLE $BUILD_DIR/.swift-bin puts-step "Installing resources" find -L .build/$SWIFT_BUILD_CONFIGURATION/* -regex '.*\.resources$' -exec cp -a {} $BUILD_DIR/.swift-bin \; || true 2>/dev/null