1{ blas
2, boost
3, clblast
4, cmake
5, config
6, cudaPackages
7, fetchFromGitHub
8, fftw
9, fftwFloat
10, fmt_9
11, forge
12, freeimage
13, gtest
14, lapack
15, lib
16, libGL
17, mesa
18, ocl-icd
19, opencl-clhpp
20, pkg-config
21, python3
22, span-lite
23, stdenv
24 # NOTE: We disable tests by default, because they cannot be run easily on
25 # non-NixOS systems when either CUDA or OpenCL support is enabled (CUDA and
26 # OpenCL need access to drivers that are installed outside of Nix on
27 # non-NixOS systems).
28, doCheck ? false
29, cpuSupport ? true
30, cudaSupport ? config.cudaSupport
31 # OpenCL needs mesa which is broken on Darwin
32, openclSupport ? !stdenv.isDarwin
33 # This argument lets one run CUDA & OpenCL tests on non-NixOS systems by
34 # telling Nix where to find the drivers. If you know the version of the
35 # NVidia driver that is installed on your system, you can do:
36 #
37 # arrayfire.override {
38 # nvidiaComputeDrivers =
39 # callPackage
40 # (prev.linuxPackages.nvidiaPackages.mkDriver {
41 # version = cudaVersion; # our driver version
42 # sha256_64bit = cudaHash; # sha256 of the .run binary
43 # useGLVND = false;
44 # useProfiles = false;
45 # useSettings = false;
46 # usePersistenced = false;
47 # ...
48 # })
49 # { libsOnly = true; };
50 # }
51, nvidiaComputeDrivers ? null
52}:
53
54# ArrayFire compiles with 64-bit BLAS, but some tests segfault or throw
55# exceptions, which means that it isn't really supported yet...
56assert blas.isILP64 == false;
57
58stdenv.mkDerivation rec {
59 pname = "arrayfire";
60 version = "3.9.0";
61
62 src = fetchFromGitHub {
63 owner = pname;
64 repo = pname;
65 rev = "v3.9.0";
66 hash = "sha256-80fxdkaeAQ5u0X/UGPaI/900cdkZ/vXNcOn5tkZ+C3Y=";
67 };
68
69 # We cannot use the clfft from Nixpkgs because ArrayFire maintain a fork
70 # of clfft where they've modified the CMake build system, and the
71 # CMakeLists.txt of ArrayFire assumes that we're using that fork.
72 #
73 # This can be removed once ArrayFire upstream their changes.
74 clfft = fetchFromGitHub {
75 owner = pname;
76 repo = "clfft";
77 rev = "760096b37dcc4f18ccd1aac53f3501a83b83449c";
78 sha256 = "sha256-vJo1YfC2AJIbbRj/zTfcOUmi0Oj9v64NfA9MfK8ecoY=";
79 };
80 glad = fetchFromGitHub {
81 owner = pname;
82 repo = "glad";
83 rev = "ef8c5508e72456b714820c98e034d9a55b970650";
84 sha256 = "sha256-u9Vec7XLhE3xW9vzM7uuf+b18wZsh/VMtGbB6nMVlno=";
85 };
86 threads = fetchFromGitHub {
87 owner = pname;
88 repo = "threads";
89 rev = "4d4a4f0384d1ac2f25b2c4fc1d57b9e25f4d6818";
90 sha256 = "sha256-qqsT9woJDtQvzuV323OYXm68pExygYs/+zZNmg2sN34=";
91 };
92 test-data = fetchFromGitHub {
93 owner = pname;
94 repo = "arrayfire-data";
95 rev = "a5f533d7b864a4d8f0dd7c9aaad5ff06018c4867";
96 sha256 = "sha256-AWzhsrDXyZrQN2bd0Ng/XlE8v02x7QWTiFTyaAuRXSw=";
97 };
98 # ArrayFire fails to compile with newer versions of spdlog, so we can't use
99 # the one in Nixpkgs. Once they upgrade, we can switch to using spdlog from
100 # Nixpkgs.
101 spdlog = fetchFromGitHub {
102 owner = "gabime";
103 repo = "spdlog";
104 rev = "v1.9.2";
105 hash = "sha256-GSUdHtvV/97RyDKy8i+ticnSlQCubGGWHg4Oo+YAr8Y=";
106 };
107
108 cmakeFlags = [
109 "-DBUILD_TESTING=ON"
110 # We do not build examples, because building tests already takes long enough...
111 "-DAF_BUILD_EXAMPLES=OFF"
112 # No need to build forge, because it's a separate package
113 "-DAF_BUILD_FORGE=OFF"
114 "-DAF_COMPUTE_LIBRARY='FFTW/LAPACK/BLAS'"
115 # Prevent ArrayFire from trying to download some matrices from the Internet
116 "-DAF_TEST_WITH_MTX_FILES=OFF"
117 # Have to use the header-only version, because we're not using the version
118 # from Nixpkgs. Otherwise, libaf.so won't be able to find the shared
119 # library, because ArrayFire's CMake files do not run the install step of
120 # spdlog.
121 "-DAF_WITH_SPDLOG_HEADER_ONLY=ON"
122 (if cpuSupport then "-DAF_BUILD_CPU=ON" else "-DAF_BUILD_CPU=OFF")
123 (if openclSupport then "-DAF_BUILD_OPENCL=ON" else "-DAF_BUILD_OPENCL=OFF")
124 (if cudaSupport then "-DAF_BUILD_CUDA=ON" else "-DAF_BUILD_CUDA=OFF")
125 ] ++ lib.optionals cudaSupport [
126 # ArrayFire use deprecated FindCUDA in their CMake files, so we help CMake
127 # locate cudatoolkit.
128 "-DCUDA_LIBRARIES_PATH=${cudaPackages.cudatoolkit}/lib"
129 ];
130
131 # ArrayFire have a repo with assets for the examples. Since we don't build
132 # the examples anyway, remove the dependency on assets.
133 patches = [ ./no-assets.patch ./no-download.patch ];
134
135 postPatch = ''
136 mkdir -p ./extern/af_glad-src
137 mkdir -p ./extern/af_threads-src
138 mkdir -p ./extern/af_test_data-src
139 mkdir -p ./extern/ocl_clfft-src
140 mkdir -p ./extern/spdlog-src
141 cp -R --no-preserve=mode,ownership ${glad}/* ./extern/af_glad-src/
142 cp -R --no-preserve=mode,ownership ${threads}/* ./extern/af_threads-src/
143 cp -R --no-preserve=mode,ownership ${test-data}/* ./extern/af_test_data-src/
144 cp -R --no-preserve=mode,ownership ${clfft}/* ./extern/ocl_clfft-src/
145 cp -R --no-preserve=mode,ownership ${spdlog}/* ./extern/spdlog-src/
146
147 # libaf.so (the unified backend) tries to load the right shared library at
148 # runtime, and the search paths are hard-coded... We tweak them to point to
149 # the installation directory in the Nix store.
150 substituteInPlace src/api/unified/symbol_manager.cpp \
151 --replace '"/opt/arrayfire-3/lib/",' \
152 "\"$out/lib/\", \"/opt/arrayfire-3/lib/\","
153 '';
154
155 inherit doCheck;
156 checkPhase =
157 let
158 LD_LIBRARY_PATH = builtins.concatStringsSep ":" (
159 [ "${forge}/lib" "${freeimage}/lib" ]
160 ++ lib.optional cudaSupport "${cudaPackages.cudatoolkit}/lib64"
161 # On non-NixOS systems, help the tests find Nvidia drivers
162 ++ lib.optional (nvidiaComputeDrivers != null) "${nvidiaComputeDrivers}/lib"
163 );
164 ctestFlags = builtins.concatStringsSep " " (
165 # We have to run with "-j1" otherwise various segfaults occur on non-NixOS systems.
166 [ "--output-on-errors" "-j1" ]
167 # See https://github.com/arrayfire/arrayfire/issues/3484
168 ++ lib.optional openclSupport "-E '(inverse_dense|cholesky_dense)'"
169 );
170 in
171 ''
172 export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}
173 '' +
174 # On non-NixOS systems, help the tests find Nvidia drivers
175 lib.optionalString (openclSupport && nvidiaComputeDrivers != null) ''
176 export OCL_ICD_VENDORS=${nvidiaComputeDrivers}/etc/OpenCL/vendors
177 '' + ''
178 # Note: for debugging, enable AF_TRACE=all
179 AF_PRINT_ERRORS=1 ctest ${ctestFlags}
180 '';
181
182 buildInputs = [
183 blas
184 boost.dev
185 boost.out
186 clblast
187 fftw
188 fftwFloat
189 # We need fmt_9 because ArrayFire fails to compile with newer versions.
190 fmt_9
191 forge
192 freeimage
193 gtest
194 lapack
195 libGL
196 ocl-icd
197 opencl-clhpp
198 span-lite
199 ]
200 ++ lib.optionals cudaSupport [
201 cudaPackages.cudatoolkit
202 cudaPackages.cudnn
203 cudaPackages.cuda_cccl
204 ]
205 ++ lib.optionals openclSupport [
206 mesa
207 ];
208
209 nativeBuildInputs = [
210 cmake
211 pkg-config
212 python3
213 ];
214
215 meta = with lib; {
216 description = "A general-purpose library for parallel and massively-parallel computations";
217 longDescription = ''
218 A general-purpose library that simplifies the process of developing software that targets parallel and massively-parallel architectures including CPUs, GPUs, and other hardware acceleration devices.";
219 '';
220 license = licenses.bsd3;
221 homepage = "https://arrayfire.com/";
222 platforms = platforms.linux;
223 maintainers = with maintainers; [ chessai twesterhout ];
224 };
225}