Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

qt5: cross compile with a clean separation of build and host binaries #267311

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
6d53085
distccMasquerade: add ar
Nov 13, 2023
964550b
Revert "nixos/no-x-libs: build qtbase without qt translation"
Jan 10, 2024
d81dd55
qt5: rework bootstrapping
Dec 7, 2023
f7a5576
qt5.qtbase: always build all packaged binaries for the hostPlatform
Dec 7, 2023
3d23b67
qt5.qtbase: support substituting a cross-built qtbase dependency with…
Jan 10, 2024
e26f0de
qt5.full: add disallowedReferences for qmake from buildHost
Nov 13, 2023
85a7eed
qt5: fix discovery of QT modules in cross builds
Nov 13, 2023
3a0a27b
qt5.qtwayland: fix cross compilation and dependencies
Nov 13, 2023
bef05f6
qt5.qtdeclarative: fix cross for qtdeclarative and some of it's users
Nov 13, 2023
d37157c
qt5.qttools: fix detection of lrelease and other tools in cross build…
Nov 13, 2023
e3eaf7e
qt5.wrapQtAppsHook: move libs to depsTargetTargetPropagated
Artturin Oct 25, 2023
041620b
qt5.qtwebkit: use hyphen from pkgs
Nov 14, 2023
f3ae8f6
qt5.qtwebkit: add missing optional deps
Nov 21, 2023
7b40a46
Revert "qt5.qtwebchannel: omit "bin" output when cross compiling"
Nov 16, 2023
0f6bb01
pyqt5: update cross
Nov 21, 2023
2c2d838
qt5.qtwebengine: update cross compilation support
Nov 16, 2023
772fd80
pyqtwebengine: update cross compilation support
Dec 2, 2023
5d64c29
qt5.qtbase: add preliminary support for cross on Darwin
Dec 3, 2023
0199c73
qt5.full: simplify package functions' definitions and calls
Dec 4, 2023
dbabeed
qt5.qtbase: remove broken QMAKEMODULES code
Dec 6, 2023
27353f1
qt5.qtbase: fix mysql support for cross builds
Dec 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion nixos/modules/config/no-x-libs.nix
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ with lib;
qemu = super.qemu.override { gtkSupport = false; spiceSupport = false; sdlSupport = false; };
qrencode = super.qrencode.overrideAttrs (_: { doCheck = false; });
qt5 = super.qt5.overrideScope (const (super': {
qtbase = super'.qtbase.override { withGtk3 = false; withQttranslation = false; };
qtbase = super'.qtbase.override { withGtk3 = false; };
}));
stoken = super.stoken.override { withGTK3 = false; };
# translateManpages -> perlPackages.po4a -> texlive-combined-basic -> texlive-core-big -> libX11
Expand Down
54 changes: 24 additions & 30 deletions pkgs/development/libraries/qt-5/5.15/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@ Check for any minor version changes.
*/

{ makeScopeWithSplicing', generateSplicesForMkScope
, lib, stdenv, fetchurl, fetchgit, fetchpatch, fetchFromGitHub, makeSetupHook, makeWrapper
, bison, cups ? null, harfbuzz, libGL, perl, python3
, gstreamer, gst-plugins-base, gtk3, dconf
, llvmPackages_15, overrideSDK, overrideLibcxx
, lib, stdenv, fetchurl, fetchgit, fetchpatch, fetchFromGitHub, makeSetupHook
, python3, llvmPackages_15, overrideSDK, overrideLibcxx
, darwin
, buildPackages

# options
, developerBuild ? false
Expand Down Expand Up @@ -46,13 +45,19 @@ let
./qtbase.patch.d/0009-qtbase-qtpluginpath.patch
./qtbase.patch.d/0010-qtbase-assert.patch
./qtbase.patch.d/0011-fix-header_module.patch
./qtbase.patch.d/0015-qtbase-cross-build.patch
(fetchpatch {
url = "https://sources.debian.org/data/main/q/qtbase-opensource-src/5.15.8%2Bdfsg-11/debian/patches/cross_build_mysql.diff";
hash = "sha256-tzmmLmMXmeDwRVjdpWekDJvSkrIIlslC12HP7XPcm3E=";
})
];
qtdeclarative = [
./qtdeclarative.patch
# prevent headaches from stale qmlcache data
./qtdeclarative-default-disable-qmlcache.patch
# add version specific QML import path
./qtdeclarative-qml-paths.patch
./qtdeclarative-cross-build.patch
];
qtlocation = lib.optionals stdenv.cc.isClang [
# Fix build with Clang 16
Expand Down Expand Up @@ -190,6 +195,7 @@ let
hash = "sha256-s4GsGMJTBNWw2gTJuIEP3tqT82AmTsR2mbj59m2p6rM=";
})
./qtwebengine-link-pulseaudio.patch
./qtwebengine-cross-build.patch
] ++ lib.optionals stdenv.isDarwin [
./qtwebengine-darwin-no-platform-check.patch
./qtwebengine-mac-dont-set-dsymutil-path.patch
Expand Down Expand Up @@ -228,7 +234,7 @@ let
./qtwebkit-darwin-no-readline.patch
./qtwebkit-darwin-no-qos-classes.patch
];
qttools = [ ./qttools.patch ];
qttools = [ ./qttools.patch ./qttools-cross-build.patch ];
};

addPackages = self:
Expand All @@ -241,7 +247,12 @@ let
(callPackage ../mkDerivation.nix { wrapQtAppsHook = null; }) stdenv.mkDerivation;
};

callPackage = self.newScope { inherit qtCompatVersion qtModule srcs stdenv; };
qtbase-bootstrap = buildPackages.qt5.qtbase.override { bootstrapBuild = true; };
# qtbase won't be spliced here, but that's fine as it's only a buildInput
qttools-bootstrap = buildPackages.qt5.qttools.override { qtbase=qtbase-bootstrap; qtdeclarative = null; };

# ↓Things available only to packages in the scope↓
callPackage = self.newScope { inherit qtbase-bootstrap qttools-bootstrap stdenv; };
in {

inherit callPackage qtCompatVersion qtModule srcs;
Expand All @@ -253,8 +264,7 @@ let
qtbase = callPackage ../modules/qtbase.nix {
inherit (srcs.qtbase) src version;
patches = patches.qtbase;
inherit bison cups harfbuzz libGL;
withGtk3 = !stdenv.isDarwin; inherit dconf gtk3;
withGtk3 = !stdenv.isDarwin;
inherit developerBuild decryptSslTraffic;
inherit (darwin.apple_sdk_11_0.frameworks) AGL AppKit ApplicationServices AVFoundation Carbon Cocoa CoreAudio CoreBluetooth
CoreLocation CoreServices DiskArbitration Foundation OpenGL MetalKit IOKit;
Expand All @@ -278,9 +288,7 @@ let
qtlocation = callPackage ../modules/qtlocation.nix {};
qtlottie = callPackage ../modules/qtlottie.nix {};
qtmacextras = callPackage ../modules/qtmacextras.nix {};
qtmultimedia = callPackage ../modules/qtmultimedia.nix {
inherit gstreamer gst-plugins-base;
};
qtmultimedia = callPackage ../modules/qtmultimedia.nix {};
qtnetworkauth = callPackage ../modules/qtnetworkauth.nix {};
qtpim = callPackage ../modules/qtpim.nix {};
qtpositioning = callPackage ../modules/qtpositioning.nix {};
Expand Down Expand Up @@ -357,11 +365,9 @@ let
] ++ lib.optional (!stdenv.isDarwin) qtwayland
++ lib.optional (stdenv.isDarwin) qtmacextras);

qmake = callPackage ({ qtbase }: makeSetupHook {
qmake = callPackage ({ qtbase-bootstrap }: makeSetupHook {
name = "qmake-hook";
${if stdenv.buildPlatform == stdenv.hostPlatform
then "propagatedBuildInputs"
else "depsTargetTargetPropagated"} = [ qtbase.dev ];
propagatedBuildInputs = [ qtbase-bootstrap.qmake ];
substitutions = {
inherit debug;
fix_qmake_libtool = ../hooks/fix-qmake-libtool.sh;
Expand All @@ -370,27 +376,15 @@ let

wrapQtAppsHook = callPackage ({ makeBinaryWrapper, qtbase, qtwayland }: makeSetupHook {
name = "wrap-qt5-apps-hook";
propagatedBuildInputs = [ qtbase.dev makeBinaryWrapper ]
propagatedBuildInputs = [ makeBinaryWrapper ];
depsTargetTargetPropagated = [ qtbase.dev ]
++ lib.optional stdenv.isLinux qtwayland.dev;
} ../hooks/wrap-qt-apps-hook.sh) { };
};

baseScope = makeScopeWithSplicing' {
finalScope = makeScopeWithSplicing' {
otherSplices = generateSplicesForMkScope "qt5";
f = addPackages;
};

bootstrapScope = baseScope.overrideScope(final: prev: {
qtbase = prev.qtbase.override { qttranslations = null; };
qtdeclarative = null;
});

finalScope = baseScope.overrideScope(final: prev: {
# qttranslations causes eval-time infinite recursion when
# cross-compiling; disabled for now.
qttranslations =
if stdenv.buildPlatform == stdenv.hostPlatform
then bootstrapScope.qttranslations
else null;
});
in finalScope
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
diff --git a/mkspecs/features/device_config.prf b/mkspecs/features/device_config.prf
index c15559e174..023a4bcb35 100644
--- a/mkspecs/features/device_config.prf
+++ b/mkspecs/features/device_config.prf
@@ -1,9 +1,5 @@
# This file is loaded by some qmakespecs to get early configuration data.

-# Some of these qmakespecs can be used also in host mode, but they are not
-# supposed to be influenced by -device-option then.
-host_build: return()
-
DEVICE_PRI = $$[QT_HOST_DATA/get]/mkspecs/qdevice.pri
exists($$DEVICE_PRI):include($$DEVICE_PRI)
unset(DEVICE_PRI)
diff --git a/mkspecs/features/qt_build_config.prf b/mkspecs/features/qt_build_config.prf
index 511b158b91..70d1e10611 100644
--- a/mkspecs/features/qt_build_config.prf
+++ b/mkspecs/features/qt_build_config.prf
@@ -15,6 +15,13 @@
debug(1, "Cannot load qmodule.pri!")
} else {
debug(1, "Loaded qmodule.pri from ($$QMAKE_QT_MODULE)")
+
+ # Yeah, there are multiple pkg-config related varialbes and functions
+ # that are used throughout QT modules somewhat interchangeably.
+ # As we're now trying to build all packaged binaries for the hostPlatform
+ # only, let's not create even more confusion and just follow a simple rule:
+ # always get pkg-config from the PKG_CONFIG env variable.
+ PKG_CONFIG_EXECUTABLE = $$(PKG_CONFIG)
}
} else {
debug(1, "Not loading qmodule.pri twice")
diff --git a/mkspecs/features/qt_configure.prf b/mkspecs/features/qt_configure.prf
index 6537d98c5d..19ed05db61 100644
--- a/mkspecs/features/qt_configure.prf
+++ b/mkspecs/features/qt_configure.prf
@@ -423,16 +423,7 @@ defineReplace(qtConfPkgConfigEnv) {
}

defineReplace(qtConfPkgConfig) {
- host = $$1
- isEmpty(host): host = false
-
- $$host {
- pkg_config = $$qtConfFindInPath("pkg-config")
- } else {
- pkg_config = "$$qtConfPkgConfigEnv()$$PKG_CONFIG_EXECUTABLE"
- }
-
- return($$pkg_config)
+ return($$getenv("PKG_CONFIG"))
}

defineTest(qtConfPkgConfigPackageExists) {
diff --git a/mkspecs/features/qt_tool.prf b/mkspecs/features/qt_tool.prf
index a8d589f0fa..3d0f832a6b 100644
--- a/mkspecs/features/qt_tool.prf
+++ b/mkspecs/features/qt_tool.prf
@@ -18,7 +18,7 @@ DEFINES *= QT_USE_QSTRINGBUILDER
# If we are doing a prefix build, create a "module" pri which enables
# qtPrepareTool() to work with the non-installed build.
# Non-bootstrapped tools always need this because of the environment setup.
-!build_pass:if(!host_build|!force_bootstrap|force_independent|!isEmpty(HOST_QT_TOOLS)) {
+!build_pass:if(!host_build|!force_bootstrap|force_independent|cross_compile) {
isEmpty(MODULE):MODULE = $$TARGET

load(qt_build_paths)
@@ -27,7 +27,7 @@ DEFINES *= QT_USE_QSTRINGBUILDER

vars = binary depends

- !host_build|isEmpty(HOST_QT_TOOLS) {
+ !host_build|!cross_compile {
load(resolve_target)

!host_build|!force_bootstrap: MODULE_DEPENDS = $$replace(QT, -private$, _private)
@@ -55,6 +55,10 @@ DEFINES *= QT_USE_QSTRINGBUILDER
bin = $${HOST_QT_TOOLS}/$${TARGET}
equals(QMAKE_HOST.os, Windows): bin = $${bin}.exe
bin = $$system_path($$bin)
+ !exists($$bin) {
+ # search in PATH as a fallback
+ bin = $$system("command -v $${TARGET}")
+ }
}

TOOL_PRI_CONT = \
diff --git a/src/corelib/Qt5CoreConfigExtras.cmake.in b/src/corelib/Qt5CoreConfigExtras.cmake.in
index be07a2e1e8..0b9c425ec8 100644
--- a/src/corelib/Qt5CoreConfigExtras.cmake.in
+++ b/src/corelib/Qt5CoreConfigExtras.cmake.in
@@ -5,30 +5,20 @@ endif()
if (NOT TARGET Qt5::qmake)
add_executable(Qt5::qmake IMPORTED)

-!!IF isEmpty(CMAKE_BIN_DIR_IS_ABSOLUTE)
- set(imported_location \"$$NIX_OUTPUT_DEV/$${CMAKE_BIN_DIR}qmake$$CMAKE_BIN_SUFFIX\")
-!!ELSE
- set(imported_location \"$${CMAKE_BIN_DIR}qmake$$CMAKE_BIN_SUFFIX\")
-!!ENDIF
- _qt5_Core_check_file_exists(${imported_location})
+ find_program(qmake_imported_location \"qmake$$CMAKE_BIN_SUFFIX\" PATHS ENV PATH NO_DEFAULT_PATH)

set_target_properties(Qt5::qmake PROPERTIES
- IMPORTED_LOCATION ${imported_location}
+ IMPORTED_LOCATION ${qmake_imported_location}
)
endif()

if (NOT TARGET Qt5::moc)
add_executable(Qt5::moc IMPORTED)

-!!IF isEmpty(CMAKE_BIN_DIR_IS_ABSOLUTE)
- set(imported_location \"$$NIX_OUTPUT_DEV/$${CMAKE_BIN_DIR}moc$$CMAKE_BIN_SUFFIX\")
-!!ELSE
- set(imported_location \"$${CMAKE_BIN_DIR}moc$$CMAKE_BIN_SUFFIX\")
-!!ENDIF
- _qt5_Core_check_file_exists(${imported_location})
+ find_program(moc_imported_location \"moc$$CMAKE_BIN_SUFFIX\" PATHS ENV PATH NO_DEFAULT_PATH)

set_target_properties(Qt5::moc PROPERTIES
- IMPORTED_LOCATION ${imported_location}
+ IMPORTED_LOCATION ${moc_imported_location}
)
# For CMake automoc feature
get_target_property(QT_MOC_EXECUTABLE Qt5::moc LOCATION)
@@ -37,15 +27,10 @@ endif()
if (NOT TARGET Qt5::rcc)
add_executable(Qt5::rcc IMPORTED)

-!!IF isEmpty(CMAKE_BIN_DIR_IS_ABSOLUTE)
- set(imported_location \"$$NIX_OUTPUT_DEV/$${CMAKE_BIN_DIR}rcc$$CMAKE_BIN_SUFFIX\")
-!!ELSE
- set(imported_location \"$${CMAKE_BIN_DIR}rcc$$CMAKE_BIN_SUFFIX\")
-!!ENDIF
- _qt5_Core_check_file_exists(${imported_location})
+ find_program(rcc_imported_location \"rcc$$CMAKE_BIN_SUFFIX\" PATHS ENV PATH NO_DEFAULT_PATH)

set_target_properties(Qt5::rcc PROPERTIES
- IMPORTED_LOCATION ${imported_location}
+ IMPORTED_LOCATION ${rcc_imported_location}
)
endif()

diff --git a/src/dbus/Qt5DBusConfigExtras.cmake.in b/src/dbus/Qt5DBusConfigExtras.cmake.in
index b13b964ec8..f4b7109037 100644
--- a/src/dbus/Qt5DBusConfigExtras.cmake.in
+++ b/src/dbus/Qt5DBusConfigExtras.cmake.in
@@ -2,22 +2,20 @@
if (NOT TARGET Qt5::qdbuscpp2xml)
add_executable(Qt5::qdbuscpp2xml IMPORTED)

- set(imported_location \"$$NIX_OUTPUT_DEV/bin/qdbuscpp2xml$$CMAKE_BIN_SUFFIX\")
- _qt5_DBus_check_file_exists(${imported_location})
+ find_program(qdbuscpp2xml_imported_location \"qdbuscpp2xml$$CMAKE_BIN_SUFFIX\" PATHS ENV PATH NO_DEFAULT_PATH)

set_target_properties(Qt5::qdbuscpp2xml PROPERTIES
- IMPORTED_LOCATION ${imported_location}
+ IMPORTED_LOCATION ${qdbuscpp2xml_imported_location}
)
endif()

if (NOT TARGET Qt5::qdbusxml2cpp)
add_executable(Qt5::qdbusxml2cpp IMPORTED)

- set(imported_location \"$$NIX_OUTPUT_DEV/bin/qdbusxml2cpp$$CMAKE_BIN_SUFFIX\")
- _qt5_DBus_check_file_exists(${imported_location})
+ find_program(qdbusxml2cpp_imported_location \"qdbusxml2cpp$$CMAKE_BIN_SUFFIX\" PATHS ENV PATH NO_DEFAULT_PATH)

set_target_properties(Qt5::qdbusxml2cpp PROPERTIES
- IMPORTED_LOCATION ${imported_location}
+ IMPORTED_LOCATION ${qdbusxml2cpp_imported_location}
)
endif()

diff --git a/src/widgets/Qt5WidgetsConfigExtras.cmake.in b/src/widgets/Qt5WidgetsConfigExtras.cmake.in
index ca0b8e4bfb..f49f09fed2 100644
--- a/src/widgets/Qt5WidgetsConfigExtras.cmake.in
+++ b/src/widgets/Qt5WidgetsConfigExtras.cmake.in
@@ -2,15 +2,10 @@
if (NOT TARGET Qt5::uic)
add_executable(Qt5::uic IMPORTED)

-!!IF isEmpty(CMAKE_BIN_DIR_IS_ABSOLUTE)
- set(imported_location \"$$NIX_OUTPUT_DEV/$${CMAKE_BIN_DIR}uic$$CMAKE_BIN_SUFFIX\")
-!!ELSE
- set(imported_location \"$${CMAKE_BIN_DIR}uic$$CMAKE_BIN_SUFFIX\")
-!!ENDIF
- _qt5_Widgets_check_file_exists(${imported_location})
+ find_program(uic_imported_location \"uic$$CMAKE_BIN_SUFFIX\" PATHS ENV PATH NO_DEFAULT_PATH)

set_target_properties(Qt5::uic PROPERTIES
- IMPORTED_LOCATION ${imported_location}
+ IMPORTED_LOCATION ${uic_imported_location}
)
endif()

Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
diff --git a/mkspecs/features/qt_build_config.prf b/mkspecs/features/qt_build_config.prf
index 70d1e10611..ce8b9383eb 100644
--- a/mkspecs/features/qt_build_config.prf
+++ b/mkspecs/features/qt_build_config.prf
@@ -16,6 +16,12 @@
} else {
debug(1, "Loaded qmodule.pri from ($$QMAKE_QT_MODULE)")

+ # detect cross compilation status dynamically for the case of
+ # switching cross and natively built qtbase
+ _crossComp = $$(XQMAKESPEC)
+ isEmpty(_crossComp): CONFIG -= cross_compile
+ else: CONFIG += cross_compile
+
# Yeah, there are multiple pkg-config related varialbes and functions
# that are used throughout QT modules somewhat interchangeably.
# As we're now trying to build all packaged binaries for the hostPlatform
diff --git a/mkspecs/features/qt_config.prf b/mkspecs/features/qt_config.prf
index 93c54e3010..65552276ac 100644
--- a/mkspecs/features/qt_config.prf
+++ b/mkspecs/features/qt_config.prf
@@ -5,6 +5,18 @@ QMAKE_QT_CONFIG = $$[QT_HOST_DATA/get]/mkspecs/qconfig.pri
debug(1, "Cannot load qconfig.pri!")
} else {
debug(1, "Loaded .qconfig.pri from ($$QMAKE_QT_CONFIG)")
+
+ # detect cross compilation status dynamically for the case of
+ # switching cross and natively built qtbase
+ _crossComp = $$(XQMAKESPEC)
+ isEmpty(_crossComp) {
+ QT.global.enabled_features -= cross_compile
+ CONFIG -= cross_compile
+ } else {
+ QT.global.enabled_features += cross_compile
+ CONFIG += cross_compile
+ }
+
dirs = $$(QMAKEMODULES)
QMAKE_MODULE_PATH = $$split(dirs, $$DIRLIST_SEPARATOR)
QMAKE_MODULE_PATH += $$QMAKEMODULES
Loading