├── .gitignore ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── Setup.hs ├── alpine-haskell.cabal ├── docker ├── build-gmp.mk └── build-simple.mk ├── executables └── Main.hs ├── package.yaml ├── stack.yaml └── stack.yaml.lock /.gitignore: -------------------------------------------------------------------------------- 1 | .stack-work 2 | # JetBrains' IDEs 3 | .idea 4 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Set up environment variables, OS packages, and scripts that are common to the 3 | # build and distribution layers in this Dockerfile 4 | FROM alpine:3.9 AS base 5 | 6 | # Must be one of 'gmp' or 'simple'; used to build GHC with support for either 7 | # 'integer-gmp' (with 'libgmp') or 'integer-simple' 8 | # 9 | # Default to building with 'integer-gmp' and 'libgmp' support 10 | ARG GHC_BUILD_TYPE 11 | 12 | # Must be a valid GHC version number, only tested with 8.4.4, 8.6.4, and 8.6.5 13 | # 14 | # Default to GHC version 8.6.5 (latest at the time of writing) 15 | ARG GHC_VERSION=8.6.5 16 | 17 | # Add ghcup's bin directory to the PATH so that the versions of GHC it builds 18 | # are available in the build layers 19 | ENV GHCUP_INSTALL_BASE_PREFIX=/ 20 | ENV PATH=/.ghcup/bin:$PATH 21 | 22 | # Use the latest version of ghcup (at the time of writing) 23 | ENV GHCUP_VERSION=0.0.7 24 | ENV GHCUP_SHA256="b4b200d896eb45b56c89d0cfadfcf544a24759a6ffac029982821cc96b2faedb ghcup" 25 | 26 | # Install the basic required dependencies to run 'ghcup' and 'stack' 27 | RUN apk upgrade --no-cache &&\ 28 | apk add --no-cache \ 29 | curl \ 30 | gcc \ 31 | git \ 32 | libc-dev \ 33 | xz &&\ 34 | if [ "${GHC_BUILD_TYPE}" = "gmp" ]; then \ 35 | echo "Installing 'libgmp'" &&\ 36 | apk add --no-cache gmp-dev; \ 37 | fi 38 | 39 | # Download, verify, and install ghcup 40 | RUN echo "Downloading and installing ghcup" &&\ 41 | cd /tmp &&\ 42 | wget -P /tmp/ "https://gitlab.haskell.org/haskell/ghcup/raw/${GHCUP_VERSION}/ghcup" &&\ 43 | if ! echo -n "${GHCUP_SHA256}" | sha256sum -c -; then \ 44 | echo "ghcup-${GHCUP_VERSION} checksum failed" >&2 &&\ 45 | exit 1 ;\ 46 | fi ;\ 47 | mv /tmp/ghcup /usr/bin/ghcup &&\ 48 | chmod +x /usr/bin/ghcup 49 | 50 | ################################################################################ 51 | # Intermediate layer that builds GHC 52 | FROM base AS build-ghc 53 | 54 | # Carry build args through to this stage 55 | ARG GHC_BUILD_TYPE=gmp 56 | ARG GHC_VERSION=8.6.5 57 | 58 | RUN echo "Install OS packages necessary to build GHC" &&\ 59 | apk add --no-cache \ 60 | autoconf \ 61 | automake \ 62 | binutils-gold \ 63 | build-base \ 64 | coreutils \ 65 | cpio \ 66 | ghc \ 67 | linux-headers \ 68 | libffi-dev \ 69 | llvm5 \ 70 | musl-dev \ 71 | ncurses-dev \ 72 | perl \ 73 | python3 \ 74 | py3-sphinx \ 75 | zlib-dev 76 | 77 | COPY docker/build-gmp.mk /tmp/build-gmp.mk 78 | COPY docker/build-simple.mk /tmp/build-simple.mk 79 | RUN if [ "${GHC_BUILD_TYPE}" = "gmp" ]; then \ 80 | echo "Using 'integer-gmp' build config" &&\ 81 | apk add --no-cache gmp-dev &&\ 82 | mv /tmp/build-gmp.mk /tmp/build.mk && rm /tmp/build-simple.mk; \ 83 | elif [ "${GHC_BUILD_TYPE}" = "simple" ]; then \ 84 | echo "Using 'integer-simple' build config" &&\ 85 | mv /tmp/build-simple.mk /tmp/build.mk && rm tmp/build-gmp.mk; \ 86 | else \ 87 | echo "Invalid argument \[ GHC_BUILD_TYPE=${GHC_BUILD_TYPE} \]" && exit 1; \ 88 | fi 89 | 90 | RUN echo "Compiling and installing GHC" &&\ 91 | LD=ld.gold \ 92 | SPHINXBUILD=/usr/bin/sphinx-build-3 \ 93 | ghcup -v compile -j $(nproc) -c /tmp/build.mk ${GHC_VERSION} ghc-8.4.3 &&\ 94 | rm /tmp/build.mk &&\ 95 | echo "Uninstalling GHC bootstrapping compiler" &&\ 96 | apk del ghc &&\ 97 | ghcup set ${GHC_VERSION} 98 | 99 | ################################################################################ 100 | # Intermediate layer that assembles 'stack' tooling 101 | FROM base AS build-tooling 102 | 103 | ENV STACK_VERSION=2.1.3 104 | ENV STACK_SHA256="4e937a6ad7b5e352c5bd03aef29a753e9c4ca7e8ccc22deb5cd54019a8cf130c stack-${STACK_VERSION}-linux-x86_64-static.tar.gz" 105 | 106 | # Download, verify, and install stack 107 | RUN echo "Downloading and installing stack" &&\ 108 | cd /tmp &&\ 109 | wget -P /tmp/ "https://github.com/commercialhaskell/stack/releases/download/v${STACK_VERSION}/stack-${STACK_VERSION}-linux-x86_64-static.tar.gz" &&\ 110 | if ! echo -n "${STACK_SHA256}" | sha256sum -c -; then \ 111 | echo "stack-${STACK_VERSION} checksum failed" >&2 &&\ 112 | exit 1 ;\ 113 | fi ;\ 114 | tar -xvzf /tmp/stack-${STACK_VERSION}-linux-x86_64-static.tar.gz &&\ 115 | cp -L /tmp/stack-${STACK_VERSION}-linux-x86_64-static/stack /usr/bin/stack &&\ 116 | rm /tmp/stack-${STACK_VERSION}-linux-x86_64-static.tar.gz &&\ 117 | rm -rf /tmp/stack-${STACK_VERSION}-linux-x86_64-static 118 | 119 | ################################################################################ 120 | # Assemble the final image 121 | FROM base 122 | 123 | # Carry build args through to this stage 124 | ARG GHC_BUILD_TYPE=gmp 125 | ARG GHC_VERSION=8.6.5 126 | 127 | COPY --from=build-ghc /.ghcup /.ghcup 128 | COPY --from=build-tooling /usr/bin/stack /usr/bin/stack 129 | 130 | # NOTE: 'stack --docker' needs bash + usermod/groupmod (from shadow) 131 | RUN apk add --no-cache bash shadow openssh-client tar 132 | 133 | RUN ghcup set ${GHC_VERSION} &&\ 134 | stack config set system-ghc --global true 135 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright Author name here (c) 2019 2 | 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer in the documentation and/or other materials provided 14 | with the distribution. 15 | 16 | * Neither the name of Author name here nor the names of other 17 | contributors may be used to endorse or promote products derived 18 | from this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # https://www.gnu.org/software/make/manual/html_node/Special-Variables.html 3 | # https://ftp.gnu.org/old-gnu/Manuals/make-3.80/html_node/make_17.html 4 | ALPINE_HASKELL_MKFILE_PATH := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)) 5 | ALPINE_HASKELL_ROOT_DIR := $(shell cd $(shell dirname $(ALPINE_HASKELL_MKFILE_PATH)); pwd) 6 | 7 | # Common aliases lifted from other Makefiles 8 | package = alpine-haskell 9 | main_exe = demo 10 | 11 | # Use GHC options informed by this blog post: 12 | # https://rybczak.net/2016/03/26/how-to-reduce-compilation-times-of-haskell-projects/ 13 | ghc_opts = -j +RTS -A128m -RTS 14 | stack_yaml = STACK_YAML="stack.yaml" 15 | stack = $(stack_yaml) stack 16 | 17 | # Stack commands that will be executed in the Docker container 18 | stack_docker = $(stack) --docker 19 | 20 | # GHC version to build 21 | TARGET_GHC_VERSION ?= 8.6.5 22 | 23 | ################################################################################ 24 | # Standard build (runs in the Docker container) 25 | .PHONY: build 26 | build: 27 | $(stack_docker) build $(package) \ 28 | --ghc-options='$(ghc_opts)' 29 | 30 | # Static build (runs in the Docker container) 31 | .PHONY: build-static 32 | build-static: 33 | $(stack_docker) build $(package) --flag $(package):static \ 34 | --ghc-options='$(ghc_opts)' 35 | 36 | # Fast build (-O0) (runs in the Docker container) 37 | .PHONY: build-fast 38 | build-fast: 39 | $(stack_docker) build $(package) \ 40 | --ghc-options='$(ghc_opts)' \ 41 | --fast 42 | 43 | # Clean up all build artifacts 44 | clean: 45 | $(stack_docker) clean 46 | 47 | # Run ghcid (runs in the Docker container) 48 | ghcid: 49 | $(stack) exec -- ghcid \ 50 | --command "$(stack_docker) ghci \ 51 | --ghci-options='-fobject-code $(ghc_opts)' \ 52 | --main-is $(package):$(main_exe)" 53 | 54 | ################################################################################ 55 | # Convenience targets for building GHC locally 56 | # 57 | # The intermediate layers of the multi-stage Docker build file are cached so 58 | # that changes to the Dockerfile don't force us to rebuild GHC when developing 59 | 60 | # Build GHC with support for 'integer-gmp' and 'libgmp' 61 | .PHONY: docker-build-gmp 62 | docker-build-gmp: docker-base-gmp docker-ghc-gmp docker-tooling-gmp docker-image-gmp 63 | 64 | .PHONY: docker-base-gmp 65 | docker-base-gmp: 66 | docker build \ 67 | --build-arg GHC_BUILD_TYPE=gmp \ 68 | --build-arg GHC_VERSION=$(TARGET_GHC_VERSION) \ 69 | --target base \ 70 | --tag alpine-haskell-gmp:base \ 71 | --cache-from alpine-haskell-gmp:base \ 72 | --file $(ALPINE_HASKELL_ROOT_DIR)/Dockerfile \ 73 | $(ALPINE_HASKELL_ROOT_DIR) 74 | 75 | .PHONY: docker-ghc-gmp 76 | docker-ghc-gmp: 77 | docker build \ 78 | --build-arg GHC_BUILD_TYPE=gmp \ 79 | --build-arg GHC_VERSION=$(TARGET_GHC_VERSION) \ 80 | --target build-ghc \ 81 | --tag alpine-haskell-gmp:build-ghc-$(TARGET_GHC_VERSION) \ 82 | --cache-from alpine-haskell-gmp:build-ghc-$(TARGET_GHC_VERSION) \ 83 | --cache-from alpine-haskell-gmp:base \ 84 | --file $(ALPINE_HASKELL_ROOT_DIR)/Dockerfile \ 85 | $(ALPINE_HASKELL_ROOT_DIR) 86 | 87 | .PHONY: docker-tooling-gmp 88 | docker-tooling-gmp: 89 | docker build \ 90 | --build-arg GHC_BUILD_TYPE=gmp \ 91 | --build-arg GHC_VERSION=$(TARGET_GHC_VERSION) \ 92 | --target build-tooling \ 93 | --tag alpine-haskell-gmp:build-tooling \ 94 | --cache-from alpine-haskell-gmp:build-tooling\ 95 | --cache-from alpine-haskell-gmp:build-ghc-$(TARGET_GHC_VERSION) \ 96 | --cache-from alpine-haskell-gmp:base \ 97 | --file $(ALPINE_HASKELL_ROOT_DIR)/Dockerfile \ 98 | $(ALPINE_HASKELL_ROOT_DIR) 99 | 100 | .PHONY: docker-image-gmp 101 | docker-image-gmp: 102 | docker build \ 103 | --build-arg GHC_BUILD_TYPE=gmp \ 104 | --build-arg GHC_VERSION=$(TARGET_GHC_VERSION) \ 105 | --tag alpine-haskell-gmp:$(TARGET_GHC_VERSION) \ 106 | --cache-from alpine-haskell-gmp:$(TARGET_GHC_VERSION) \ 107 | --cache-from alpine-haskell-gmp:build-tooling \ 108 | --cache-from alpine-haskell-gmp:build-ghc-$(TARGET_GHC_VERSION) \ 109 | --cache-from alpine-haskell-gmp:base \ 110 | --file $(ALPINE_HASKELL_ROOT_DIR)/Dockerfile \ 111 | $(ALPINE_HASKELL_ROOT_DIR) 112 | 113 | # Build GHC with support for 'integer-simple' 114 | .PHONY: docker-build-simple 115 | docker-build-simple: docker-base-simple docker-ghc-simple docker-tooling-simple docker-image-simple 116 | 117 | .PHONY: docker-base-simple 118 | docker-base-simple: 119 | docker build \ 120 | --build-arg GHC_BUILD_TYPE=simple \ 121 | --build-arg GHC_VERSION=$(TARGET_GHC_VERSION) \ 122 | --target base \ 123 | --tag alpine-haskell-simple:base \ 124 | --cache-from alpine-haskell-simple:base \ 125 | --file $(ALPINE_HASKELL_ROOT_DIR)/Dockerfile \ 126 | $(ALPINE_HASKELL_ROOT_DIR) 127 | 128 | .PHONY: docker-ghc-simple 129 | docker-ghc-simple: 130 | docker build \ 131 | --build-arg GHC_BUILD_TYPE=simple \ 132 | --build-arg GHC_VERSION=$(TARGET_GHC_VERSION) \ 133 | --target build-ghc \ 134 | --tag alpine-haskell-simple:build-ghc-$(TARGET_GHC_VERSION) \ 135 | --cache-from alpine-haskell-simple:build-ghc-$(TARGET_GHC_VERSION) \ 136 | --cache-from alpine-haskell-simple:base \ 137 | --file $(ALPINE_HASKELL_ROOT_DIR)/Dockerfile \ 138 | $(ALPINE_HASKELL_ROOT_DIR) 139 | 140 | .PHONY: docker-tooling-simple 141 | docker-tooling-simple: 142 | docker build \ 143 | --build-arg GHC_BUILD_TYPE=simple \ 144 | --build-arg GHC_VERSION=$(TARGET_GHC_VERSION) \ 145 | --target build-tooling \ 146 | --tag alpine-haskell-simple:build-tooling \ 147 | --cache-from alpine-haskell-simple:build-tooling\ 148 | --cache-from alpine-haskell-simple:build-ghc-$(TARGET_GHC_VERSION) \ 149 | --cache-from alpine-haskell-simple:base \ 150 | --file $(ALPINE_HASKELL_ROOT_DIR)/Dockerfile \ 151 | $(ALPINE_HASKELL_ROOT_DIR) 152 | 153 | .PHONY: docker-image-simple 154 | docker-image-simple: 155 | docker build \ 156 | --build-arg GHC_BUILD_TYPE=simple \ 157 | --build-arg GHC_VERSION=$(TARGET_GHC_VERSION) \ 158 | --tag alpine-haskell-simple:$(TARGET_GHC_VERSION) \ 159 | --cache-from alpine-haskell-simple:$(TARGET_GHC_VERSION) \ 160 | --cache-from alpine-haskell-simple:build-tooling \ 161 | --cache-from alpine-haskell-simple:build-ghc-$(TARGET_GHC_VERSION) \ 162 | --cache-from alpine-haskell-simple:base \ 163 | --file $(ALPINE_HASKELL_ROOT_DIR)/Dockerfile \ 164 | $(ALPINE_HASKELL_ROOT_DIR) 165 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GHC, Alpine, Stack, and Docker 2 | 3 | 4 | **Table of Contents** 5 | 6 | - [Prerequisites](#prerequisites) 7 | - [Building the Docker Images](#building-the-docker-images) 8 | - ["Quick" Start](#quick-start) 9 | - [Overview](#overview) 10 | - [Developing Locally with `stack`](#developing-locally-with-stack) 11 | - [TODO](#todo) 12 | 13 | 14 | 15 | This repository is a small demonstration of the steps required to build an 16 | Alpine Linux Docker image with all the tools necessary to compile Haskell 17 | programs linked against `musl` libc. 18 | 19 | Such an environment are extremely useful for producing small Docker images for 20 | the deployment of services and for creating portable Haskell executables (either 21 | statically linked, or bundled with the `musl` linker and their dynamic 22 | dependencies). 23 | 24 | At the time of writing, this repository is primarily geared towards showing off 25 | a workflow by which one can use `stack`'s Docker integration to seamlessly 26 | develop inside an Alpine Linux container. This gives the benefit of `stack`'s 27 | build caching and also integrates nicely with development tools like `ghcid`. 28 | 29 | In the future I hope to either update this repository with explicit instructions 30 | and/or examples that show how one can create minimal (i.e. tens of MB) 31 | Docker images to deploy Haskell applications in production. 32 | 33 | ## Prerequisites 34 | 35 | Ensure Docker is installed on your computer and the Docker daemon is running. 36 | 37 | Install the [Haskell Tool Stack](https://docs.haskellstack.org/en/stable/README/). 38 | 39 | ## Building the Docker Images 40 | 41 | At the time of writing (1 Apr. 2019) GHC-HQ doesn't provide a version of GHC 42 | that is compatible with `musl` libc, and the `ghc` package provided by Alpine 43 | is out of date. 44 | 45 | This means that the first step in this process is going to be _compiling GHC 46 | itself_ and packaging up all the necessary tools and dependencies in an Alpine 47 | Linux container. 48 | 49 | For convenience, I've combined all of these steps into a single, multi-stage 50 | [Dockerfile](Dockerfile) in this repository, and written a [Makefile](Makefile) 51 | that caches the intermediate build layers so changes to the final environment 52 | don't trigger a full rebuild of GHC and the associated tooling. 53 | 54 | ### "Quick" Start 55 | 56 | To build the Docker images, navigate to the project root directory and run: 57 | 58 | make docker-build-gmp 59 | 60 | Keep in mind that this stage compiles GHC, which can take anywhere from 30 mins 61 | to upwards of an hour depending on how fast your computer is. 62 | 63 | ### Overview 64 | 65 | I've tried to keep the [Dockerfile](Dockerfile) relatively well commented, but 66 | the build process can be roughly understood as an impl 67 | 68 | - `base` 69 | - Base layer used for all the intermediate build images to follow 70 | - Contains all OS dependencies required to run `ghcup` and `stack` 71 | 72 | - `build-ghc` 73 | - Builds GHC via `ghcup` 74 | - Contains all dependencies required to build GHC 75 | - Contains some (currently unused) logic for selecting between `integer-gmp` 76 | and `integer-simple` 77 | - `integer-gmp` depends on `libgmp`, which is licensed under the LGPL, so 78 | if one wants to distribute a statically linked, closed source binary they 79 | will need to build against a version of GHC that uses `integer-simple` 80 | 81 | - `build-tooling` 82 | - Downloads `stack` and verifies the hash 83 | 84 | - `alpine-haskell` 85 | - Assembles artifacts from the previous layers 86 | - Copies GHC and `stack` 87 | - Installs `bash` and `shadow` 88 | - `stack` requires `usermod`/`groupmod` from `shadow` as well as `bash` to 89 | run 90 | 91 | ## Developing Locally with `stack` 92 | 93 | Once the images have finished building, this project can be compiled to 94 | demonstrate what local development looks like with `stack`. 95 | 96 | For convenience, I've added some targets to the [Makefile](Makefile) that run 97 | some common development tasks. 98 | 99 | First, ensure that `ghcid` is installed (for example, by running 100 | `stack build --copy-compiler-tool ghcid`). 101 | 102 | Then, compile this project in Docker by running `make build-fast`. 103 | 104 | Finally, start a `ghcid` development loop with `make ghcid`; this loop uses 105 | `stack --docker` to spawn a container in which GHC recompiles everything 106 | whenever it detects changes in your code. 107 | 108 | Try changing something in `executables/Main.hs` and see the changes reflected in 109 | `ghcid`! 110 | 111 | ## TODO 112 | 113 | - Demonstrate `integer-simple` support 114 | - Demonstrate static linking 115 | - Create separate `Dockerfile`s for GHC and combined tooling 116 | - Automate the creation of these images in CI and host them on Dockerhub 117 | 118 | ## Related work 119 | 120 | - [build most Haskell programs into fully static Linux executables using Nix](https://github.com/nh2/static-haskell-nix) 121 | -------------------------------------------------------------------------------- /Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /alpine-haskell.cabal: -------------------------------------------------------------------------------- 1 | cabal-version: 1.12 2 | 3 | -- This file has been generated from package.yaml by hpack version 0.31.2. 4 | -- 5 | -- see: https://github.com/sol/hpack 6 | -- 7 | -- hash: 505d4249f4963f666cdbe5b35aaadf879681abe857624407f240142dad22129b 8 | 9 | name: alpine-haskell 10 | version: 0.1.0.0 11 | category: Web 12 | homepage: https://github.com/githubuser/alpine-haskell#readme 13 | author: Author name here 14 | maintainer: example@example.com 15 | copyright: 2019 Author name here 16 | license: BSD3 17 | license-file: LICENSE 18 | build-type: Simple 19 | extra-source-files: 20 | README.md 21 | 22 | flag static 23 | description: Statically link executables. 24 | manual: True 25 | default: False 26 | 27 | executable demo 28 | main-is: Main.hs 29 | other-modules: 30 | Paths_alpine_haskell 31 | hs-source-dirs: 32 | executables 33 | build-depends: 34 | base >=4.7 && <5 35 | if flag(static) 36 | ghc-options: -rtsopts -threaded -optc-Os -optl=-pthread -optl=-static -fPIC 37 | ld-options: -static 38 | else 39 | ghc-options: -rtsopts -threaded 40 | default-language: Haskell2010 41 | -------------------------------------------------------------------------------- /docker/build-gmp.mk: -------------------------------------------------------------------------------- 1 | SRC_HC_OPTS = -O -H64m 2 | BuildFlavour = perf-llvm 3 | GhcStage1HcOpts = -O 4 | GhcStage2HcOpts = -O2 5 | GhcLibHcOpts = -O2 6 | GhcWithLlvmCodeGen = YES 7 | BUILD_PROF_LIBS = YES 8 | SplitObjs = NO 9 | SplitSections = YES 10 | BUILD_MAN = NO 11 | BUILD_SPHINX_HTML = YES 12 | BUILD_SPHINX_PDF = NO 13 | HADDOCK_DOCS = YES 14 | EXTRA_HADDOCK_OPTS += --quickjump --hyperlinked-source 15 | -------------------------------------------------------------------------------- /docker/build-simple.mk: -------------------------------------------------------------------------------- 1 | INTEGER_LIBRARY = integer-simple 2 | BuildFlavour = perf-llvm 3 | SRC_HC_OPTS = -O -H64m 4 | GhcStage1HcOpts = -O 5 | GhcStage2HcOpts = -O2 6 | GhcLibHcOpts = -O2 7 | GhcWithLlvmCodeGen = YES 8 | BUILD_PROF_LIBS = YES 9 | SplitObjs = NO 10 | SplitSections = YES 11 | BUILD_SPHINX_HTML = YES 12 | BUILD_SPHINX_PDF = NO 13 | HADDOCK_DOCS = YES 14 | EXTRA_HADDOCK_OPTS += --quickjump --hyperlinked-source 15 | -------------------------------------------------------------------------------- /executables/Main.hs: -------------------------------------------------------------------------------- 1 | module Main where 2 | 3 | main :: IO () 4 | main = do 5 | putStrLn "hello world!" 6 | -------------------------------------------------------------------------------- /package.yaml: -------------------------------------------------------------------------------- 1 | name: alpine-haskell 2 | version: 0.1.0.0 3 | homepage: https://github.com/githubuser/alpine-haskell#readme 4 | license: BSD3 5 | author: Author name here 6 | maintainer: example@example.com 7 | copyright: 2019 Author name here 8 | category: Web 9 | extra-source-files: 10 | - README.md 11 | 12 | dependencies: 13 | - base >= 4.7 && < 5 14 | 15 | flags: 16 | static: 17 | description: Statically link executables. 18 | manual: true 19 | default: false 20 | 21 | executables: 22 | demo: 23 | source-dirs: executables 24 | main: Main.hs 25 | when: 26 | - condition: flag(static) 27 | then: 28 | ld-options: -static 29 | ghc-options: "-rtsopts -threaded -optc-Os -optl=-pthread -optl=-static -fPIC" 30 | else: 31 | ghc-options: "-rtsopts -threaded" 32 | -------------------------------------------------------------------------------- /stack.yaml: -------------------------------------------------------------------------------- 1 | resolver: lts-13.24 2 | packages: 3 | - . 4 | 5 | docker: 6 | enable: false 7 | repo: "alpine-haskell-gmp:8.6.5" 8 | stack-exe: image 9 | -------------------------------------------------------------------------------- /stack.yaml.lock: -------------------------------------------------------------------------------- 1 | # This file was autogenerated by Stack. 2 | # You should not edit this file by hand. 3 | # For more information, please see the documentation at: 4 | # https://docs.haskellstack.org/en/stable/lock_files 5 | 6 | packages: [] 7 | snapshots: 8 | - completed: 9 | size: 498402 10 | url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/13/24.yaml 11 | sha256: 33e96adfe24f112b62f6edd22565cdbaa13155703bbfbfdc3d0a9bc6138ae7bf 12 | original: lts-13.24 13 | --------------------------------------------------------------------------------