diff --git a/.github/workflows/workflow.yaml b/.github/workflows/workflow.yaml index 906cba9e..6db01e72 100644 --- a/.github/workflows/workflow.yaml +++ b/.github/workflows/workflow.yaml @@ -1,7 +1,9 @@ name: Continuous integration on: - - push - - pull_request + push: + branches: + - master + pull_request: jobs: build: @@ -12,18 +14,19 @@ jobs: run: | choco install -y haskell-stack choco install -y r --version 4.0.0 - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Get Stack snapshot install directory id: stack-snapshot + # NOTE: `stack path` must run at least once prior to caching to ensure the directory + # exists and is populated. run: | stack path --snapshot-install-root - echo "::set-output name=dir::$(stack path --snapshot-install-root)" - - uses: actions/cache@v1 + "dir=$(stack path --snapshot-install-root)" | Out-File -FilePath $env:GITHUB_OUTPUT -Append + - uses: actions/cache@v4 with: path: ${{ steps.stack-snapshot.outputs.dir }} - key: ${{ steps.stack-snapshot.outputs.dir }}-${{ hashFiles('**/*.cabal') }} - restore-keys: | - ${{ runner.os }}-stack- + key: ${{ runner.os }}-stack-${{ hashFiles('**/*.cabal') }} + restore-keys: ${{ runner.os }}-stack- - name: Build run: | stack build inline-r H ` @@ -32,32 +35,39 @@ jobs: test: name: Build & Test - ${{ matrix.os }} - ${{ matrix.stack_yaml }} strategy: + fail-fast: false matrix: - os: [ubuntu-latest, macos-latest] - stack_yaml: [stack.yaml, stack-lts-18.yaml, stack-lts-19.yaml] + os: + - macos-latest + - ubuntu-latest + stack_yaml: + - stack.yaml + - stack-lts-19.yaml + - stack-lts-20.yaml + - stack-lts-21.yaml runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2 - - uses: cachix/install-nix-action@v15 - with: - nix_path: nixpkgs=./nixpkgs.nix + - uses: actions/checkout@v4 + - uses: DeterminateSystems/nix-installer-action@main + - uses: DeterminateSystems/magic-nix-cache-action@main - name: Install Stack run: | - nix-env -f. -iA nixpkgs.stack + nix-env --file ./nixpkgs.nix --install --attr stack - name: Get Stack snapshot install directory id: stack-snapshot + # NOTE: `stack path` must run at least once prior to caching to ensure the directory + # exists and is populated. + # NOTE: The renaming of the stack.yaml file is a workaround for + # https://github.com/commercialhaskell/stack/issues/5028. run: | - # XXX Workaround - # https://github.com/commercialhaskell/stack/issues/5028. [ ${{ matrix.stack_yaml }} = stack.yaml ] || mv ${{ matrix.stack_yaml }} stack.yaml stack --nix path --snapshot-install-root - echo "::set-output name=dir::$(stack --nix path --snapshot-install-root)" - - uses: actions/cache@v2 + echo "dir=$(stack --nix path --snapshot-install-root)" > "${GITHUB_OUTPUT}" + - uses: actions/cache@v4 with: path: ${{ steps.stack-snapshot.outputs.dir }} - key: ${{ steps.stack-snapshot.outputs.dir }}-${{ hashFiles('**/*.cabal') }} - restore-keys: | - ${{ steps.stack-snapshot.outputs.dir }} + key: ${{ runner.os }}-stack-${{ hashFiles('**/*.cabal') }} + restore-keys: ${{ runner.os }}-stack- - name: Build run: | stack --nix build @@ -69,6 +79,6 @@ jobs: if: ${{ runner.os == 'Linux' }} run: | stack --nix install - export PATH=~/.local/bin:$PATH + export PATH="$HOME/.local/bin:$PATH" stack --nix exec -- ihaskell install stack --nix exec -- jupyter nbconvert --to notebook --execute --inplace ./IHaskell/examples/tutorial-ihaskell-inline-r.ipynb diff --git a/inline-r/src/Language/R/HExp.hs b/inline-r/src/Language/R/HExp.hs index 91bcc9a3..028b402a 100644 --- a/inline-r/src/Language/R/HExp.hs +++ b/inline-r/src/Language/R/HExp.hs @@ -336,12 +336,12 @@ peekHExp s = do <*> (coerceAnySome <$> R.cdr su) R.Special -> coerce $ return Special R.Builtin -> coerce $ return Builtin - R.Char -> unsafeCoerce $ Char (Vector.unsafeFromSEXP su) - R.Logical -> unsafeCoerce $ Logical (Vector.unsafeFromSEXP su) - R.Int -> unsafeCoerce $ Int (Vector.unsafeFromSEXP su) - R.Real -> unsafeCoerce $ Real (Vector.unsafeFromSEXP su) - R.Complex -> unsafeCoerce $ Complex (Vector.unsafeFromSEXP su) - R.String -> unsafeCoerce $ String (Vector.unsafeFromSEXP su) + R.Char -> coerce $ return $ Char (Vector.unsafeFromSEXP su) + R.Logical -> coerce $ return $ Logical (Vector.unsafeFromSEXP su) + R.Int -> coerce $ return $ Int (Vector.unsafeFromSEXP su) + R.Real -> coerce $ return $ Real (Vector.unsafeFromSEXP su) + R.Complex -> coerce $ return $ Complex (Vector.unsafeFromSEXP su) + R.String -> coerce $ return $ String (Vector.unsafeFromSEXP su) R.DotDotDot -> unimplemented $ "peekHExp: " ++ show (R.typeOf s) R.Vector -> coerce $ Vector <$> (fromIntegral <$> R.trueLength (coerceAny su)) @@ -363,7 +363,7 @@ peekHExp s = do peekElemOff (castPtr $ R.unsafeSEXPToVectorPtr s) 2) <*> (coerceAny <$> R.sexp <$> peekElemOff (castPtr $ R.unsafeSEXPToVectorPtr s) 3) - R.Raw -> unsafeCoerce $ Raw (Vector.unsafeFromSEXP su) + R.Raw -> coerce $ return $ Raw (Vector.unsafeFromSEXP su) R.S4 -> coerce $ S4 <$> (coerceAnySome <$> R.tag su) _ -> unimplemented $ "peekHExp: " ++ show (R.typeOf s) diff --git a/inline-r/tests/Test/Event.hs b/inline-r/tests/Test/Event.hs index 329b6576..58dae207 100644 --- a/inline-r/tests/Test/Event.hs +++ b/inline-r/tests/Test/Event.hs @@ -82,7 +82,11 @@ tests = testGroup "events" withSystemTempFile "inline-r-" $ \path h -> do hPutStrLn h "hello" hClose h +#if MIN_VERSION_unix(2,8,0) + fd <- openFd path ReadOnly defaultFileFlags{ nonBlock = True } +#else fd <- openFd path ReadOnly Nothing defaultFileFlags{ nonBlock = True } +#endif action fd closeFd fd #endif diff --git a/nixpkgs.nix b/nixpkgs.nix index c5f229f0..217e0408 100644 --- a/nixpkgs.nix +++ b/nixpkgs.nix @@ -1,9 +1,11 @@ let - # NixOS/Nixpkgs master 2022-11-27 - rev = "a115bb9bd56831941be3776c8a94005867f316a7"; - sha256 = "1501jzl4661qwr45b9ip7c7bpmbl94816draybhh60s9wgxn068d"; + # NixOS/Nixpkgs master on 2024-02-01 + rev = "a6fefb39e18b6ff828c04d59ea26d4988135bb88"; + sha256 = "sha256-lsnvxt/1KCUgrV8KURXdZXRo+mLUZdc7o5H0MvYFOHQ="; in -import (fetchTarball { - inherit sha256; - url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz"; -}) +import ( + fetchTarball { + inherit sha256; + url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz"; + } +) diff --git a/shell-lts-19.nix b/shell-lts-19.nix new file mode 100644 index 00000000..80ff12ef --- /dev/null +++ b/shell-lts-19.nix @@ -0,0 +1 @@ +builtins.import ./shell.nix { ghcAttr = "ghc90"; } diff --git a/shell-lts-20.nix b/shell-lts-20.nix new file mode 100644 index 00000000..c02b3a02 --- /dev/null +++ b/shell-lts-20.nix @@ -0,0 +1 @@ +builtins.import ./shell.nix { ghcAttr = "ghc92"; } diff --git a/shell-lts-21.nix b/shell-lts-21.nix new file mode 100644 index 00000000..6f56f41c --- /dev/null +++ b/shell-lts-21.nix @@ -0,0 +1 @@ +builtins.import ./shell.nix { ghcAttr = "ghc94"; } diff --git a/shell.nix b/shell.nix index 53f2f8b9..93e68288 100644 --- a/shell.nix +++ b/shell.nix @@ -1,43 +1,137 @@ -{ pkgs ? import ./nixpkgs.nix { }, ghc ? pkgs.haskell.compiler.ghc8107 }: +{ + pkgs ? import ./nixpkgs.nix { }, + ghcAttr ? "ghc96", + RVersion ? "4.2.3", +}: +let + inherit (pkgs) + cabal-install + fetchpatch + fetchurl + haskell + python3 + rPackages + rWrapper + stdenv + zeromq + zlib + ; -with pkgs; + inherit (pkgs.lib) lists strings versions; -let - # Uncomment the line below to build HaskellR against a version of R with + # Set enableStrictBarrier to true to build HaskellR against a version of R with # the --enable-strict-barrier configure flag enabled for better memory # diagnostics. + R = (pkgs.R.override { enableStrictBarrier = false; }).overrideAttrs ( + # Pin R to a specific version to avoid breaking changes in the R API. + finalAttrs: prevAttrs: { + version = RVersion; + src = fetchurl { + url = "https://cran.r-project.org/src/base/R-${versions.major finalAttrs.version}/R-${finalAttrs.version}.tar.gz"; + hash = builtins.getAttr RVersion { + "4.0.0" = "sha256-Br6wKRtWmXhITrDctdIzlmXsdFc3vftOhz56WnVJKUA="; + "4.0.1" = "sha256-lf4kpNjY+PiIRgyPX+QxHOxlbnoXItIzIYvAOGG8bzI="; + "4.0.2" = "sha256-07zqs2TaCHZiXkCXgItCUSOV/fQSkvSRWrH9JXwbvnU="; + "4.0.3" = "sha256-CZg6injV+2vEXSexxV+bpSZfePpUpVwTrmkfh8W7ng0="; + "4.0.4" = "sha256-Uj8n1pdEoIyPC9Xh5sPYmk2yntmDOIunCWOjzTpKgC4="; + "4.0.5" = "sha256-Cj7geap3LhMf5UNTEatif8vMtaUMq8VCkub2IEbx/+8="; + "4.1.0" = "sha256-6OaJWdcoLKFHNg/JZEram9FhureBurFNM7iZmpUYJ4E="; + "4.1.1" = "sha256-UV4DJldSJX0LcDbzgPguQrRu2Ec/VPJce2ftJbu902Q="; + "4.1.2" = "sha256-IDYiXp9yB9TOCX5Ulyrs2qi0DX2ZEc0mSR+sWg+rOK8="; + "4.1.3" = "sha256-Ff9bMzxhCUBgsqUunB2OxVzELdAp45yiKr2qkJUm/tY="; + "4.2.0" = "sha256-OOq3cZt60JU4jwaqCQxaKyAnkZRd5g0+K7DqsfUJdIg="; + "4.2.1" = "sha256-TVLbSG0nhI5UYT1O6XetlS7AjOF4B+G1JbEM1ENsZD8="; + "4.2.2" = "sha256-D/YrQuxRr6VxPK7nxP3noMRZQLo5vvjFyUh/7wyVPfU="; + "4.2.3" = "sha256-VeSpptQ74xTiwD0CZqb6VESv3OULMDv8O4Kzl5UW4HQ="; + "4.3.0" = "sha256-RdzEi2zyfTYQIPd/3ho5IJ6Ze4FAKzZjyhwBAFampgk="; + "4.3.1" = "sha256-jdC/JPECPG9hjDsxc4PSkbSklPQNc7mDrCL/6pnkupk="; + "4.3.2" = "sha256-s/V2CsLu6AJqPw7vyyW0dyPZeAOO7o6ER2IJTIYMRSo="; + }; + }; - # R = pkgs.R.override { enableStrictBarrier = true; }; - - # XXX Workaround https://ghc.haskell.org/trac/ghc/ticket/11042. - libHack = - if stdenv.isDarwin - then { DYLD_LIBRARY_PATH = [ "${R}/lib/R/lib" ]; } - else { LD_LIBRARY_PATH = [ "${R}/lib/R" ]; } - ; + patches = + prevAttrs.patches or [ ] + # R: 4.0.4 -> 4.1.0 + # See https://github.com/NixOS/nixpkgs/commit/9a88197fe7825f486052e3a9eca4a68192335978 + ++ + lists.optionals + ( + RVersion == "4.1.0" + && strings.hasInfix "--without-recommended-packages" (prevAttrs.preConfigure or "") + ) + [ + (fetchpatch { + name = "fix-tests-without-recommended-packages.patch"; + url = "https://github.com/wch/r-source/commit/7715c67cabe13bb15350cba1a78591bbb76c7bac.patch"; + # this part of the patch reverts something that was committed after R 4.1.0, so ignore it. + excludes = [ "tests/Pkgs/xDir/pkg/DESCRIPTION" ]; + hash = "sha256-iguLndCIuKuCxVCi/4NSu+9RzBx5JyeHx3K6IhpYshQ="; + }) + (fetchpatch { + name = "use-codetools-conditionally.patch"; + url = "https://github.com/wch/r-source/commit/7543c28b931db386bb254e58995973493f88e30d.patch"; + hash = "sha256-+yHXB5AItFyQjSxfogxk72DrSDGiBh7OiLYFxou6Xlk="; + }) + ] + # R: 4.1.3 -> 4.2.0 + # See: https://github.com/NixOS/nixpkgs/commit/5eb9f35c44d30153ff1df2105ed73e148a79a3ee + ++ lists.optionals (RVersion == "4.2.0" || RVersion == "4.2.1") [ + (fetchpatch { + name = "test-reg-packages.patch"; + url = "https://raw.githubusercontent.com/NixOS/nixpkgs/5eb9f35c44d30153ff1df2105ed73e148a79a3ee/pkgs/applications/science/math/R/test-reg-packages.patch"; + hash = "sha256-FUzrenAFvD8GL1/RMG8DRRx+ITcEkDkRGKTVyAhyKqA="; + }) + ]; - python3Env = python3.withPackages (ps: with ps; [ - ipython - jupyter_client - notebook - ]); + postPatch = + prevAttrs.postPatch or "" + # Nixpkgs ships with curl >= 8.x, which is not compatible with R pre-4.3. However, in the release notes for R + # 4.3 (https://stat.ethz.ch/pipermail/r-announce/2023/000691.html), it is mentioned that despite the major + # version change for curl, the API is still compatible with the previous version. Therefore, we can patch the + # check for curl 7.x. This fixes the following error: + # error: libcurl >= 7.28.0 library and headers are required with support for https + # We must patch the ./configure script and the ./m4/R.m4 file to make this work. + + strings.optionalString (strings.versionOlder RVersion "4.3.0") '' + substituteInPlace \ + ./configure \ + ./m4/R.m4 \ + --replace-fail \ + "#if LIBCURL_VERSION_MAJOR > 7" \ + "#if LIBCURL_VERSION_MAJOR < 7" \ + --replace-fail \ + "#elif LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 28" \ + "#elif LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 28 || LIBCURL_VERSION_MAJOR == 8" + ''; + } + ); rEnv = rWrapper.override { - packages = with rPackages; [ - # ggplot2 is required for ./IHaskell/examples/tutorial-ihaskell-inline-r.ipynb - ggplot2 - ]; + inherit R; + # ggplot2 is required for ./IHaskell/examples/tutorial-ihaskell-inline-r.ipynb + packages = with rPackages; [ ggplot2 ]; }; -in -haskell.lib.buildStackProject ({ + python3Env = python3.withPackages ( + ps: with ps; [ + ipython + jupyter_client + notebook + ] + ); +in +haskell.lib.buildStackProject { name = "HaskellR"; - inherit ghc; + ghc = pkgs.haskell.compiler.${ghcAttr}; buildInputs = [ - zeromq - zlib + cabal-install python3Env rEnv + zeromq + zlib ]; LANG = "en_US.UTF-8"; -} // libHack) + # NOTE: Workaround https://ghc.haskell.org/trac/ghc/ticket/11042. + ${(strings.optionalString stdenv.isDarwin "DY") + "LD_LIBRARY_PATH"} = [ + ("${R}/lib/R" + (strings.optionalString stdenv.isDarwin "/lib")) + ]; +} diff --git a/stack-lts-19.yaml b/stack-lts-19.yaml index 6595e99a..0583f542 100644 --- a/stack-lts-19.yaml +++ b/stack-lts-19.yaml @@ -10,5 +10,5 @@ extra-deps: - ihaskell-blaze-0.3.0.1 nix: - shell-file: ./shell.nix + shell-file: ./shell-lts-19.nix path: ["nixpkgs=./nixpkgs.nix"] diff --git a/stack-lts-18.yaml b/stack-lts-20.yaml similarity index 70% rename from stack-lts-18.yaml rename to stack-lts-20.yaml index 1b632d1c..e75a1b15 100644 --- a/stack-lts-18.yaml +++ b/stack-lts-20.yaml @@ -1,4 +1,4 @@ -resolver: lts-18.28 +resolver: lts-20.26 packages: - examples @@ -10,5 +10,5 @@ extra-deps: - ihaskell-blaze-0.3.0.1 nix: - shell-file: ./shell.nix + shell-file: ./shell-lts-20.nix path: ["nixpkgs=./nixpkgs.nix"] diff --git a/stack-lts-18.yaml.lock b/stack-lts-20.yaml.lock similarity index 78% rename from stack-lts-18.yaml.lock rename to stack-lts-20.yaml.lock index 8331cd73..a2edf554 100644 --- a/stack-lts-18.yaml.lock +++ b/stack-lts-20.yaml.lock @@ -5,15 +5,15 @@ packages: - completed: + hackage: ihaskell-blaze-0.3.0.1@sha256:57f0e79758d084da3a662d0909ba2b01e469200029fed495fc208ba5f59024fd,2161 pantry-tree: sha256: 69fee7554a6410e45011c89d9e9547d18e2798e4f01ebd0426573b05e0e21696 size: 223 - hackage: ihaskell-blaze-0.3.0.1@sha256:57f0e79758d084da3a662d0909ba2b01e469200029fed495fc208ba5f59024fd,2161 original: hackage: ihaskell-blaze-0.3.0.1 snapshots: - completed: - sha256: 428ec8d5ce932190d3cbe266b9eb3c175cd81e984babf876b64019e2cbe4ea68 - size: 590100 - url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/28.yaml - original: lts-18.28 + sha256: 5a59b2a405b3aba3c00188453be172b85893cab8ebc352b1ef58b0eae5d248a2 + size: 650475 + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/20/26.yaml + original: lts-20.26 diff --git a/stack-lts-21.yaml b/stack-lts-21.yaml new file mode 100644 index 00000000..306f0ea0 --- /dev/null +++ b/stack-lts-21.yaml @@ -0,0 +1,17 @@ +resolver: lts-21.25 + +packages: +- examples +- H +- IHaskell +- inline-r + +extra-deps: +- ghc-parser-0.2.6.0 +- ihaskell-0.11.0.0 +- ihaskell-blaze-0.3.0.1 +- ipython-kernel-0.11.0.0 + +nix: + shell-file: ./shell-lts-21.nix + path: ["nixpkgs=./nixpkgs.nix"] diff --git a/stack-lts-21.yaml.lock b/stack-lts-21.yaml.lock new file mode 100644 index 00000000..bd107998 --- /dev/null +++ b/stack-lts-21.yaml.lock @@ -0,0 +1,40 @@ +# This file was autogenerated by Stack. +# You should not edit this file by hand. +# For more information, please see the documentation at: +# https://docs.haskellstack.org/en/stable/lock_files + +packages: +- completed: + hackage: ghc-parser-0.2.6.0@sha256:0b0cbceb3bd2762cef201dc54ae302d7918bed23b2f85ffd99c1c8b6a9df32b6,1579 + pantry-tree: + sha256: 02bb412e738063631d10750648b5c432d5df99599eaeff5050d92df6416df102 + size: 903 + original: + hackage: ghc-parser-0.2.6.0 +- completed: + hackage: ihaskell-0.11.0.0@sha256:beff2321a5d753d8d74509b6b1f4aebc9b466e32bb91d028dc60e08658184625,6729 + pantry-tree: + sha256: 40e8d35f3a061ee0f22825f72c42edfd2352a9a05a4ac85190b6e13a00c23aff + size: 2939 + original: + hackage: ihaskell-0.11.0.0 +- completed: + hackage: ihaskell-blaze-0.3.0.1@sha256:57f0e79758d084da3a662d0909ba2b01e469200029fed495fc208ba5f59024fd,2161 + pantry-tree: + sha256: 69fee7554a6410e45011c89d9e9547d18e2798e4f01ebd0426573b05e0e21696 + size: 223 + original: + hackage: ihaskell-blaze-0.3.0.1 +- completed: + hackage: ipython-kernel-0.11.0.0@sha256:4e1c174037c4088b0113663d17c443fb6612e0f7639d28152c1e237816972550,2676 + pantry-tree: + sha256: 56fb92a6761881b39a0a2e2835e9d6fecd0ad15310c2a5c854ea2abcc9e78ecd + size: 792 + original: + hackage: ipython-kernel-0.11.0.0 +snapshots: +- completed: + sha256: a81fb3877c4f9031e1325eb3935122e608d80715dc16b586eb11ddbff8671ecd + size: 640086 + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/21/25.yaml + original: lts-21.25 diff --git a/stack.yaml b/stack.yaml index 33dad3bd..ac41197c 100644 --- a/stack.yaml +++ b/stack.yaml @@ -1,4 +1,4 @@ -resolver: lts-20.11 +resolver: lts-22.8 packages: - examples diff --git a/stack.yaml.lock b/stack.yaml.lock index e58e29b7..f7581dda 100644 --- a/stack.yaml.lock +++ b/stack.yaml.lock @@ -13,7 +13,7 @@ packages: hackage: ihaskell-blaze-0.3.0.1 snapshots: - completed: - sha256: adbc602422dde10cc330175da7de8609e70afc41449a7e2d6e8b1827aa0e5008 - size: 649342 - url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/20/11.yaml - original: lts-20.11 + sha256: 56ef9e03804cb4827866e762dc9752eeb392adda8f4811690da110dd9a165b9e + size: 714105 + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/22/8.yaml + original: lts-22.8