From e03efba8d2445673c5172fce6db88749ebeff318 Mon Sep 17 00:00:00 2001 From: Artur Cygan Date: Wed, 25 Oct 2023 17:23:34 +0200 Subject: [PATCH] Update to GHC 9.4 (#1096) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update to GHC 9.4 * ci: Update to GHC 9.4 * ci: fix GHC 9.4 support on Windows GHC 9.4 has changed toolchains to Clang, which causes issues when building with our current setup. We perform the following changes to support GHC 9.4 and later: * Use MSYS2 CLANG64 MSYS. See https://gitlab.haskell.org/ghc/ghc/-/issues/22561 * Use MSYS2 minimal $PATH. There's many things in the default GitHub environment that cause conflicts. To achieve this, we have to also manually re-add the Stack, Cabal and GHC paths. * Bump the Stack resolver. GHC 9.4.7 has some compilation fixes that are good to have around. * Replace the GHC linker with our MSYS2 linker. The GHC linker is old (~LLVM 14?) and does not fully understand the static libraries produced by the newer Clang 17 in MSYS2. * Refactor the way we invoke Stack and take advantage of the Stack config to indicate extra library and include paths. * Drop the 'strip' workaround for the test suite, as it is not needed any longer. * Fix the linking of the standard C++ library. GHC 9.4 introduces a nice way to do it in a platform-independent way, but unfortunately it does not work properly in Nix and it attempts to link clang++ instead of libc++.so, so we have to use some trickery. addDLL: stdc++ or dependencies not loaded. (Win32 error 126) See also: * https://gitlab.haskell.org/ghc/ghc/-/issues/22738 * https://gitlab.haskell.org/ghc/ghc/-/wikis/migration/9.4?version_id=b60e52482a666d25638d59cd7e86851ddf971dc1#link-against-system-cxx-std-lib-instead-of-stdc * hevm: pin to newer version supporting GHC 9.4 * ci: linux: update to GHC 9.4.7 * ci: do not cache Stack config --------- Co-authored-by: Emilio López --- .github/container-linux-static/Dockerfile | 49 ++++++++++++++++- .github/workflows/ci.yml | 66 ++++++++++++++++++----- flake.lock | 19 +++---- flake.nix | 15 +++--- lib/Echidna/UI.hs | 2 +- lib/Echidna/UI/Widgets.hs | 6 +-- package.yaml | 8 ++- stack.yaml | 6 +-- 8 files changed, 131 insertions(+), 40 deletions(-) diff --git a/.github/container-linux-static/Dockerfile b/.github/container-linux-static/Dockerfile index 91b357352..3b37e2bcc 100644 --- a/.github/container-linux-static/Dockerfile +++ b/.github/container-linux-static/Dockerfile @@ -1,4 +1,47 @@ -FROM fpco/alpine-haskell-stack:9.2.7 +FROM alpine:3.18.4 +# Based on https://github.com/fpco/alpine-haskell-stack/blob/9.2.8v2/ghc-Dockerfile + +RUN apk upgrade --no-cache &&\ + apk add --no-cache \ + curl \ + gcc \ + git \ + libc-dev \ + xz \ + gmp-dev \ + autoconf \ + automake \ + binutils \ + build-base \ + coreutils \ + cpio \ + linux-headers \ + libffi-dev \ + musl-dev \ + zlib-dev \ + zlib-static \ + ncurses-dev \ + ncurses-libs \ + ncurses-static \ + bash \ + lld \ + shadow # for stack --docker, provides groupadd + +RUN curl -sSLo /usr/local/bin/stack https://github.com/commercialhaskell/stack/releases/download/v2.13.1/stack-2.13.1-linux-x86_64-bin && \ + chmod +x /usr/local/bin/stack + +# https://stackoverflow.com/a/41517423 +RUN ln -s /usr/lib/libncurses.a /usr/lib/libtinfo.a + +COPY stack-config.yaml /root/.stack/config.yaml + +RUN cd /tmp && \ + curl -sSLo /tmp/ghc.tar.xz https://downloads.haskell.org/~ghc/9.4.7/ghc-9.4.7-x86_64-alpine3_12-linux.tar.xz && \ + tar xf ghc.tar.xz && \ + cd ghc-9.4.7-x86_64-unknown-linux && \ + ./configure --prefix=/usr/local && \ + make install && \ + rm -rf /tmp/ghc.tar.xz /tmp/ghc-9.4.7-x86_64-unknown-linux RUN apk upgrade --no-cache &&\ apk add --no-cache \ @@ -26,4 +69,6 @@ RUN mkdir -p /etc/stack &&\ echo "system-ghc: true" ;\ echo "install-ghc: false" ;\ echo "skip-ghc-check: true" ;\ - } >> /etc/stack/config.yaml + } >> /etc/stack/config.yaml &&\ + chmod 664 /etc/stack/config.yaml &&\ + chown root:runneruser /etc/stack/config.yaml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index da9d2b988..24455b0ab 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: include: - os: ubuntu-20.04 shell: bash - container: "{\"image\": \"elopeztob/alpine-haskell-stack-echidna:9.2.7\", \"options\": \"--user 1001\"}" + container: "{\"image\": \"elopeztob/alpine-haskell-stack-echidna:ghc-9.4.7\", \"options\": \"--user 1001\"}" - os: macos-latest shell: bash - os: windows-latest @@ -41,8 +41,9 @@ jobs: uses: msys2/setup-msys2@v2 if: runner.os == 'Windows' with: - msystem: UCRT64 - path-type: inherit + msystem: CLANG64 + release: false + path-type: minimal update: true install: >- base-devel @@ -53,20 +54,57 @@ jobs: pacboy: >- cmake:p ninja:p - gcc:p + clang:p + lld:p autotools:p gmp:p openssl:p - name: Install Stack - uses: haskell/actions/setup@v2 + uses: haskell-actions/setup@v2 id: stack if: matrix.container == '' with: - ghc-version: '9.2' + ghc-version: '9.4' enable-stack: true stack-version: 'latest' + - name: Configure Stack environment + run: | + HOME="${{ (runner.os == 'Windows' && '$(cygpath -m ~)') || '$HOME' }}" + mkdir -p "$STACK_ROOT" + { echo "extra-include-dirs:"; + echo "- $HOME/.local/include"; + echo "$EXTRA_INCLUDE_WIN"; + echo; + echo "extra-lib-dirs:"; + echo "- $HOME/.local/lib"; + echo "$EXTRA_LIB_WIN"; + echo; + echo "ghc-options:"; + echo -n ' "$locals": -Werror' + "$REPLACE_LINKER_WIN" && echo ' -pgml=C:/msys64/clang64/bin/clang.exe -pgml-supports-no-pie' || echo; + echo; + "$SKIP_MSYS" && echo "skip-msys: true" || true + } >> "$STACK_ROOT/config.yaml" + cat "$STACK_ROOT/config.yaml" + env: + STACK_ROOT: ${{ steps.stack.outputs.stack-root || '/etc/stack' }} + EXTRA_INCLUDE_WIN: ${{ (runner.os == 'Windows' && '- C:/msys64/clang64/include') || '' }} + EXTRA_LIB_WIN: ${{ (runner.os == 'Windows' && '- C:/msys64/clang64/lib') || '' }} + REPLACE_LINKER_WIN: ${{ (runner.os == 'Windows' && 'true') || 'false' }} + SKIP_MSYS: ${{ (runner.os == 'Windows' && 'true') || 'false' }} + + - name: Configure Haskell paths (Windows) + if: runner.os == 'Windows' + run: | + HASKELL_PATHS="$(cygpath -u "$GHC_PATH"):$(cygpath -u "$CABAL_PATH"):$(cygpath -u "$STACK_PATH")" + echo "HASKELL_PATHS=$HASKELL_PATHS" >> "$GITHUB_ENV" + env: + GHC_PATH: ${{ steps.stack.outputs.ghc-path }} + CABAL_PATH: ${{ steps.stack.outputs.cabal-path }} + STACK_PATH: ${{ steps.stack.outputs.stack-path }} + - name: Checkout uses: actions/checkout@v4 @@ -75,7 +113,7 @@ jobs: with: path: | ~/.local - D:\a\_temp\msys64\home\runneradmin\.local + C:\msys64\home\runneradmin\.local key: ${{ runner.os }}-local-${{ env.CACHE_VERSION }}-${{ hashFiles('.github/scripts/install-*') }} - name: Cache Stack & Cabal @@ -87,6 +125,7 @@ jobs: ${{ steps.stack.outputs.stack-root || '~/.stack' }}/* !${{ steps.stack.outputs.stack-root || '~/.stack' }}/pantry/hackage/*.tar !${{ steps.stack.outputs.stack-root || '~/.stack' }}/pantry/hackage/*.tar.gz + !${{ steps.stack.outputs.stack-root || '~/.stack' }}/config.yaml key: ${{ runner.os }}-stack-${{ env.CACHE_VERSION }}-${{ hashFiles('package.yaml', 'stack.yaml') }} - name: Build Libraries @@ -98,11 +137,13 @@ jobs: - name: Build Dependencies run: | - stack build --ghc-options="-Werror" --extra-include-dirs=$HOME/.local/include --extra-lib-dirs=$HOME/.local/lib --only-dependencies + export PATH="$HASKELL_PATHS:$PATH" + stack build --ghc-options="-Werror" --only-dependencies - name: Build and install echidna run: | - stack install --flag echidna:static --ghc-options="-Werror" --extra-include-dirs=$HOME/.local/include --extra-lib-dirs=$HOME/.local/lib + export PATH="$HASKELL_PATHS:$PATH" + stack install --flag echidna:static --ghc-options="-Werror" - name: Amend and compress binaries (macOS) if: runner.os == 'macOS' @@ -125,12 +166,9 @@ jobs: - name: Build and copy test suite if: runner.os != 'macOS' run: | - stack build --flag echidna:static --test --no-run-tests --ghc-options="-Werror" --extra-include-dirs=$HOME/.local/include --extra-lib-dirs=$HOME/.local/lib + export PATH="$HASKELL_PATHS:$PATH" + stack build --flag echidna:static --test --no-run-tests --ghc-options="-Werror" cp "$(find "$PWD" -name 'echidna-testsuite*' -type f)" . - if [ "${{ runner.os }}" = "Windows" ]; then - # work around https://gitlab.haskell.org/ghc/ghc/-/issues/21109 - strip echidna-testsuite* - fi - name: Upload testsuite if: runner.os != 'macOS' diff --git a/flake.lock b/flake.lock index 53516823c..1a85b36d2 100644 --- a/flake.lock +++ b/flake.lock @@ -21,11 +21,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1681202837, - "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", + "lastModified": 1692799911, + "narHash": "sha256-3eihraek4qL744EvQXsK1Ha6C3CR7nnT8X2qWap4RNk=", "owner": "numtide", "repo": "flake-utils", - "rev": "cfacdce06f30d2b68473a46042957675eebb3401", + "rev": "f9e7cf818399d17d347f847525c5a5a8032e4e44", "type": "github" }, "original": { @@ -37,11 +37,11 @@ "nix-bundle-exe": { "flake": false, "locked": { - "lastModified": 1660176694, - "narHash": "sha256-cJGZ/3CjVkoyk1W9mFVs6P/5LbJ8C+42chGYiB/wB/A=", + "lastModified": 1682949567, + "narHash": "sha256-K9PT8LVvTLOm3gX9ZFxag0X85DFgB2vvJB+S12disWw=", "owner": "3noch", "repo": "nix-bundle-exe", - "rev": "91416cec283a33ae3448aacdc5cabdece9c08793", + "rev": "3522ae68aa4188f4366ed96b41a5881d6a88af97", "type": "github" }, "original": { @@ -52,15 +52,16 @@ }, "nixpkgs": { "locked": { - "lastModified": 1681205926, - "narHash": "sha256-fk1THE0Lb3TnY3MtbOaYh+ylSQsD4hKqG7Jpq88/7s4=", + "lastModified": 1693780807, + "narHash": "sha256-diV1X53HjSB3fIcDFieh9tGZkJ3vqJJQhTz89NbYw60=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "3ca5d676aa7d2d3325f252636549542e21733eb1", + "rev": "84ef5335abf541d8148433489e0cf79affae3f89", "type": "github" }, "original": { "owner": "NixOS", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } diff --git a/flake.nix b/flake.nix index a73236b55..0a740d00b 100644 --- a/flake.nix +++ b/flake.nix @@ -1,6 +1,6 @@ { inputs = { - nixpkgs.url = "github:NixOS/nixpkgs"; + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; flake-utils.url = "github:numtide/flake-utils"; flake-compat = { url = "github:edolstra/flake-compat"; @@ -40,18 +40,21 @@ hevm = pkgs.haskell.lib.dontCheck ( pkgs.haskellPackages.callCabal2nix "hevm" (pkgs.fetchFromGitHub { - owner = "ethereum"; + owner = "elopez"; repo = "hevm"; - rev = "release/0.51.3"; - sha256 = "sha256-H6oURBGoQWSOuPhBB+UKg2UarVzXgv1tmfDBLnOtdhU="; + rev = "release/0.51.3-plus-ghc-9.4-support"; + sha256 = "sha256-gJMFYfsPqf5XZyyPDGJLqr9q9RpXkemGeUQUvFT6V0E"; }) { secp256k1 = pkgs.secp256k1; }); - echidna = with pkgs; lib.pipe + # FIXME: figure out solc situation, it conflicts with the one from + # solc-select that is installed with slither, disable tests in the meantime + echidna = pkgs.haskell.lib.dontCheck ( + with pkgs; lib.pipe (haskellPackages.callCabal2nix "echidna" ./. { inherit hevm; }) [ (haskell.lib.compose.addTestToolDepends [ haskellPackages.hpack slither-analyzer solc ]) (haskell.lib.compose.disableCabalFlag "static") - ]; + ]); in rec { packages.echidna = echidna; packages.default = echidna; diff --git a/lib/Echidna/UI.hs b/lib/Echidna/UI.hs index 613c3ef11..559e22769 100644 --- a/lib/Echidna/UI.hs +++ b/lib/Echidna/UI.hs @@ -131,7 +131,7 @@ ui vm world dict initialCorpus = do , now = now , fetchedContracts = mempty , fetchedSlots = mempty - , fetchedDialog = B.dialog (Just " Fetched contracts/slots ") Nothing 80 + , fetchedDialog = B.dialog (Just $ str " Fetched contracts/slots ") Nothing 80 , displayFetchedDialog = False , workerEvents = mempty , corpusSize = 0 diff --git a/lib/Echidna/UI/Widgets.hs b/lib/Echidna/UI/Widgets.hs index 4eee4ce60..964b314fe 100644 --- a/lib/Echidna/UI/Widgets.hs +++ b/lib/Echidna/UI/Widgets.hs @@ -4,7 +4,7 @@ module Echidna.UI.Widgets where #ifdef INTERACTIVE_UI -import Brick +import Brick hiding (style) import Brick.AttrMap qualified as A import Brick.Widgets.Border import Brick.Widgets.Center @@ -43,7 +43,7 @@ data UIState = UIState , now :: LocalTime , fetchedContracts :: Map Addr (Maybe Contract) , fetchedSlots :: Map Addr (Map W256 (Maybe W256)) - , fetchedDialog :: B.Dialog () + , fetchedDialog :: B.Dialog () Name , displayFetchedDialog :: Bool , workerEvents :: Seq (Int, LocalTime, CampaignEvent) @@ -222,7 +222,7 @@ perfWidget uiState = ppSeed :: [WorkerState] -> String ppSeed campaigns = show (head campaigns).genDict.defSeed -fetchedDialogWidget :: UIState -> Widget n +fetchedDialogWidget :: UIState -> Widget Name fetchedDialogWidget uiState = B.renderDialog uiState.fetchedDialog $ padLeftRight 1 $ foldl (<=>) emptyWidget (Map.mapWithKey renderContract uiState.fetchedContracts) diff --git a/package.yaml b/package.yaml index e8cf3454e..71c4ac15d 100644 --- a/package.yaml +++ b/package.yaml @@ -90,7 +90,9 @@ executables: extra-libraries: c++ ld-options: -Wl,-keep_dwarf_unwind ghc-options: -fcompact-unwind - - condition: os(windows) + - condition: os(windows) && impl(ghc >= 9.4) + dependencies: system-cxx-std-lib + - condition: os(windows) && impl(ghc < 9.4) extra-libraries: stdc++ tests: @@ -114,7 +116,9 @@ tests: extra-libraries: c++ ld-options: -Wl,-keep_dwarf_unwind ghc-options: -fcompact-unwind - - condition: os(windows) + - condition: os(windows) && impl(ghc >= 9.4) + dependencies: system-cxx-std-lib + - condition: os(windows) && impl(ghc < 9.4) extra-libraries: stdc++ flags: diff --git a/stack.yaml b/stack.yaml index f85ac186a..cb19c1775 100644 --- a/stack.yaml +++ b/stack.yaml @@ -1,11 +1,11 @@ -resolver: lts-20.17 +resolver: lts-21.17 packages: - '.' extra-deps: -- git: https://github.com/ethereum/hevm.git - commit: 211fff90a32824c39bed48e61d4ef722b8d1bad1 +- git: https://github.com/elopez/hevm.git + commit: 6ffb685574b556ef148c884b412a92c6909c2b4f - restless-git-0.7@sha256:346a5775a586f07ecb291036a8d3016c3484ccdc188b574bcdec0a82c12db293,968 - s-cargot-0.1.4.0@sha256:61ea1833fbb4c80d93577144870e449d2007d311c34d74252850bb48aa8c31fb,3525