Skip to content

Commit

Permalink
Merge pull request #47 from vst/32-distribute-statically-compiled-binary
Browse files Browse the repository at this point in the history
Statically Compiled Executable
  • Loading branch information
vst authored Apr 1, 2024
2 parents 2224197 + dc4cce5 commit 43a6710
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 0 deletions.
65 changes: 65 additions & 0 deletions build-static.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/usr/bin/env bash

## NOTE: Things would be much easier if we could use Nix, but we can
## not (or I find it rather tedious). So, we have to use Docker.
##
## Also, `cabal install` does not work with
## `--enable-executable-static` flag. So, we have to use `cabal build`
## instead. Finally, `cabal build` does not work with
## `--enable-executable-stripping`, hence the `strip` command usage.

## GHC version:
GHC_VERSION="9.4.8"

## Docker image:
DOCKER_IMAGE="quay.io/benz0li/ghc-musl:${GHC_VERSION}"

## Executable name:
EXECUTABLE_NAME="lhp"

## Final executable name:
FINAL_EXECUTABLE_NAME="${EXECUTABLE_NAME}-static-$(uname --kernel-name | tr '[:upper:]' '[:lower:]')-$(uname --machine)"

## Final executable path:
FINAL_EXECUTABLE_PATH="/tmp/${FINAL_EXECUTABLE_NAME}"

## Docker container name:
CONTAINER_NAME="static-builder-for-${EXECUTABLE_NAME}"

## Create/update .cabal file:
hpack

## Cleanup first:
cabal clean
cabal v1-clean

## First, pin all packages as per Nix:
cabal freeze

## Run the Docker container:
docker run -i --detach -v "$(pwd):/app" --name "${CONTAINER_NAME}" "${DOCKER_IMAGE}" /bin/bash

## Update cabal database:
docker exec "${CONTAINER_NAME}" cabal update

## Build the static binary:
docker exec -w "/app" "${CONTAINER_NAME}" cabal build --enable-executable-static

## Get the path to the executable:
BUILD_PATH="$(docker exec -w "/app" "${CONTAINER_NAME}" cabal list-bin "${EXECUTABLE_NAME}")"

## Strip debugging symbols:
docker exec "${CONTAINER_NAME}" strip "${BUILD_PATH}"

## Copy the binary to the host:
docker cp "${CONTAINER_NAME}:${BUILD_PATH}" "${FINAL_EXECUTABLE_PATH}"

## Compress the executable:
upx "${FINAL_EXECUTABLE_PATH}"

## Cleanup:
docker exec -w "/app" "${CONTAINER_NAME}" cabal clean
docker exec -w "/app" "${CONTAINER_NAME}" cabal v1-clean
docker rm -f "${CONTAINER_NAME}"
rm cabal.project.freeze
file "${FINAL_EXECUTABLE_PATH}"
1 change: 1 addition & 0 deletions default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ let
pkgs.nil
pkgs.nixpkgs-fmt
pkgs.nodePackages.prettier
pkgs.upx

## Our custom scripts:
dev-test-build
Expand Down

0 comments on commit 43a6710

Please sign in to comment.