Set up Linux, OSX and FreeBSD on CircleCI.
authorMateusz Kowalczyk <fuuzetsu@fuuzetsu.co.uk>
Fri, 27 Oct 2017 17:14:06 +0000 (18:14 +0100)
committerMateusz Kowalczyk <fuuzetsu@fuuzetsu.co.uk>
Tue, 7 Nov 2017 10:22:15 +0000 (10:22 +0000)
.circleci/build.sh [new file with mode: 0755]
.circleci/config.yml
.circleci/fetch-submodules.sh [new file with mode: 0755]
.circleci/images/x86_64-freebsd/Dockerfile [new file with mode: 0644]
.circleci/images/x86_64-freebsd/build-toolchain.sh [new file with mode: 0755]
.circleci/prepare-system.sh [new file with mode: 0755]

diff --git a/.circleci/build.sh b/.circleci/build.sh
new file mode 100755 (executable)
index 0000000..74d5ea7
--- /dev/null
@@ -0,0 +1,59 @@
+#!/usr/bin/env bash
+# vim: sw=2 et
+
+set -euo pipefail
+
+fail() {
+  echo "ERROR: $*" >&2
+  exit 1
+}
+
+echo 'BUILD_SPHINX_HTML = NO' > mk/validate.mk
+echo 'BUILD_SPHINX_PDF = NO' >> mk/validate.mk
+
+cat > mk/build.mk <<EOF
+V=1
+HADDOCK_DOCS=YES
+LATEX_DOCS=YES
+HSCOLOUR_SRCS=YES
+BUILD_DOCBOOK_HTML=YES
+BeConservative=YES
+EOF
+
+export THREADS=8
+export SKIP_PERF_TESTS=YES
+export VERBOSE=2
+
+function run_build() {
+    ./boot
+    ./configure "$@"
+    make -j$THREADS
+    make test
+    make binary-dist
+}
+
+case "$(uname)" in
+  Linux)
+    if [[ -n ${TARGET:-} ]]; then
+      if [[ $TARGET = FreeBSD ]]; then
+        # cross-compiling to FreeBSD
+        echo 'HADDOCK_DOCS = NO' >> mk/build.mk
+        echo 'WERROR=' >> mk/build.mk
+        export PATH=/opt/ghc/bin:$PATH
+        run_build --target=x86_64-unknown-freebsd10
+      else
+        fail "TARGET=$target not supported"
+      fi
+    else
+      run_build
+    fi
+    ;;
+  Darwin)
+    if [[ -n ${TARGET:-} ]]; then
+      fail "uname=$(uname) not supported for cross-compilation"
+    fi
+    run_build
+    ;;
+  *)
+    fail "uname=$(uname) not supported"
+esac
index 6ee6c48..e38d265 100644 (file)
@@ -1,28 +1,90 @@
 version: 2
-jobs:
-  build:
+
+aliases:
+  - &defaults
     working_directory: ~/ghc
+  - &prepare
+    run:
+      name: prepare-system
+      command: .circleci/prepare-system.sh
+  - &submodules
+    run:
+      name: submodules
+      command: .circleci/fetch-submodules.sh
+  - &build
+    run:
+      name: build
+      command: .circleci/build.sh
+      # Building bindist takes ~15 minutes without output, account for
+      # that.
+      no_output_timeout: "30m"
+  - &collectartifacts
+    run:
+      name: collect artifacts
+      # We need this because CircleCI expects a path without
+      # wildcards but bindist archive name is not static
+      command: |
+        mkdir -p /tmp/artifacts
+        pwd
+        find .
+        cp ghc*.tar.xz /tmp/artifacts
+
+jobs:
+  "validate-x86_64-linux":
+    resource_class: xlarge
     docker:
-    - image: haskell:8
+      - image: haskell:8.2
+    steps:
+      # Make sure we have proper openssh before checkout: CircleCI git
+      # does not check the repository out properly without it and also
+      # takes 20 times longer than it should be.
+      - run:
+          name: install openssh
+          command: |
+            apt-get update -qq
+            apt-get install -y openssh-client
+      - checkout
+      - *prepare
+      - *submodules
+      - *build
+      - *collectartifacts
+      - store-artifacts:
+          path: /tmp/artifacts
+
+  "validate-x86_64-freebsd":
     resource_class: xlarge
+    docker:
+      - image: tweag/toolchain-x86_64-freebsd
+    environment:
+      TARGET: FreeBSD
+    steps:
+      - run:
+          name: install git
+          command: |
+            apt-get update -qq
+            apt-get install -qy openssh-client
+      - checkout
+      - *prepare
+      - *submodules
+      - *build
+
+  "validate-x86_64-darwin":
+    macos:
+      xcode: "9.0"
     steps:
-    - run:
-        name: git
-        command: |
-          apt-get update
-          apt-get install -y git openssh-client make automake autoconf gcc perl python3
-    - checkout
-    - run:
-        name: submodules
-        command: |
-          # Use github.com/ghc for those submodule repositories we couldn't connect to.
-          git config remote.origin.url git://github.com/ghc/ghc.git
-          git config --global url."git://github.com/ghc/packages-".insteadOf git://github.com/ghc/packages/
-          git submodule init # Don't be quiet, we want to show these urls.
-          git submodule --quiet update --recursive # Now we can be quiet again.
-    - run:
-        name: build
-        command: |
-          echo 'BUILD_SPHINX_HTML  = NO' >> mk/validate.mk
-          echo 'BUILD_SPHINX_PDF   = NO' >> mk/validate.mk
-          THREADS=8 SKIP_PERF_TESTS=YES VERBOSE=2 ./validate --fast --quiet
+      - checkout
+      - *prepare
+      - *submodules
+      - *build
+      - *collectartifacts
+      - store-artifacts:
+          path: /tmp/artifacts
+
+workflows:
+  version: 2
+  validate:
+    jobs:
+    - validate-x86_64-linux
+    # FreeBSD disabled: https://github.com/haskell/unix/issues/102
+    # - validate-x86_64-freebsd
+    - validate-x86_64-darwin
diff --git a/.circleci/fetch-submodules.sh b/.circleci/fetch-submodules.sh
new file mode 100755 (executable)
index 0000000..7279d21
--- /dev/null
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+# Use github.com/ghc for those submodule repositories we couldn't connect to.
+git config remote.origin.url git://github.com/ghc/ghc.git
+git config --global url."git://github.com/ghc/packages-".insteadOf git://github.com/ghc/packages/
+git submodule init # Don't be quiet, we want to show these urls.
+git submodule --quiet update --recursive # Now we can be quiet again.
diff --git a/.circleci/images/x86_64-freebsd/Dockerfile b/.circleci/images/x86_64-freebsd/Dockerfile
new file mode 100644 (file)
index 0000000..9c51cc0
--- /dev/null
@@ -0,0 +1,24 @@
+FROM ubuntu:16.04
+
+RUN apt-get update && apt-get install -y --no-install-recommends \
+  autoconf \
+  automake \
+  bzip2 \
+  ca-certificates \
+  curl \
+  file \
+  g++ \
+  git \
+  make \
+  openssh-client \
+  patch \
+  perl \
+  python2.7 \
+  python3 \
+  software-properties-common \
+  sudo \
+  wget \
+  xz-utils
+
+COPY build-toolchain.sh /tmp/
+RUN /tmp/build-toolchain.sh x86_64
diff --git a/.circleci/images/x86_64-freebsd/build-toolchain.sh b/.circleci/images/x86_64-freebsd/build-toolchain.sh
new file mode 100755 (executable)
index 0000000..56b8315
--- /dev/null
@@ -0,0 +1,102 @@
+#!/usr/bin/env bash
+
+set -ex
+
+ARCH=$1
+BINUTILS=2.25.1
+GCC=6.4.0
+FREEBSD=10.4-RELEASE
+
+mkdir binutils
+cd binutils
+
+# Build binutils for target platform.
+curl https://ftp.gnu.org/gnu/binutils/binutils-$BINUTILS.tar.bz2 | tar xjf -
+
+mkdir binutils-build
+cd binutils-build
+../binutils-$BINUTILS/configure --target=$ARCH-unknown-freebsd10
+make -j$(nproc)
+make install
+cd ..
+
+cd ..
+rm -rf binutils
+
+mkdir freebsd
+case "$ARCH" in
+    x86_64)
+       FREEBSD_ARCH=amd64
+    ;;
+    i686)
+       FREEBSD_ARCH=i386
+    ;;
+esac
+    
+URL=ftp://ftp.freebsd.org/pub/FreeBSD/releases/$FREEBSD_ARCH/$FREEBSD/base.txz
+curl $URL | tar xJf - -C freebsd ./usr/include ./usr/lib ./lib
+
+dst=/usr/local/$ARCH-unknown-freebsd10
+
+cp -r freebsd/usr/include $dst/
+cp freebsd/usr/lib/crt1.o $dst/lib
+cp freebsd/usr/lib/Scrt1.o $dst/lib
+cp freebsd/usr/lib/crti.o $dst/lib
+cp freebsd/usr/lib/crtn.o $dst/lib
+cp freebsd/usr/lib/libc.a $dst/lib
+cp freebsd/usr/lib/libutil.a $dst/lib
+cp freebsd/usr/lib/libutil_p.a $dst/lib
+cp freebsd/usr/lib/libm.a $dst/lib
+cp freebsd/usr/lib/librt.so.1 $dst/lib
+cp freebsd/usr/lib/libexecinfo.so.1 $dst/lib
+cp freebsd/lib/libc.so.7 $dst/lib
+cp freebsd/lib/libm.so.5 $dst/lib
+cp freebsd/lib/libutil.so.9 $dst/lib
+cp freebsd/lib/libthr.so.3 $dst/lib
+cp freebsd/lib/libncurses.so.8 $dst/lib
+cp freebsd/lib/libncursesw.so.8 $dst/lib
+
+# Install iconv port in target env.
+URL_ICONV=http://pkg.freebsd.org/FreeBSD:11:$FREEBSD_ARCH/latest/All/libiconv-1.14_11.txz
+curl $URL_ICONV | tar xJf - -C freebsd
+cp -r freebsd/usr/local/include $dst/
+cp -d freebsd/usr/local/lib/* $dst/lib
+
+ln -s libc.so.7 $dst/lib/libc.so
+ln -s libm.so.5 $dst/lib/libm.so
+ln -s librt.so.1 $dst/lib/librt.so
+ln -s libutil.so.9 $dst/lib/libutil.so
+ln -s libexecinfo.so.1 $dst/lib/libexecinfo.so
+ln -s libthr.so.3 $dst/lib/libpthread.so
+ln -s libncurses.so.8 $dst/lib/libncurses.so
+ln -s libncursesw.so.8 $dst/lib/libncursesw.so
+rm -rf freebsd
+
+# Build gcc for target platform.
+mkdir gcc
+cd gcc
+curl https://ftp.gnu.org/gnu/gcc/gcc-$GCC/gcc-$GCC.tar.gz | tar xzf -
+cd gcc-$GCC
+./contrib/download_prerequisites
+
+mkdir ../gcc-build
+cd ../gcc-build
+../gcc-$GCC/configure \
+    --enable-languages=c \
+    --target=$ARCH-unknown-freebsd10 \
+    --disable-nls \
+    --disable-libgomp \
+    --disable-libquadmath \
+    --disable-libssp \
+    --disable-libvtv \
+    --disable-libcilkrts \
+    --disable-libada \
+    --disable-libsanitizer \
+    --disable-libquadmath-support \
+    --disable-lto
+make -j$(nproc)
+make install
+cd ..
+
+cd ..
+rm -rf gcc
diff --git a/.circleci/prepare-system.sh b/.circleci/prepare-system.sh
new file mode 100755 (executable)
index 0000000..5d4d630
--- /dev/null
@@ -0,0 +1,46 @@
+#!/usr/bin/env bash
+# vim: sw=2 et
+set -euo pipefail
+
+fail() {
+  echo "ERROR: $*" >&2
+  exit 1
+}
+
+case "$(uname)" in
+  Linux)
+    if [[ -n ${TARGET:-} ]]; then
+      if [[ $TARGET = FreeBSD ]]; then
+        # cross-compiling to FreeBSD
+        add-apt-repository -y ppa:hvr/ghc
+        apt-get update -qq
+        apt-get install -qy ghc-8.0.2 cabal-install  alex happy ncurses-dev git openssh-client make automake autoconf gcc perl python3 texinfo xz-utils
+        cabal update
+        cabal install --reinstall hscolour
+        ln -s $HOME/.cabal/bin/HsColour /usr/local/bin/HsColour
+      else
+        fail "TARGET=$target not supported"
+      fi
+    else
+      # assuming Ubuntu
+      apt-get update -qq
+      apt-get install -qy git openssh-client make automake autoconf gcc perl python3 texinfo xz-utils
+      cabal update
+      cabal install --reinstall hscolour
+    fi
+    ;;
+  Darwin)
+    if [[ -n ${TARGET:-} ]]; then
+      fail "uname=$(uname) not supported for cross-compilation"
+    fi
+    brew install ghc cabal-install python3 ncurses
+    cabal update
+    cabal install --reinstall alex happy haddock hscolour
+    # put them on the $PATH, don't fail if already installed
+    ln -s $HOME/.cabal/bin/alex /usr/local/bin/alex || true
+    ln -s $HOME/.cabal/bin/happy /usr/local/bin/happy || true
+    ln -s $HOME/.cabal/bin/hscolour /usr/local/bin/hscolour || true
+    ;;
+  *)
+    fail "uname=$(uname) not supported"
+esac