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