diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 88ced05..7fc6c06 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,38 +1,28 @@ -name: CI - +name: ArrayFire CI on: push: - branches: [master] + branches: + - master pull_request: - branches: [master] + +env: + ACTIONS_ALLOW_UNSECURE_COMMANDS: true jobs: build: - runs-on: macos-latest - + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Install ArrayFire - run: brew install arrayfire - - - name: Set up GHC - uses: haskell-actions/setup@v2 - with: - ghc-version: '9.8.4' - cabal-version: 'latest' - - - name: Cache cabal store - uses: actions/cache@v4 + - uses: cachix/install-nix-action@v31 with: - path: ~/.cabal/store - key: ${{ runner.os }}-cabal-${{ hashFiles('cabal.project', '*.cabal') }} - restore-keys: | - ${{ runner.os }}-cabal- + nix_path: nixpkgs=channel:nixpkgs-unstable - - name: Configure - run: cabal configure --flags="disable-default-paths disable-build-tool-depends" --extra-include-dirs=$(brew --prefix arrayfire)/include --extra-lib-dirs=$(brew --prefix arrayfire)/lib + - name: Nix channel --update + run: nix-channel --update - - name: Build - run: cabal build arrayfire + - name: Cabal update + run: nix develop --command bash -c 'cabal update' + - name: Build and run tests + run: nix develop --command bash -c 'cabal install hspec-discover && cabal test' diff --git a/arrayfire.cabal b/arrayfire.cabal index df41c2f..74a6c74 100644 --- a/arrayfire.cabal +++ b/arrayfire.cabal @@ -7,7 +7,7 @@ license: BSD-3-Clause license-file: LICENSE author: David Johnson maintainer: code@dmj.io -copyright: David Johnson (c) 2018-2025 +copyright: David Johnson (c) 2018-2026 category: Math build-type: Custom extra-source-files: CHANGELOG.md @@ -88,7 +88,7 @@ library c-sources: cbits/wrapper.c build-depends: - base < 5, filepath, vector + base < 5, deepseq, filepath, vector hs-source-dirs: src ghc-options: diff --git a/flake.lock b/flake.lock index 27da0e5..c767330 100644 --- a/flake.lock +++ b/flake.lock @@ -1,28 +1,5 @@ { "nodes": { - "arrayfire-nix": { - "inputs": { - "flake-utils": [ - "flake-utils" - ], - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1692793973, - "narHash": "sha256-6dG41ile3T+6dfRazlcPBdKBarGesswsBpb40Lcf35U=", - "owner": "twesterhout", - "repo": "arrayfire-nix", - "rev": "4236770612b80a3f29adbd8d670f6cea2bc098ba", - "type": "github" - }, - "original": { - "owner": "twesterhout", - "repo": "arrayfire-nix", - "type": "github" - } - }, "flake-utils": { "inputs": { "systems": "systems" @@ -74,7 +51,6 @@ }, "root": { "inputs": { - "arrayfire-nix": "arrayfire-nix", "flake-utils": "flake-utils", "nix-filter": "nix-filter", "nixpkgs": "nixpkgs" diff --git a/flake.nix b/flake.nix index d7f0af7..9869b69 100644 --- a/flake.nix +++ b/flake.nix @@ -5,11 +5,6 @@ nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; flake-utils.url = "github:numtide/flake-utils"; nix-filter.url = "github:numtide/nix-filter"; - arrayfire-nix = { - url = "github:twesterhout/arrayfire-nix"; - inputs.flake-utils.follows = "flake-utils"; - inputs.nixpkgs.follows = "nixpkgs"; - }; }; outputs = inputs: @@ -30,13 +25,50 @@ ]; }; + # Build ArrayFire from the official binary installer; avoids freeimage entirely. + mkArrayfire = pkgs: pkgs.stdenv.mkDerivation rec { + pname = "arrayfire"; + version = "3.10.0"; + src = pkgs.fetchurl { + url = "https://arrayfire.s3.amazonaws.com/${version}/ArrayFire-v${version}_Linux_x86_64.sh"; + hash = "sha256-8SibCWnRxts79S6WEHb3skF2TIDl1QnjY6EiohmoIog="; + }; + nativeBuildInputs = [ pkgs.autoPatchelfHook ]; + # GPU/visualization libs (CUDA, OpenGL, GLFW, FreeImage, Intel OpenCL) are + # optional ArrayFire backends not available in headless CI environments. + autoPatchelfIgnoreMissingDeps = true; + buildInputs = with pkgs; [ + stdenv.cc.cc.lib + fftw + fftwFloat + openblas + ocl-icd + boost.out + ]; + unpackPhase = "true"; + installPhase = '' + mkdir -p $out + bash $src --exclude-subdir --prefix=$out + ''; + meta = { + description = "A general-purpose library for parallel and massively-parallel architectures"; + platforms = [ "x86_64-linux" ]; + }; + }; + + arrayfire-overlay = self: super: { + arrayfire = mkArrayfire self; + }; + # An overlay that lets us test arrayfire-haskell with different GHC versions arrayfire-haskell-overlay = self: super: { haskell = super.haskell // { packageOverrides = inputs.nixpkgs.lib.composeExtensions super.haskell.packageOverrides (hself: hsuper: { arrayfire = self.haskell.lib.appendConfigureFlags - (hself.callCabal2nix "arrayfire" src { af = self.arrayfire; }) + (hself.callCabal2nix "arrayfire" src { + af = self.arrayfire; + }) [ "-f disable-default-paths" ]; }); }; @@ -55,21 +87,20 @@ cabal-install doctest hsc2hs - hspec-discover - # Language servers - haskell-language-server + # hspec-discover nil # Formatters nixpkgs-fmt ]; shellHook = '' + export LD_LIBRARY_PATH="${pkgs.arrayfire}/lib:$LD_LIBRARY_PATH" ''; }; pkgs-for = system: import inputs.nixpkgs { inherit system; overlays = [ - inputs.arrayfire-nix.overlays.default + arrayfire-overlay arrayfire-haskell-overlay ]; }; @@ -78,7 +109,6 @@ packages = inputs.flake-utils.lib.eachDefaultSystemMap (system: with (pkgs-for system); { default = haskellPackages.arrayfire; - haskell = haskell.packages; }); devShells = inputs.flake-utils.lib.eachDefaultSystemMap (system: {