biome: 1.9.2 -> 1.9.3
[NixPkgs.git] / pkgs / applications / misc / blender / default.nix
blob1a9ea4fd5ea40456034ea3bcc67163d7dae65245
2   Cocoa,
3   CoreGraphics,
4   ForceFeedback,
5   OpenAL,
6   OpenGL,
7   SDL,
8   addDriverRunpath,
9   alembic,
10   blender,
11   boost,
12   brotli,
13   callPackage,
14   cmake,
15   colladaSupport ? true,
16   config,
17   cudaPackages,
18   cudaSupport ? config.cudaSupport,
19   dbus,
20   embree,
21   fetchgit,
22   fetchpatch2,
23   fetchzip,
24   ffmpeg,
25   fftw,
26   fftwFloat,
27   freetype,
28   gettext,
29   glew,
30   gmp,
31   hipSupport ? false,
32   jackaudioSupport ? false,
33   jemalloc,
34   lib,
35   libGL,
36   libGLU,
37   libX11,
38   libXext,
39   libXi,
40   libXrender,
41   libXxf86vm,
42   libdecor,
43   libepoxy,
44   libffi,
45   libharu,
46   libjack2,
47   libjpeg,
48   libpng,
49   libsamplerate,
50   libsndfile,
51   libspnav,
52   libtiff,
53   libwebp,
54   libxkbcommon,
55   llvmPackages,
56   makeWrapper,
57   mesa,
58   openal,
59   opencollada,
60   opencolorio,
61   openexr,
62   openimagedenoise,
63   openimageio,
64   openjpeg,
65   openpgl,
66   opensubdiv,
67   openvdb,
68   openxr-loader,
69   pkg-config,
70   potrace,
71   pugixml,
72   python3Packages, # must use instead of python3.pkgs, see https://github.com/NixOS/nixpkgs/issues/211340
73   rocmPackages, # comes with a significantly larger closure size
74   runCommand,
75   spaceNavSupport ? stdenv.hostPlatform.isLinux,
76   sse2neon,
77   stdenv,
78   tbb,
79   wayland,
80   wayland-protocols,
81   wayland-scanner,
82   waylandSupport ? stdenv.hostPlatform.isLinux,
83   zlib,
84   zstd,
87 let
88   embreeSupport =
89     (!stdenv.hostPlatform.isAarch64 && stdenv.hostPlatform.isLinux) || stdenv.hostPlatform.isDarwin;
90   openImageDenoiseSupport =
91     (!stdenv.hostPlatform.isAarch64 && stdenv.hostPlatform.isLinux) || stdenv.hostPlatform.isDarwin;
92   openUsdSupport = !stdenv.hostPlatform.isDarwin;
94   python3 = python3Packages.python;
95   pyPkgsOpenusd = python3Packages.openusd.override { withOsl = false; };
97   libdecor' = libdecor.overrideAttrs (old: {
98     # Blender uses private APIs, need to patch to expose them
99     patches = (old.patches or [ ]) ++ [ ./libdecor.patch ];
100   });
102   optix = fetchzip {
103     # URL from https://gitlab.archlinux.org/archlinux/packaging/packages/blender/-/commit/333add667b43255dcb011215a2d2af48281e83cf#9b9baac1eb9b72790eef5540a1685306fc43fd6c_30_30
104     url = "https://developer.download.nvidia.com/redist/optix/v7.3/OptiX-7.3.0-Include.zip";
105     hash = "sha256-aMrp0Uff4c3ICRn4S6zedf6Q4Mc0/duBhKwKgYgMXVU=";
106   };
109 stdenv.mkDerivation (finalAttrs: {
110   pname = "blender";
111   version = "4.2.2";
113   srcs = [
114     (fetchzip {
115       name = "source";
116       url = "https://download.blender.org/source/blender-${finalAttrs.version}.tar.xz";
117       hash = "sha256-wv9EwB4DXSVS5K+lb+7gU3pTrMDO/ELeV2eErivfsWU=";
118     })
119     (fetchgit {
120       name = "assets";
121       url = "https://projects.blender.org/blender/blender-assets.git";
122       rev = "v${finalAttrs.version}";
123       fetchLFS = true;
124       hash = "sha256-vepK0inPMuleAJBSipwoI99nMBBiFaK/eSMHDetEtjY=";
125     })
126   ];
128   postUnpack = ''
129     chmod -R u+w *
130     rm -r assets/working
131     mv assets --target-directory source/release/datafiles/
132   '';
134   sourceRoot = "source";
136   patches = [
137     ./draco.patch
138     (fetchpatch2 {
139       url = "https://gitlab.archlinux.org/archlinux/packaging/packages/blender/-/raw/4b6214600e11851d7793256e2f6846a594e6f223/ffmpeg-7-1.patch";
140       hash = "sha256-YXXqP/+79y3f41n3cJ3A1RBzgdoYqfKZD/REqmWYdgQ=";
141     })
142     (fetchpatch2 {
143       url = "https://gitlab.archlinux.org/archlinux/packaging/packages/blender/-/raw/4b6214600e11851d7793256e2f6846a594e6f223/ffmpeg-7-2.patch";
144       hash = "sha256-mF6IA/dbHdNEkBN5XXCRcLIZ/8kXoirNwq7RDuLRAjw=";
145     })
146   ] ++ lib.optional stdenv.hostPlatform.isDarwin ./darwin.patch;
148   postPatch =
149     (lib.optionalString stdenv.hostPlatform.isDarwin ''
150       : > build_files/cmake/platform/platform_apple_xcode.cmake
151       substituteInPlace source/creator/CMakeLists.txt \
152         --replace-fail '${"$"}{LIBDIR}/python' \
153                   '${python3}' \
154         --replace-fail '${"$"}{LIBDIR}/materialx/' '${python3Packages.materialx}/'
155       substituteInPlace build_files/cmake/platform/platform_apple.cmake \
156         --replace-fail '${"$"}{LIBDIR}/brotli/lib/libbrotlicommon-static.a' \
157                   '${lib.getLib brotli}/lib/libbrotlicommon.dylib' \
158         --replace-fail '${"$"}{LIBDIR}/brotli/lib/libbrotlidec-static.a' \
159                   '${lib.getLib brotli}/lib/libbrotlidec.dylib'
160     '')
161     + (lib.optionalString hipSupport ''
162       substituteInPlace extern/hipew/src/hipew.c --replace '"/opt/rocm/hip/lib/libamdhip64.so"' '"${rocmPackages.clr}/lib/libamdhip64.so"'
163       substituteInPlace extern/hipew/src/hipew.c --replace '"opt/rocm/hip/bin"' '"${rocmPackages.clr}/bin"'
164     '');
166   env.NIX_CFLAGS_COMPILE = "-I${python3}/include/${python3.libPrefix}";
168   cmakeFlags =
169     [
170       "-DMaterialX_DIR=${python3Packages.materialx}/lib/cmake/MaterialX"
171       "-DPYTHON_INCLUDE_DIR=${python3}/include/${python3.libPrefix}"
172       "-DPYTHON_LIBPATH=${python3}/lib"
173       "-DPYTHON_LIBRARY=${python3.libPrefix}"
174       "-DPYTHON_NUMPY_INCLUDE_DIRS=${python3Packages.numpy}/${python3.sitePackages}/numpy/core/include"
175       "-DPYTHON_NUMPY_PATH=${python3Packages.numpy}/${python3.sitePackages}"
176       "-DPYTHON_VERSION=${python3.pythonVersion}"
177       "-DWITH_ALEMBIC=ON"
178       "-DWITH_BUILDINFO=OFF"
179       "-DWITH_CODEC_FFMPEG=ON"
180       "-DWITH_CODEC_SNDFILE=ON"
181       "-DWITH_CPU_CHECK=OFF"
182       "-DWITH_CYCLES_DEVICE_OPTIX=${if cudaSupport then "ON" else "OFF"}"
183       "-DWITH_CYCLES_EMBREE=${if embreeSupport then "ON" else "OFF"}"
184       "-DWITH_CYCLES_OSL=OFF"
185       "-DWITH_FFTW3=ON"
186       "-DWITH_HYDRA=${if openUsdSupport then "ON" else "OFF"}"
187       "-DWITH_IMAGE_OPENJPEG=ON"
188       "-DWITH_INSTALL_PORTABLE=OFF"
189       "-DWITH_JACK=${if jackaudioSupport then "ON" else "OFF"}"
190       "-DWITH_LIBS_PRECOMPILED=OFF"
191       "-DWITH_MOD_OCEANSIM=ON"
192       "-DWITH_OPENCOLLADA=${if colladaSupport then "ON" else "OFF"}"
193       "-DWITH_OPENCOLORIO=ON"
194       "-DWITH_OPENIMAGEDENOISE=${if openImageDenoiseSupport then "ON" else "OFF"}"
195       "-DWITH_OPENSUBDIV=ON"
196       "-DWITH_OPENVDB=ON"
197       "-DWITH_PULSEAUDIO=OFF"
198       "-DWITH_PYTHON_INSTALL=OFF"
199       "-DWITH_PYTHON_INSTALL_NUMPY=OFF"
200       "-DWITH_PYTHON_INSTALL_REQUESTS=OFF"
201       "-DWITH_SDL=OFF"
202       "-DWITH_STRICT_BUILD_OPTIONS=ON"
203       "-DWITH_TBB=ON"
204       "-DWITH_USD=${if openUsdSupport then "ON" else "OFF"}"
206       # Blender supplies its own FindAlembic.cmake (incompatible with the Alembic-supplied config file)
207       "-DALEMBIC_INCLUDE_DIR=${lib.getDev alembic}/include"
208       "-DALEMBIC_LIBRARY=${lib.getLib alembic}/lib/libAlembic${stdenv.hostPlatform.extensions.sharedLibrary}"
209     ]
210     ++ lib.optionals waylandSupport [
211       "-DWITH_GHOST_WAYLAND=ON"
212       "-DWITH_GHOST_WAYLAND_DBUS=ON"
213       "-DWITH_GHOST_WAYLAND_DYNLOAD=OFF"
214       "-DWITH_GHOST_WAYLAND_LIBDECOR=ON"
215     ]
216     ++ lib.optionals stdenv.hostPlatform.isDarwin [
217       "-DLIBDIR=/does-not-exist"
218       "-DSSE2NEON_INCLUDE_DIR=${sse2neon}/lib"
219     ]
220     ++ lib.optional stdenv.cc.isClang "-DPYTHON_LINKFLAGS=" # Clang doesn't support "-export-dynamic"
221     ++ lib.optionals cudaSupport [
222       "-DOPTIX_ROOT_DIR=${optix}"
223       "-DWITH_CYCLES_CUDA_BINARIES=ON"
224     ];
226   preConfigure = ''
227     (
228       expected_python_version=$(grep -E --only-matching 'set\(_PYTHON_VERSION_SUPPORTED [0-9.]+\)' build_files/cmake/Modules/FindPythonLibsUnix.cmake | grep -E --only-matching '[0-9.]+')
229       actual_python_version=$(python -c 'import sys; print(".".join(map(str, sys.version_info[0:2])))')
230       if ! [[ "$actual_python_version" = "$expected_python_version" ]]; then
231         echo "wrong Python version, expected '$expected_python_version', got '$actual_python_version'" >&2
232         exit 1
233       fi
234     )
235   '';
237   nativeBuildInputs =
238     [
239       cmake
240       llvmPackages.llvm.dev
241       makeWrapper
242       python3Packages.wrapPython
243     ]
244     ++ lib.optionals cudaSupport [
245       addDriverRunpath
246       cudaPackages.cuda_nvcc
247     ]
248     ++ lib.optionals waylandSupport [
249       pkg-config
250       wayland-scanner
251     ];
253   buildInputs =
254     [
255       alembic
256       boost
257       ffmpeg
258       fftw
259       fftwFloat
260       freetype
261       gettext
262       glew
263       gmp
264       jemalloc
265       libepoxy
266       libharu
267       libjpeg
268       libpng
269       libsamplerate
270       libsndfile
271       libtiff
272       libwebp
273       opencolorio
274       openexr
275       openimageio
276       openjpeg
277       openpgl
278       (opensubdiv.override { inherit cudaSupport; })
279       openvdb
280       potrace
281       pugixml
282       python3
283       python3Packages.materialx
284       tbb
285       zlib
286       zstd
287     ]
288     ++ lib.optional embreeSupport embree
289     ++ lib.optional openImageDenoiseSupport (openimagedenoise.override { inherit cudaSupport; })
290     ++ (
291       if (!stdenv.hostPlatform.isDarwin) then
292         [
293           libGL
294           libGLU
295           libX11
296           libXext
297           libXi
298           libXrender
299           libXxf86vm
300           openal
301           openxr-loader
302         ]
303       else
304         [
305           Cocoa
306           CoreGraphics
307           ForceFeedback
308           OpenAL
309           OpenGL
310           SDL
311           brotli
312           llvmPackages.openmp
313           sse2neon
314         ]
315     )
316     ++ lib.optionals cudaSupport [ cudaPackages.cuda_cudart ]
317     ++ lib.optionals openUsdSupport [ pyPkgsOpenusd ]
318     ++ lib.optionals waylandSupport [
319       dbus
320       libdecor'
321       libffi
322       libxkbcommon
323       wayland
324       wayland-protocols
325     ]
326     ++ lib.optional colladaSupport opencollada
327     ++ lib.optional jackaudioSupport libjack2
328     ++ lib.optional spaceNavSupport libspnav;
330   pythonPath =
331     let
332       ps = python3Packages;
333     in
334     [
335       ps.materialx
336       ps.numpy
337       ps.requests
338       ps.zstandard
339     ]
340     ++ lib.optional openUsdSupport [ pyPkgsOpenusd ];
342   blenderExecutable =
343     placeholder "out"
344     + (
345       if stdenv.hostPlatform.isDarwin then
346         "/Applications/Blender.app/Contents/MacOS/Blender"
347       else
348         "/bin/blender"
349     );
351   postInstall =
352     lib.optionalString stdenv.hostPlatform.isDarwin ''
353       mkdir $out/Applications
354       mv $out/Blender.app $out/Applications
355     ''
356     + lib.optionalString stdenv.hostPlatform.isLinux ''
357       mv $out/share/blender/${lib.versions.majorMinor finalAttrs.version}/python{,-ext}
358     ''
359     + ''
360       buildPythonPath "$pythonPath"
361       wrapProgram $blenderExecutable \
362         --prefix PATH : $program_PATH \
363         --prefix PYTHONPATH : "$program_PYTHONPATH" \
364         --add-flags '--python-use-system-env'
365     '';
367   # Set RUNPATH so that libcuda and libnvrtc in /run/opengl-driver(-32)/lib can be
368   # found. See the explanation in libglvnd.
369   postFixup =
370     lib.optionalString cudaSupport ''
371       for program in $out/bin/blender $out/bin/.blender-wrapped; do
372         isELF "$program" || continue
373         addDriverRunpath "$program"
374       done
375     ''
376     + lib.optionalString stdenv.hostPlatform.isDarwin ''
377       makeWrapper $out/Applications/Blender.app/Contents/MacOS/Blender $out/bin/blender
378     '';
380   passthru = {
381     python = python3;
382     pythonPackages = python3Packages;
384     withPackages =
385       f:
386       (callPackage ./wrapper.nix { }).override {
387         blender = finalAttrs.finalPackage;
388         extraModules = (f python3Packages);
389       };
391     tests = {
392       render = runCommand "${finalAttrs.pname}-test" { nativeBuildInputs = [ mesa.llvmpipeHook ]; } ''
393         set -euo pipefail
394         cat <<'PYTHON' > scene-config.py
395         import bpy
396         bpy.context.scene.eevee.taa_render_samples = 32
397         bpy.context.scene.cycles.samples = 32
398         if ${if (stdenv.hostPlatform.isAarch64 && stdenv.hostPlatform.isLinux) then "True" else "False"}:
399             bpy.context.scene.cycles.use_denoising = False
400         bpy.context.scene.render.resolution_x = 100
401         bpy.context.scene.render.resolution_y = 100
402         bpy.context.scene.render.threads_mode = 'FIXED'
403         bpy.context.scene.render.threads = 1
404         PYTHON
406         mkdir $out
407         for engine in BLENDER_EEVEE_NEXT CYCLES; do
408           echo "Rendering with $engine..."
409           # Beware that argument order matters
410           ${lib.getExe finalAttrs.finalPackage} \
411             --background \
412             -noaudio \
413             --factory-startup \
414             --python-exit-code 1 \
415             --python scene-config.py \
416             --engine "$engine" \
417             --render-output "$out/$engine" \
418             --render-frame 1
419         done
420       '';
421       tester-cudaAvailable = cudaPackages.writeGpuTestPython { } ''
422         import subprocess
423         subprocess.run([${
424           lib.concatMapStringsSep ", " (x: ''"${x}"'') [
425             (lib.getExe (blender.override { cudaSupport = true; }))
426             "--background"
427             "-noaudio"
428             "--python-exit-code"
429             "1"
430             "--python"
431             "${./test-cuda.py}"
432           ]
433         }], check=True)  # noqa: E501
434       '';
435     };
436   };
438   meta = {
439     description = "3D Creation/Animation/Publishing System";
440     homepage = "https://www.blender.org";
441     # They comment two licenses: GPLv2 and Blender License, but they
442     # say: "We've decided to cancel the BL offering for an indefinite period."
443     # OptiX, enabled with cudaSupport, is non-free.
444     license =
445       with lib.licenses;
446       [ gpl2Plus ] ++ lib.optional cudaSupport (unfree // { shortName = "NVidia OptiX EULA"; });
448     platforms = [
449       "aarch64-linux"
450       "x86_64-darwin"
451       "x86_64-linux"
452       "aarch64-darwin"
453     ];
454     broken = stdenv.hostPlatform.isDarwin; # fails due to too-old SDK, using newer SDK fails to compile
455     maintainers = with lib.maintainers; [
456       amarshall
457       veprbl
458     ];
459     mainProgram = "blender";
460   };