1{
2 stdenv,
3 lib,
4 src,
5 patches,
6 version,
7 qtCompatVersion,
8
9 coreutils,
10 bison,
11 flex,
12 gdb,
13 gperf,
14 lndir,
15 perl,
16 pkg-config,
17 python3,
18 which,
19 # darwin support
20 apple-sdk_14,
21 xcbuild,
22
23 dbus,
24 fontconfig,
25 freetype,
26 glib,
27 harfbuzz,
28 icu,
29 libdrm,
30 libX11,
31 libXcomposite,
32 libXcursor,
33 libXext,
34 libXi,
35 libXrender,
36 libjpeg,
37 libpng,
38 libxcb,
39 libxkbcommon,
40 libxml2,
41 libxslt,
42 openssl,
43 pcre2,
44 sqlite,
45 udev,
46 xcbutil,
47 xcbutilimage,
48 xcbutilkeysyms,
49 xcbutilrenderutil,
50 xcbutilwm,
51 zlib,
52 at-spi2-core,
53
54 # optional dependencies
55 cups ? null,
56 libpq ? null,
57 withGtk3 ? false,
58 dconf,
59 gtk3,
60 withQttranslation ? true,
61 qttranslations ? null,
62 withLibinput ? false,
63 libinput,
64
65 # options
66 libGLSupported ? !stdenv.hostPlatform.isDarwin,
67 libGL,
68 # qmake detection for libmysqlclient does not seem to work when cross compiling
69 mysqlSupport ? stdenv.hostPlatform == stdenv.buildPlatform,
70 libmysqlclient,
71 buildExamples ? false,
72 buildTests ? false,
73 debug ? false,
74 developerBuild ? false,
75 decryptSslTraffic ? false,
76 testers,
77 buildPackages,
78}:
79
80let
81 debugSymbols = debug || developerBuild;
82 qtPlatformCross =
83 plat:
84 with plat;
85 if isLinux then
86 "linux-generic-g++"
87 else
88 throw "Please add a qtPlatformCross entry for ${plat.config}";
89
90 # Per https://doc.qt.io/qt-5/macos.html#supported-versions: build SDK = 13.x or 14.x.
91 darwinVersionInputs = [
92 apple-sdk_14
93 ];
94in
95
96stdenv.mkDerivation (
97 finalAttrs:
98 (
99 {
100 pname = "qtbase";
101 inherit qtCompatVersion src version;
102 debug = debugSymbols;
103
104 propagatedBuildInputs = [
105 libxml2
106 libxslt
107 openssl
108 sqlite
109 zlib
110
111 # Text rendering
112 freetype
113 harfbuzz
114 icu
115
116 # Image formats
117 libjpeg
118 libpng
119 pcre2
120 ]
121 ++ lib.optionals (!stdenv.hostPlatform.isDarwin) (
122 [
123 dbus
124 glib
125 udev
126
127 # Text rendering
128 fontconfig
129
130 libdrm
131
132 # X11 libs
133 libX11
134 libXcomposite
135 libXext
136 libXi
137 libXrender
138 libxcb
139 libxkbcommon
140 xcbutil
141 xcbutilimage
142 xcbutilkeysyms
143 xcbutilrenderutil
144 xcbutilwm
145 ]
146 ++ lib.optional libGLSupported libGL
147 );
148
149 buildInputs = [
150 python3
151 at-spi2-core
152 ]
153 ++ lib.optionals (!stdenv.hostPlatform.isDarwin) (
154 lib.optional withLibinput libinput ++ lib.optional withGtk3 gtk3
155 )
156 ++ lib.optional stdenv.hostPlatform.isDarwin darwinVersionInputs
157 ++ lib.optional developerBuild gdb
158 ++ lib.optional (cups != null) cups
159 ++ lib.optional (mysqlSupport) libmysqlclient
160 ++ lib.optional (libpq != null) libpq;
161
162 nativeBuildInputs = [
163 bison
164 flex
165 gperf
166 lndir
167 perl
168 pkg-config
169 which
170 ]
171 ++ lib.optionals (mysqlSupport) [ libmysqlclient ]
172 ++ lib.optionals stdenv.hostPlatform.isDarwin [ xcbuild ];
173
174 }
175 // lib.optionalAttrs (stdenv.buildPlatform != stdenv.hostPlatform) {
176 # `qtbase` expects to find `cc` (with no prefix) in the
177 # `$PATH`, so the following is needed even if
178 # `stdenv.buildPlatform.canExecute stdenv.hostPlatform`
179 depsBuildBuild = [ buildPackages.stdenv.cc ];
180 }
181 // {
182
183 propagatedNativeBuildInputs = [ lndir ];
184
185 strictDeps = true;
186
187 # libQt5Core links calls CoreFoundation APIs that call into the system ICU. Binaries linked
188 # against it will crash during build unless they can access `/usr/share/icu/icudtXXl.dat`.
189 propagatedSandboxProfile = lib.optionalString stdenv.hostPlatform.isDarwin ''
190 (allow file-read* (subpath "/usr/share/icu"))
191 '';
192
193 enableParallelBuilding = true;
194
195 outputs = [
196 "bin"
197 "dev"
198 "out"
199 ];
200
201 inherit patches;
202
203 fix_qt_builtin_paths = ../hooks/fix-qt-builtin-paths.sh;
204 fix_qt_module_paths = ../hooks/fix-qt-module-paths.sh;
205 preHook = ''
206 . "$fix_qt_builtin_paths"
207 . "$fix_qt_module_paths"
208 . ${../hooks/move-qt-dev-tools.sh}
209 . ${../hooks/fix-qmake-libtool.sh}
210 '';
211
212 postPatch = ''
213 for prf in qml_plugin.prf qt_plugin.prf qt_docs.prf qml_module.prf create_cmake.prf; do
214 substituteInPlace "mkspecs/features/$prf" \
215 --subst-var qtPluginPrefix \
216 --subst-var qtQmlPrefix \
217 --subst-var qtDocPrefix
218 done
219
220 substituteInPlace configure --replace /bin/pwd pwd
221 substituteInPlace src/corelib/global/global.pri --replace /bin/ls ${coreutils}/bin/ls
222 sed -e 's@/\(usr\|opt\)/@/var/empty/@g' -i mkspecs/*/*.conf
223
224 sed -i '/PATHS.*NO_DEFAULT_PATH/ d' src/corelib/Qt5Config.cmake.in
225 sed -i '/PATHS.*NO_DEFAULT_PATH/ d' src/corelib/Qt5CoreMacros.cmake
226 sed -i 's/NO_DEFAULT_PATH//' src/gui/Qt5GuiConfigExtras.cmake.in
227 sed -i '/PATHS.*NO_DEFAULT_PATH/ d' mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in
228
229 # https://bugs.gentoo.org/803470
230 sed -i 's/-lpthread/-pthread/' mkspecs/common/linux.conf src/corelib/configure.json
231
232 patchShebangs ./bin
233 ''
234 + (
235 if stdenv.hostPlatform.isDarwin then
236 ''
237 for file in \
238 configure \
239 mkspecs/features/mac/asset_catalogs.prf \
240 mkspecs/features/mac/default_pre.prf \
241 mkspecs/features/mac/sdk.mk \
242 mkspecs/features/mac/sdk.prf
243 do
244 substituteInPlace "$file" \
245 --replace-quiet /usr/bin/xcode-select '${lib.getExe' xcbuild "xcode-select"}' \
246 --replace-quiet /usr/bin/xcrun '${lib.getExe' xcbuild "xcrun"}' \
247 --replace-quiet /usr/libexec/PlistBuddy '${lib.getExe' xcbuild "PlistBuddy"}'
248 done
249
250 substituteInPlace configure \
251 --replace-fail /System/Library/Frameworks/Cocoa.framework "$SDKROOT/System/Library/Frameworks/Cocoa.framework"
252
253 substituteInPlace mkspecs/common/macx.conf \
254 --replace-fail 'CONFIG += ' 'CONFIG += no_default_rpath ' \
255 --replace-fail \
256 'QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.13' \
257 "QMAKE_MACOSX_DEPLOYMENT_TARGET = $MACOSX_DEPLOYMENT_TARGET"
258 ''
259 else
260 lib.optionalString libGLSupported ''
261 sed -i mkspecs/common/linux.conf \
262 -e "/^QMAKE_INCDIR_OPENGL/ s|$|${lib.getDev libGL}/include|" \
263 -e "/^QMAKE_LIBDIR_OPENGL/ s|$|${lib.getLib libGL}/lib|"
264 ''
265 + lib.optionalString (stdenv.hostPlatform.isx86_32 && stdenv.cc.isGNU) ''
266 sed -i mkspecs/common/gcc-base-unix.conf \
267 -e "/^QMAKE_LFLAGS_SHLIB/ s/-shared/-shared -static-libgcc/"
268 ''
269 );
270
271 qtPluginPrefix = "lib/qt-${qtCompatVersion}/plugins";
272 qtQmlPrefix = "lib/qt-${qtCompatVersion}/qml";
273 qtDocPrefix = "share/doc/qt-${qtCompatVersion}";
274
275 setOutputFlags = false;
276 preConfigure = ''
277 export LD_LIBRARY_PATH="$PWD/lib:$PWD/plugins/platforms''${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH"
278
279 NIX_CFLAGS_COMPILE+=" -DNIXPKGS_QT_PLUGIN_PREFIX=\"$qtPluginPrefix\""
280
281 # paralellize compilation of qtmake, which happens within ./configure
282 export MAKEFLAGS+=" -j$NIX_BUILD_CORES"
283
284 ./bin/syncqt.pl -version $version
285 ''
286 + lib.optionalString (!stdenv.buildPlatform.canExecute stdenv.hostPlatform) ''
287 # QT's configure script will refuse to use pkg-config unless these two environment variables are set
288 export PKG_CONFIG_SYSROOT_DIR=/
289 export PKG_CONFIG_LIBDIR=${lib.getLib pkg-config}/lib
290 echo "QMAKE_LFLAGS=''${LDFLAGS}" >> mkspecs/devices/${qtPlatformCross stdenv.hostPlatform}/qmake.conf
291 echo "QMAKE_CFLAGS=''${CFLAGS}" >> mkspecs/devices/${qtPlatformCross stdenv.hostPlatform}/qmake.conf
292 echo "QMAKE_CXXFLAGS=''${CXXFLAGS}" >> mkspecs/devices/${qtPlatformCross stdenv.hostPlatform}/qmake.conf
293 '';
294
295 postConfigure = ''
296 qmakeCacheInjectNixOutputs() {
297 local cache="$1/.qmake.stash"
298 echo "qmakeCacheInjectNixOutputs: $cache"
299 if ! [ -f "$cache" ]; then
300 echo >&2 "qmakeCacheInjectNixOutputs: WARNING: $cache does not exist"
301 fi
302 cat >>"$cache" <<EOF
303 NIX_OUTPUT_BIN = $bin
304 NIX_OUTPUT_DEV = $dev
305 NIX_OUTPUT_OUT = $out
306 NIX_OUTPUT_DOC = $dev/$qtDocPrefix
307 NIX_OUTPUT_QML = $bin/$qtQmlPrefix
308 NIX_OUTPUT_PLUGIN = $bin/$qtPluginPrefix
309 EOF
310 }
311
312 find . -name '.qmake.conf' | while read conf; do
313 qmakeCacheInjectNixOutputs "$(dirname $conf)"
314 done
315 '';
316
317 env = {
318 NIX_CFLAGS_COMPILE = toString (
319 [
320 "-Wno-error=sign-compare" # freetype-2.5.4 changed signedness of some struct fields
321 ]
322 ++ lib.optionals (stdenv.buildPlatform != stdenv.hostPlatform) [
323 "-Wno-warn=free-nonheap-object"
324 "-Wno-free-nonheap-object"
325 "-w"
326 ]
327 ++ [
328 ''-DNIXPKGS_QTCOMPOSE="${libX11.out}/share/X11/locale"''
329 ''-DLIBRESOLV_SO="${stdenv.cc.libc.out}/lib/libresolv"''
330 ''-DNIXPKGS_LIBXCURSOR="${libXcursor.out}/lib/libXcursor"''
331 ]
332 ++ lib.optional libGLSupported ''-DNIXPKGS_MESA_GL="${libGL.out}/lib/libGL"''
333 ++ lib.optional stdenv.hostPlatform.isLinux "-DUSE_X11"
334 ++ lib.optionals withGtk3 [
335 ''-DNIXPKGS_QGTK3_XDG_DATA_DIRS="${gtk3}/share/gsettings-schemas/${gtk3.name}"''
336 ''-DNIXPKGS_QGTK3_GIO_EXTRA_MODULES="${dconf.lib}/lib/gio/modules"''
337 ]
338 ++ lib.optional decryptSslTraffic "-DQT_DECRYPT_SSL_TRAFFIC"
339 );
340 }
341 // lib.optionalAttrs (stdenv.buildPlatform != stdenv.hostPlatform) {
342 NIX_CFLAGS_COMPILE_FOR_BUILD = toString ([
343 "-Wno-warn=free-nonheap-object"
344 "-Wno-free-nonheap-object"
345 "-w"
346 ]);
347 };
348
349 prefixKey = "-prefix ";
350
351 # PostgreSQL autodetection fails sporadically because Qt omits the "-lpq" flag
352 # if dependency paths contain the string "pq", which can occur in the hash.
353 # To prevent these failures, we need to override PostgreSQL detection.
354 PSQL_LIBS = lib.optionalString (libpq != null) "-L${libpq}/lib -lpq";
355
356 }
357 // lib.optionalAttrs (stdenv.buildPlatform != stdenv.hostPlatform) {
358 configurePlatforms = [ ];
359 }
360 // {
361 # TODO Remove obsolete and useless flags once the build will be totally mastered
362 configureFlags = [
363 "-plugindir $(out)/$(qtPluginPrefix)"
364 "-qmldir $(out)/$(qtQmlPrefix)"
365 "-docdir $(out)/$(qtDocPrefix)"
366
367 "-verbose"
368 "-confirm-license"
369 "-opensource"
370
371 "-release"
372 "-shared"
373 "-accessibility"
374 "-optimized-qmake"
375 # for separateDebugInfo
376 "-no-strip"
377 "-system-proxies"
378 "-pkg-config"
379
380 "-gui"
381 "-widgets"
382 "-opengl desktop"
383 "-icu"
384 "-L"
385 "${icu.out}/lib"
386 "-I"
387 "${icu.dev}/include"
388 "-pch"
389 ]
390 ++ lib.optionals (stdenv.hostPlatform != stdenv.buildPlatform) [
391 "-device ${qtPlatformCross stdenv.hostPlatform}"
392 "-device-option CROSS_COMPILE=${stdenv.cc.targetPrefix}"
393 ]
394 ++ lib.optional debugSymbols "-debug"
395 ++ lib.optionals developerBuild [
396 "-developer-build"
397 "-no-warnings-are-errors"
398 ]
399 ++ lib.optionals (stdenv.buildPlatform != stdenv.hostPlatform) [
400 "-no-warnings-are-errors"
401 ]
402 ++ (
403 if (!stdenv.hostPlatform.isx86_64) then
404 [
405 "-no-sse2"
406 ]
407 else
408 [
409 "-sse2"
410 "${lib.optionalString (!stdenv.hostPlatform.sse3Support) "-no"}-sse3"
411 "${lib.optionalString (!stdenv.hostPlatform.ssse3Support) "-no"}-ssse3"
412 "${lib.optionalString (!stdenv.hostPlatform.sse4_1Support) "-no"}-sse4.1"
413 "${lib.optionalString (!stdenv.hostPlatform.sse4_2Support) "-no"}-sse4.2"
414 "${lib.optionalString (!stdenv.hostPlatform.avxSupport) "-no"}-avx"
415 "${lib.optionalString (!stdenv.hostPlatform.avx2Support) "-no"}-avx2"
416 ]
417 )
418 ++ [
419 "-no-mips_dsp"
420 "-no-mips_dspr2"
421 ]
422 ++ [
423 "-system-zlib"
424 "-L"
425 "${zlib.out}/lib"
426 "-I"
427 "${zlib.dev}/include"
428 "-system-libjpeg"
429 "-L"
430 "${libjpeg.out}/lib"
431 "-I"
432 "${libjpeg.dev}/include"
433 "-system-harfbuzz"
434 "-L"
435 "${harfbuzz.out}/lib"
436 "-I"
437 "${harfbuzz.dev}/include"
438 "-system-pcre"
439 "-openssl-linked"
440 "-L"
441 "${lib.getLib openssl}/lib"
442 "-I"
443 "${openssl.dev}/include"
444 "-system-sqlite"
445 ''-${if mysqlSupport then "plugin" else "no"}-sql-mysql''
446 ''-${if libpq != null then "plugin" else "no"}-sql-psql''
447 "-system-libpng"
448
449 "-make libs"
450 "-make tools"
451 ''-${lib.optionalString (!buildExamples) "no"}make examples''
452 ''-${lib.optionalString (!buildTests) "no"}make tests''
453 ]
454 ++ (
455 if stdenv.hostPlatform.isDarwin then
456 [
457 "-no-fontconfig"
458 "-no-framework"
459 "-no-rpath"
460 ]
461 else
462 [
463 "-rpath"
464 ]
465 ++ [
466 "-xcb"
467 "-qpa xcb"
468 "-L"
469 "${libX11.out}/lib"
470 "-I"
471 "${libX11.out}/include"
472 "-L"
473 "${libXext.out}/lib"
474 "-I"
475 "${libXext.out}/include"
476 "-L"
477 "${libXrender.out}/lib"
478 "-I"
479 "${libXrender.out}/include"
480
481 ''-${lib.optionalString (cups == null) "no-"}cups''
482 "-dbus-linked"
483 "-glib"
484 ]
485 ++ lib.optional withGtk3 "-gtk"
486 ++ lib.optional withLibinput "-libinput"
487 ++ [
488 "-inotify"
489 ]
490 ++ lib.optionals (cups != null) [
491 "-L"
492 "${cups.lib}/lib"
493 "-I"
494 "${cups.dev}/include"
495 ]
496 ++ lib.optionals (mysqlSupport) [
497 "-L"
498 "${libmysqlclient}/lib"
499 "-I"
500 "${libmysqlclient}/include"
501 ]
502 ++ lib.optional (withQttranslation && (qttranslations != null)) [
503 # depends on x11
504 "-translationdir"
505 "${qttranslations}/translations"
506 ]
507 );
508
509 # Move selected outputs.
510 postInstall = ''
511 moveToOutput "mkspecs" "$dev"
512 '';
513
514 devTools = [
515 "bin/fixqt4headers.pl"
516 "bin/moc"
517 "bin/qdbuscpp2xml"
518 "bin/qdbusxml2cpp"
519 "bin/qlalr"
520 "bin/qmake"
521 "bin/rcc"
522 "bin/syncqt.pl"
523 "bin/uic"
524 ];
525
526 postFixup = ''
527 # Don't retain build-time dependencies like gdb.
528 sed '/QMAKE_DEFAULT_.*DIRS/ d' -i $dev/mkspecs/qconfig.pri
529 fixQtModulePaths "''${!outputDev}/mkspecs/modules"
530 fixQtBuiltinPaths "''${!outputDev}" '*.pr?'
531
532 # Move development tools to $dev
533 moveQtDevTools
534 moveToOutput bin "$dev"
535
536 # fixup .pc file (where to find 'moc' etc.)
537 sed -i "$dev/lib/pkgconfig/Qt5Core.pc" \
538 -e "/^host_bins=/ c host_bins=$dev/bin"
539 '';
540
541 dontStrip = debugSymbols;
542
543 setupHook = ../hooks/qtbase-setup-hook.sh;
544
545 passthru.tests.pkg-config = testers.testMetaPkgConfig finalAttrs.finalPackage;
546
547 meta = with lib; {
548 homepage = "https://www.qt.io/";
549 description = "Cross-platform application framework for C++";
550 license = with licenses; [
551 fdl13Plus
552 gpl2Plus
553 lgpl21Plus
554 lgpl3Plus
555 ];
556 maintainers = with maintainers; [
557 qknight
558 ttuegel
559 periklis
560 bkchr
561 ];
562 pkgConfigModules = [
563 "Qt5Concurrent"
564 "Qt5Core"
565 "Qt5DBus"
566 "Qt5Gui"
567 "Qt5Network"
568 "Qt5OpenGL"
569 "Qt5OpenGLExtensions"
570 "Qt5PrintSupport"
571 #"Qt5Qml"
572 #"Qt5QmlModels"
573 #"Qt5Quick"
574 #"Qt5QuickTest"
575 #"Qt5QuickWidgets"
576 "Qt5Sql"
577 "Qt5Test"
578 "Qt5Widgets"
579 "Qt5Xml"
580 ];
581 platforms = platforms.unix;
582 };
583
584 }
585 )
586)