lol
1{ lib, stdenv
2, fetchFromGitHub
3, fetchpatch
4, callPackage
5, cmake, pkg-config, unzip, zlib, pcre, hdf5
6, glog, boost, gflags, protobuf_21
7, config
8
9, enableJPEG ? true, libjpeg
10, enablePNG ? true, libpng
11, enableTIFF ? true, libtiff
12, enableWebP ? true, libwebp
13, enableEXR ? !stdenv.isDarwin, openexr, ilmbase
14, enableEigen ? true, eigen
15, enableOpenblas ? true, openblas, blas, lapack
16, enableContrib ? true
17
18, enableCuda ? config.cudaSupport
19, cudaPackages ? { }
20, enableUnfree ? false
21, enableIpp ? false
22, enablePython ? false, pythonPackages ? null
23, enableGtk2 ? false, gtk2
24, enableGtk3 ? false, gtk3
25, enableFfmpeg ? false, ffmpeg
26, enableGStreamer ? false, gst_all_1
27, enableTesseract ? false, tesseract, leptonica
28, enableTbb ? false, tbb
29, enableOvis ? false, ogre
30, enableGPhoto2 ? false, libgphoto2
31, enableDC1394 ? false, libdc1394
32, enableDocs ? false, doxygen, graphviz-nox
33
34, AVFoundation, Cocoa, VideoDecodeAcceleration, bzip2, CoreMedia, MediaToolbox, Accelerate
35}:
36
37assert blas.implementation == "openblas" && lapack.implementation == "openblas";
38
39assert enablePython -> pythonPackages != null;
40
41let
42 inherit (cudaPackages) cudatoolkit;
43 inherit (cudaPackages.cudaFlags) cudaCapabilities;
44
45 version = "3.4.18";
46
47 src = fetchFromGitHub {
48 owner = "opencv";
49 repo = "opencv";
50 rev = version;
51 hash = "sha256-PgwAZNoPknFT0jCLt3TCzend6OYFY3iUIzDf/FptAYA=";
52 };
53
54 contribSrc = fetchFromGitHub {
55 owner = "opencv";
56 repo = "opencv_contrib";
57 rev = version;
58 hash = "sha256-TEF/GHglOmsshlC6q4iw14ZMpvA0SaKwlidomAN+sRc=";
59 };
60
61 # Contrib must be built in order to enable Tesseract support:
62 buildContrib = enableContrib || enableTesseract;
63
64 useSystemProtobuf = ! stdenv.isDarwin;
65
66 # See opencv/3rdparty/ippicv/ippicv.cmake
67 ippicv = {
68 src = fetchFromGitHub {
69 owner = "opencv";
70 repo = "opencv_3rdparty";
71 rev = "32e315a5b106a7b89dbed51c28f8120a48b368b4";
72 sha256 = "19w9f0r16072s59diqxsr5q6nmwyz9gnxjs49nglzhd66p3ddbkp";
73 } + "/ippicv";
74 files = let name = platform : "ippicv_2019_${platform}_general_20180723.tgz"; in
75 if stdenv.hostPlatform.system == "x86_64-linux" then
76 { ${name "lnx_intel64"} = "c0bd78adb4156bbf552c1dfe90599607"; }
77 else if stdenv.hostPlatform.system == "i686-linux" then
78 { ${name "lnx_ia32"} = "4f38432c30bfd6423164b7a24bbc98a0"; }
79 else if stdenv.hostPlatform.system == "x86_64-darwin" then
80 { ${name "mac_intel64"} = "fe6b2bb75ae0e3f19ad3ae1a31dfa4a2"; }
81 else
82 throw "ICV is not available for this platform (or not yet supported by this package)";
83 dst = ".cache/ippicv";
84 };
85
86 # See opencv_contrib/modules/xfeatures2d/cmake/download_vgg.cmake
87 vgg = {
88 src = fetchFromGitHub {
89 owner = "opencv";
90 repo = "opencv_3rdparty";
91 rev = "fccf7cd6a4b12079f73bbfb21745f9babcd4eb1d";
92 sha256 = "0r9fam8dplyqqsd3qgpnnfgf9l7lj44di19rxwbm8mxiw0rlcdvy";
93 };
94 files = {
95 "vgg_generated_48.i" = "e8d0dcd54d1bcfdc29203d011a797179";
96 "vgg_generated_64.i" = "7126a5d9a8884ebca5aea5d63d677225";
97 "vgg_generated_80.i" = "7cd47228edec52b6d82f46511af325c5";
98 "vgg_generated_120.i" = "151805e03568c9f490a5e3a872777b75";
99 };
100 dst = ".cache/xfeatures2d/vgg";
101 };
102
103 # See opencv_contrib/modules/xfeatures2d/cmake/download_boostdesc.cmake
104 boostdesc = {
105 src = fetchFromGitHub {
106 owner = "opencv";
107 repo = "opencv_3rdparty";
108 rev = "34e4206aef44d50e6bbcd0ab06354b52e7466d26";
109 sha256 = "13yig1xhvgghvxspxmdidss5lqiikpjr0ddm83jsi0k85j92sn62";
110 };
111 files = {
112 "boostdesc_bgm.i" = "0ea90e7a8f3f7876d450e4149c97c74f";
113 "boostdesc_bgm_bi.i" = "232c966b13651bd0e46a1497b0852191";
114 "boostdesc_bgm_hd.i" = "324426a24fa56ad9c5b8e3e0b3e5303e";
115 "boostdesc_binboost_064.i" = "202e1b3e9fec871b04da31f7f016679f";
116 "boostdesc_binboost_128.i" = "98ea99d399965c03d555cef3ea502a0b";
117 "boostdesc_binboost_256.i" = "e6dcfa9f647779eb1ce446a8d759b6ea";
118 "boostdesc_lbgm.i" = "0ae0675534aa318d9668f2a179c2a052";
119 };
120 dst = ".cache/xfeatures2d/boostdesc";
121 };
122
123 # See opencv_contrib/modules/face/CMakeLists.txt
124 face = {
125 src = fetchFromGitHub {
126 owner = "opencv";
127 repo = "opencv_3rdparty";
128 rev = "8afa57abc8229d611c4937165d20e2a2d9fc5a12";
129 sha256 = "061lsvqdidq9xa2hwrcvwi9ixflr2c2lfpc8drr159g68zi8bp4v";
130 };
131 files = {
132 "face_landmark_model.dat" = "7505c44ca4eb54b4ab1e4777cb96ac05";
133 };
134 dst = ".cache/data";
135 };
136
137 # See opencv/cmake/OpenCVDownload.cmake
138 installExtraFiles = extra : with lib; ''
139 mkdir -p "${extra.dst}"
140 '' + concatStrings (mapAttrsToList (name : md5 : ''
141 ln -s "${extra.src}/${name}" "${extra.dst}/${md5}-${name}"
142 '') extra.files);
143
144 opencvFlag = name: enabled: "-DWITH_${name}=${printEnabled enabled}";
145
146 printEnabled = enabled : if enabled then "ON" else "OFF";
147in
148
149stdenv.mkDerivation {
150 pname = "opencv";
151 inherit version src;
152
153 postUnpack = lib.optionalString buildContrib ''
154 cp --no-preserve=mode -r "${contribSrc}/modules" "$NIX_BUILD_TOP/opencv_contrib"
155 '';
156
157 # Ensures that we use the system OpenEXR rather than the vendored copy of the source included with OpenCV.
158 patches = [
159 ./cmake-don-t-use-OpenCVFindOpenEXR.patch
160 ];
161
162 # This prevents cmake from using libraries in impure paths (which
163 # causes build failure on non NixOS)
164 # Also, work around https://github.com/NixOS/nixpkgs/issues/26304 with
165 # what appears to be some stray headers in dnn/misc/tensorflow
166 # in contrib when generating the Python bindings:
167 postPatch = ''
168 sed -i '/Add these standard paths to the search paths for FIND_LIBRARY/,/^\s*$/{d}' CMakeLists.txt
169 sed -i -e 's|if len(decls) == 0:|if len(decls) == 0 or "opencv2/" not in hdr:|' ./modules/python/src2/gen2.py
170 '';
171
172 preConfigure =
173 lib.optionalString enableIpp (installExtraFiles ippicv) + (
174 lib.optionalString buildContrib ''
175 cmakeFlagsArray+=("-DOPENCV_EXTRA_MODULES_PATH=$NIX_BUILD_TOP/opencv_contrib")
176
177 ${installExtraFiles vgg}
178 ${installExtraFiles boostdesc}
179 ${installExtraFiles face}
180 '');
181
182 postConfigure = ''
183 [ -e modules/core/version_string.inc ]
184 echo '"(build info elided)"' > modules/core/version_string.inc
185 '';
186
187 buildInputs =
188 [ zlib pcre hdf5 glog boost gflags ]
189 ++ lib.optional useSystemProtobuf protobuf_21
190 ++ lib.optional enablePython pythonPackages.python
191 ++ lib.optional enableGtk2 gtk2
192 ++ lib.optional enableGtk3 gtk3
193 ++ lib.optional enableJPEG libjpeg
194 ++ lib.optional enablePNG libpng
195 ++ lib.optional enableTIFF libtiff
196 ++ lib.optional enableWebP libwebp
197 ++ lib.optionals enableEXR [ openexr ilmbase ]
198 ++ lib.optional enableFfmpeg ffmpeg
199 ++ lib.optionals (enableFfmpeg && stdenv.isDarwin)
200 [ VideoDecodeAcceleration bzip2 ]
201 ++ lib.optionals enableGStreamer (with gst_all_1; [ gstreamer gst-plugins-base ])
202 ++ lib.optional enableOvis ogre
203 ++ lib.optional enableGPhoto2 libgphoto2
204 ++ lib.optional enableDC1394 libdc1394
205 ++ lib.optional enableEigen eigen
206 ++ lib.optional enableOpenblas openblas
207 # There is seemingly no compile-time flag for Tesseract. It's
208 # simply enabled automatically if contrib is built, and it detects
209 # tesseract & leptonica.
210 ++ lib.optionals enableTesseract [ tesseract leptonica ]
211 ++ lib.optional enableTbb tbb
212 ++ lib.optionals stdenv.isDarwin [
213 bzip2 AVFoundation Cocoa VideoDecodeAcceleration CoreMedia MediaToolbox Accelerate
214 ]
215 ++ lib.optionals enableDocs [ doxygen graphviz-nox ];
216
217 propagatedBuildInputs = lib.optional enablePython pythonPackages.numpy
218 ++ lib.optional enableCuda cudatoolkit;
219
220 nativeBuildInputs = [ cmake pkg-config unzip ];
221
222 env.NIX_CFLAGS_COMPILE = lib.optionalString enableEXR "-I${ilmbase.dev}/include/OpenEXR";
223
224 # Configure can't find the library without this.
225 OpenBLAS_HOME = lib.optionalString enableOpenblas openblas;
226
227 cmakeFlags = [
228 "-DWITH_OPENMP=ON"
229 "-DBUILD_PROTOBUF=${printEnabled (!useSystemProtobuf)}"
230 "-DPROTOBUF_UPDATE_FILES=${printEnabled useSystemProtobuf}"
231 "-DOPENCV_ENABLE_NONFREE=${printEnabled enableUnfree}"
232 "-DBUILD_TESTS=OFF"
233 "-DBUILD_PERF_TESTS=OFF"
234 "-DBUILD_DOCS=${printEnabled enableDocs}"
235 (opencvFlag "IPP" enableIpp)
236 (opencvFlag "TIFF" enableTIFF)
237 (opencvFlag "WEBP" enableWebP)
238 (opencvFlag "JPEG" enableJPEG)
239 (opencvFlag "PNG" enablePNG)
240 (opencvFlag "OPENEXR" enableEXR)
241 (opencvFlag "CUDA" enableCuda)
242 (opencvFlag "CUBLAS" enableCuda)
243 (opencvFlag "TBB" enableTbb)
244 ] ++ lib.optionals enableCuda [
245 "-DCUDA_FAST_MATH=ON"
246 "-DCUDA_HOST_COMPILER=${cudatoolkit.cc}/bin/cc"
247 "-DCUDA_NVCC_FLAGS=--expt-relaxed-constexpr"
248 "-DCUDA_ARCH_BIN=${lib.concatStringsSep ";" cudaCapabilities}"
249 "-DCUDA_ARCH_PTX=${lib.last cudaCapabilities}"
250 ] ++ lib.optionals stdenv.isDarwin [
251 "-DWITH_OPENCL=OFF"
252 "-DWITH_LAPACK=OFF"
253
254 # Disable unnecessary vendoring that's enabled by default only for Darwin.
255 # Note that the opencvFlag feature flags listed above still take
256 # precedence, so we can safely list everything here.
257 "-DBUILD_ZLIB=OFF"
258 "-DBUILD_TIFF=OFF"
259 "-DBUILD_JASPER=OFF"
260 "-DBUILD_JPEG=OFF"
261 "-DBUILD_PNG=OFF"
262 "-DBUILD_WEBP=OFF"
263 ] ++ lib.optionals enablePython [
264 "-DOPENCV_SKIP_PYTHON_LOADER=ON"
265 ] ++ lib.optionals enableEigen [
266 # Autodetection broken by https://github.com/opencv/opencv/pull/13337
267 "-DEIGEN_INCLUDE_PATH=${eigen}/include/eigen3"
268 ];
269
270 postBuild = lib.optionalString enableDocs ''
271 make doxygen
272 '';
273
274 # By default $out/lib/pkgconfig/opencv.pc looks something like this:
275 #
276 # prefix=/nix/store/10pzq1a8fkh8q4sysj8n6mv0w0nl0miq-opencv-3.4.1
277 # exec_prefix=${prefix}
278 # libdir=${exec_prefix}//nix/store/10pzq1a8fkh8q4sysj8n6mv0w0nl0miq-opencv-3.4.1/lib
279 # ...
280 # Libs: -L${exec_prefix}//nix/store/10pzq1a8fkh8q4sysj8n6mv0w0nl0miq-opencv-3.4.1/lib ...
281 #
282 # Note that ${exec_prefix} is set to $out but that $out is also appended to
283 # ${exec_prefix}. This causes linker errors in downstream packages so we strip
284 # of $out after the ${exec_prefix} prefix:
285 postInstall = ''
286 sed -i "s|{exec_prefix}/$out|{exec_prefix}|" \
287 "$out/lib/pkgconfig/opencv.pc"
288 '';
289
290 hardeningDisable = [ "bindnow" "relro" ];
291
292 passthru = lib.optionalAttrs enablePython { pythonPath = []; } // {
293 tests = lib.optionalAttrs enableCuda {
294 no-libstdcxx-errors = callPackage ./libstdcxx-test.nix { attrName = "opencv3"; };
295 };
296 };
297
298 meta = with lib; {
299 description = "Open Computer Vision Library with more than 500 algorithms";
300 homepage = "https://opencv.org/";
301 license = with licenses; if enableUnfree then unfree else bsd3;
302 maintainers = with maintainers; [mdaiter basvandijk];
303 platforms = with platforms; linux ++ darwin;
304 };
305}