Skip to content

Commit

Permalink
Merge pull request #5267 from commercialhaskell/static-linux
Browse files Browse the repository at this point in the history
Static linux
  • Loading branch information
snoyberg authored Apr 23, 2020
2 parents 556543d + 71405b1 commit 59d143d
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 33 deletions.
38 changes: 30 additions & 8 deletions .azure/azure-linux-template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,36 @@ jobs:
GHC 8.4:
BUILD: stack
STACK_YAML: stack-ghc-84.yaml
EXTRA_SUFFIX: ""
GHC 8.6:
BUILD: stack
STACK_YAML: stack-ghc-86.yaml
EXTRA_SUFFIX: ""
GHC 8.8:
BUILD: stack
STACK_YAML: stack-ghc-88.yaml
EXTRA_SUFFIX: ""
Alpine:
BUILD: stack
STACK_YAML: stack.yaml
EXTRA_SUFFIX: "alpine"
STACK_ARGS: --docker --system-ghc --no-install-ghc --flag stack:static
style:
BUILD: style
EXTRA_SUFFIX: ""
pedantic:
BUILD: pedantic
STACK_YAML: stack.yaml
EXTRA_SUFFIX: ""
steps:
- script: |
export STACK_ROOT="$(Build.SourcesDirectory)"/.stack-root;
mkdir -p ~/.local/bin
curl -f -L "https://github.com/fpco/cache-s3/releases/download/${CACHE_S3_VERSION}/cache-s3-${CACHE_S3_VERSION}-${OS_NAME}-x86_64.tar.gz" -o ~/.local/bin/cache-s3.tar.gz
tar xzf ~/.local/bin/cache-s3.tar.gz -C ~/.local/bin
export PATH=$HOME/.local/bin:$PATH;
cache-s3 --prefix="${CACHE_S3_PREFIX}" --git-branch="$(Build.SourceBranchName)" --suffix="${OS_NAME}" restore stack --base-branch="${BASE_BRANCH}"
cache-s3 --prefix="${CACHE_S3_PREFIX}" --git-branch="$(Build.SourceBranchName)" --suffix="${OS_NAME}" restore stack work --base-branch="${BASE_BRANCH}"
cache-s3 --prefix="${CACHE_S3_PREFIX}" --git-branch="$(Build.SourceBranchName)" --suffix="${OS_NAME}${EXTRA_SUFFIX}" restore stack --base-branch="${BASE_BRANCH}"
cache-s3 --prefix="${CACHE_S3_PREFIX}" --git-branch="$(Build.SourceBranchName)" --suffix="${OS_NAME}${EXTRA_SUFFIX}" restore stack work --base-branch="${BASE_BRANCH}"
etc/scripts/ci-setup.sh
case "$BUILD" in
style)
Expand All @@ -38,11 +48,9 @@ jobs:
;;
*)
export PATH=$HOME/.local/bin:$PATH
stack --install-ghc $ARGS test --bench --only-dependencies
stack test $STACK_ARGS --bench --only-dependencies
;;
esac
GHC_OPTIONS="-Werror"
if [ "$GHCVER" = "8.2.1" ]; then GHC_OPTIONS="$GHC_OPTIONS -Wno-missing-home-modules"; fi
set -ex
case "$BUILD" in
style)
Expand All @@ -51,7 +59,21 @@ jobs:
hlint test/ --cpp-simple
;;
stack)
stack test --haddock --no-haddock-deps --ghc-options="$GHC_OPTIONS"
stack test $STACK_ARGS --haddock --no-haddock-deps --ghc-options="-Werror" --copy-bins --local-bin-path bin
# Get output about whether the exe is dynamically linked
if [[ "$EXTRA_SUFFIX" == "alpine" ]]
then
# ldd returns exit code 1 if it's static, so failure is success
(ldd ./bin/stack && exit 1) || true
else
ldd ./bin/stack
fi
# Make sure we can run the executable on this OS
# Important to make sure the Alpine exe is properly static
./bin/stack --version
;;
pedantic)
stack --system-ghc build --pedantic
Expand Down Expand Up @@ -94,9 +116,9 @@ jobs:
export AWS_SECRET_ACCESS_KEY="$(AWS_SECRET_ACCESS_KEY)";
export STACK_ROOT="$(Build.SourcesDirectory)"/.stack-root;
if [ "$(Build.SourceBranchName)" = "${BASE_BRANCH}" ]; then
cache-s3 --prefix="${CACHE_S3_PREFIX}" --git-branch="$(Build.SourceBranchName)" --suffix="${OS_NAME}" save stack;
cache-s3 --prefix="${CACHE_S3_PREFIX}" --git-branch="$(Build.SourceBranchName)" --suffix="${OS_NAME}${EXTRA_SUFFIX}" save stack;
fi;
cache-s3 --prefix="${CACHE_S3_PREFIX}" --git-branch="$(Build.SourceBranchName)" --suffix="${OS_NAME}" save stack work
cache-s3 --prefix="${CACHE_S3_PREFIX}" --git-branch="$(Build.SourceBranchName)" --suffix="${OS_NAME}${EXTRA_SUFFIX}" save stack work
condition: and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI'))
env:
OS_NAME: ${{ parameters.os }}
Expand Down
4 changes: 2 additions & 2 deletions .azure/azure-nightly-template-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
nix-channel --update # Get GHC 8.2.2
export STACK_ROOT="$(Build.SourcesDirectory)"/.stack-root;
export PATH=$HOME/.local/bin:$PATH;
stack etc/scripts/release.hs check
stack etc/scripts/release.hs check --alpine
set +ex
displayName: Integration Test
Expand All @@ -49,7 +49,7 @@ jobs:
export STACK_ROOT="$(Build.SourcesDirectory)"/.stack-root;
export PATH=$HOME/.local/bin:$PATH;
stack etc/scripts/release.hs build
stack etc/scripts/release.hs build --alpine
cp _release/stack-* $(Build.ArtifactStagingDirectory)
set +ex
Expand Down
47 changes: 26 additions & 21 deletions etc/scripts/release.hs
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,12 @@ options =
"Label to give the uploaded release asset"
, Option "" [noTestHaddocksOptName] (NoArg $ Right $ \g -> g{gTestHaddocks = False})
"Disable testing building haddocks."
, Option "" [staticOptName] (NoArg $ Right $ \g -> g{gBuildArgs = gBuildArgs g ++ ["--flag=stack:static"]})
"Build a static binary."
, Option "" [alpineOptName]
(NoArg $ Right $ \g ->
g{gBuildArgs =
gBuildArgs g ++
["--flag=stack:static", "--docker", "--system-ghc", "--no-install-ghc"]})
"Build a static binary using Alpine Docker image."
, Option "" [buildArgsOptName]
(ReqArg
(\v -> Right $ \g -> g{gBuildArgs = gBuildArgs g ++ words v})
Expand Down Expand Up @@ -196,18 +200,19 @@ rules global@Global{..} args = do
Stdout dirty <- cmd "git status --porcelain"
when (not gAllowDirty && not (null (trim dirty))) $
error ("Working tree is dirty. Use --" ++ allowDirtyOptName ++ " option to continue anyway.")
withTempDir $ \tmpDir -> do
let cmd0 c = cmd [gProjectRoot </> releaseBinDir </> binaryName </> stackExeFileName]
(stackArgs global)
["--local-bin-path=" ++ tmpDir]
c
() <- cmd0 "install" gBuildArgs integrationTestFlagArgs $ concat $ concat
[["--pedantic --no-haddock-deps "]
,[" --haddock" | gTestHaddocks]
,[" stack"]]
let cmd' c = cmd (AddPath [tmpDir] []) stackProgName (stackArgs global) c
() <- cmd' "test" gBuildArgs integrationTestFlagArgs "--pedantic --exec stack-integration-test stack"
return ()
() <- cmd
[gProjectRoot </> releaseBinDir </> binaryName </> stackExeFileName]
(stackArgs global)
["build"]
gBuildArgs
integrationTestFlagArgs
["--pedantic", "--no-haddock-deps", "--test"]
["--haddock" | gTestHaddocks]
["stack"]
() <- cmd
[gProjectRoot </> releaseBinDir </> binaryName </> stackExeFileName]
["exec"]
[gProjectRoot </> releaseBinDir </> binaryName </> "stack-integration-test"]
copyFileChanged (releaseBinDir </> binaryName </> stackExeFileName) out

unless gUploadOnly $ releaseDir </> binaryPkgZipFileName %> \out -> do
Expand Down Expand Up @@ -242,7 +247,7 @@ rules global@Global{..} args = do
unless gUploadOnly $ releaseDir </> binaryExeFileName %> \out -> do
need [releaseBinDir </> binaryName </> stackExeFileName]
(Stdout versionOut) <- cmd (releaseBinDir </> binaryName </> stackExeFileName) "--version"
-- () <- cmd "git diff"
() <- cmd "git diff"
when (not gAllowDirty && "dirty" `isInfixOf` lower versionOut) $
error ("Refusing continue because 'stack --version' reports dirty. Use --" ++
allowDirtyOptName ++ " option to continue anyway.")
Expand All @@ -265,8 +270,8 @@ rules global@Global{..} args = do
,out])
(removeFile out)
Linux ->
cmd "strip -p --strip-unneeded --remove-section=.comment -o"
[out, releaseBinDir </> binaryName </> stackExeFileName]
-- Using Ubuntu's strip to strip an Alpine exe doesn't work, so just copy
liftIO $ copyFile (releaseBinDir </> binaryName </> stackExeFileName) out
_ ->
cmd "strip -o"
[out, releaseBinDir </> binaryName </> stackExeFileName]
Expand Down Expand Up @@ -534,9 +539,9 @@ noTestHaddocksOptName = "no-test-haddocks"
buildArgsOptName :: String
buildArgsOptName = "build-args"

-- | @--static@ command-line option name.
staticOptName :: String
staticOptName = "static"
-- | @--alpine@ command-line option name.
alpineOptName :: String
alpineOptName = "alpine"

-- | @--certificate-name@ command-line option name.
certificateNameOptName :: String
Expand All @@ -548,7 +553,7 @@ uploadOnlyOptName = "upload-only"

-- | Arguments to pass to all 'stack' invocations.
stackArgs :: Global -> [String]
stackArgs Global{..} = ["--install-ghc", "--arch=" ++ display gArch, "--interleaved-output"]
stackArgs Global{..} = ["--arch=" ++ display gArch, "--interleaved-output"]

-- | Name of the 'stack' program.
stackProgName :: FilePath
Expand Down
4 changes: 4 additions & 0 deletions package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,10 @@ executables:
when:
- condition: ! '!(flag(integration-tests))'
buildable: false
- condition: flag(static)
ld-options:
- -static
- -pthread
tests:
stack-test:
main: Spec.hs
Expand Down
4 changes: 3 additions & 1 deletion stack.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ cabal-version: 2.0
--
-- see: https://github.com/sol/hpack
--
-- hash: f003cdea0be4961a87f3e62f3f9e5fee3e29924f746a6154a15ac18985deb871
-- hash: 04f6dd3ff3b1b0f7db0a0ad6192866ad73926008fd5df9215d6abae839da8874

name: stack
version: 2.3.0.2
Expand Down Expand Up @@ -553,6 +553,8 @@ executable stack-integration-test
unix
if !(flag(integration-tests))
buildable: False
if flag(static)
ld-options: -static -pthread
default-language: Haskell2010

test-suite stack-test
Expand Down
4 changes: 3 additions & 1 deletion stack.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ packages:

docker:
enable: false
repo: fpco/stack-build:lts-14.27

#image: fpco/alpine-haskell-stack:8.6.5
image: fpco/alpine-haskell-stack@sha256:49e7e15f3b1d3f882ba5bb701463b1d508fbf40e5aafce6ea31acd210da570ba

nix:
# --nix on the command-line to enable.
Expand Down

0 comments on commit 59d143d

Please sign in to comment.