Skip to content

qt6: support cross compilation#447041

Draft
outfoxxed wants to merge 1 commit intoNixOS:stagingfrom
outfoxxed:qt6-cross
Draft

qt6: support cross compilation#447041
outfoxxed wants to merge 1 commit intoNixOS:stagingfrom
outfoxxed:qt6-cross

Conversation

@outfoxxed
Copy link
Copy Markdown
Member

Implements support for cross compilation most of Qt 6.

Cross compilation was tested for riscv64 but all changes here should apply generally. I did not test qtwebengine or qtquick3dphysics as they cannot compile for riscv64. Pyside and Shiboken6 still do not work, and as such all of kde still does not work.

qt6.full still builds as expected for non-cross x86_64. All new patches are applied only when cross compiling to reduce the impact of any future breakage to just things that already didn't work.

The qtbase setup hook has also been changed to account for cross compilation, and a flag to skip running it has been added, as I'm not aware of another way to skip hooks and I've had to rebuild for it quite often.

cc @NickCao @K900

Things done

  • Built on platform:
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
    • riscv64-linux
  • Tested, as applicable:
  • Ran nixpkgs-review on this PR. See nixpkgs-review usage.
  • Tested basic functionality of all binary files, usually in ./result/bin/.
  • Nixpkgs Release Notes
    • Package update: when the change is major or breaking.
  • NixOS Release Notes
    • Module addition: when adding a new NixOS module.
    • Module update: when the change is significant.
  • Fits CONTRIBUTING.md, pkgs/README.md, maintainers/README.md and other READMEs.

Add a 👍 reaction to pull requests you find important.

@ofborg ofborg bot added the 6.topic: cross-compilation Building packages on a different platform than they will be used on label Sep 29, 2025
@nixpkgs-ci nixpkgs-ci bot added 2.status: merge conflict This PR has merge conflicts with the target branch 10.rebuild-linux: 501+ This PR causes many rebuilds on Linux and should normally target the staging branches. 10.rebuild-darwin: 101-500 This PR causes between 101 and 500 packages to rebuild on Darwin. 10.rebuild-linux: 1001-2500 This PR causes many rebuilds on Linux and should target the staging branches. labels Sep 29, 2025
@nixpkgs-ci nixpkgs-ci bot removed the 2.status: merge conflict This PR has merge conflicts with the target branch label Sep 29, 2025
Implements support for cross compilation most of Qt 6, excluding pyside.
@LunNova
Copy link
Copy Markdown
Member

LunNova commented Sep 29, 2025

Trying some aarch64 cross from an x86_64 host and qtdeclarative seems to be trying to exec aarch64 binaries during the build:

$ nix build github:nixos/nixpkgs/eb6578e1e620b38094b9be8a6cd42c01996d7c81#pkgsCross.aarch64-multiplatform.qt6.qtdeclarative
rror: builder for '/nix/store/8w6xb1vfnxxqk7iakrjjml4bgnbi548l-qtdeclarative-aarch64-unknown-linux-gnu-6.9.2.drv' failed on remote builder;
       last 25 log lines:
       > FAILED: [code=126] src/quick/.qsb/scenegraph/shaders_ng/32bitcolortext.frag.qsb.mv2qsb /build/qtdeclarative-everywhere-src-6.9.2/build/src/quick/.qsb/scenegraph/shaders_ng/32bitcolortext.frag.qsb.mv2qsb
       > cd /build/qtdeclarative-everywhere-src-6.9.2/build/src/quick && /nix/store/z7qfk0gx54ljnhsynv890522hx0d8dnv-qtshadertools-aarch64-unknown-linux-gnu-6.9.2/bin/qsb --glsl 330,300es --hlsl 61 --msl 21 --view-count 2 -b -O -s -o /build/qtdeclarative-everywhere-src-6.9.2/build/src/quick/.qsb/scenegraph/shaders_ng/32bitcolortext.frag.qsb.mv2qsb /build/qtdeclarative-everywhere-src-6.9.2/src/quick/scenegraph/shaders_ng/32bitcolortext.frag --depfile /build/qtdeclarative-everywhere-src-6.9.2/build/src/quick/.qsb/scenegraph/shaders_ng/32bitcolortext.frag.qsb.mv2qsb.d && /nix/store/2lrbixyw95bjg0x1aav648r0h0zsj2jl-cmake-4.1.1/bin/cmake -E cmake_transform_depfile Ninja gccdepfile /build/qtdeclarative-everywhere-src-6.9.2 /build/qtdeclarative-everywhere-src-6.9.2/src/quick /build/qtdeclarative-everywhere-src-6.9.2/build /build/qtdeclarative-everywhere-src-6.9.2/build/src/quick /build/qtdeclarative-everywhere-src-6.9.2/build/src/quick/.qsb/scenegraph/shaders_ng/32bitcolortext.frag.qsb.mv2qsb.d /build/qtdeclarative-everywhere-src-6.9.2/build/CMakeFiles/d/abc0d9f3021bed97a0d63c3b0019b6ad666543aea1f67412160ebe8a20ad1f43.d
       > sh: line 1: /nix/store/z7qfk0gx54ljnhsynv890522hx0d8dnv-qtshadertools-aarch64-unknown-linux-gnu-6.9.2/bin/qsb: cannot execute binary file: Exec format error
       > [5/3327] Generating .qsb/scenegraph/shaders_ng/8bittextmask.frag.qsb
       > FAILED: [code=126] src/quick/.qsb/scenegraph/shaders_ng/8bittextmask.frag.qsb /build/qtdeclarative-everywhere-src-6.9.2/build/src/quick/.qsb/scenegraph/shaders_ng/8bittextmask.frag.qsb
       > cd /build/qtdeclarative-everywhere-src-6.9.2/build/src/quick && /nix/store/z7qfk0gx54ljnhsynv890522hx0d8dnv-qtshadertools-aarch64-unknown-linux-gnu-6.9.2/bin/qsb --glsl 100es,120,150 --hlsl 50 --msl 12 -b -O -s -o /build/qtdeclarative-everywhere-src-6.9.2/build/src/quick/.qsb/scenegraph/shaders_ng/8bittextmask.frag.qsb --depfile /build/qtdeclarative-everywhere-src-6.9.2/build/src/quick/.qsb/scenegraph/shaders_ng/8bittextmask.frag.qsb.d /build/qtdeclarative-everywhere-src-6.9.2/src/quick/scenegraph/shaders_ng/8bittextmask.frag && /nix/store/2lrbixyw95bjg0x1aav648r0h0zsj2jl-cmake-4.1.1/bin/cmake -E cmake_transform_depfile Ninja gccdepfile /build/qtdeclarative-everywhere-src-6.9.2 /build/qtdeclarative-everywhere-src-6.9.2/src/quick /build/qtdeclarative-everywhere-src-6.9.2/build /build/qtdeclarative-everywhere-src-6.9.2/build/src/quick /build/qtdeclarative-everywhere-src-6.9.2/build/src/quick/.qsb/scenegraph/shaders_ng/8bittextmask.frag.qsb.d /build/qtdeclarative-everywhere-src-6.9.2/build/CMakeFiles/d/6e5ae92b78984239707dfd08b2956fcc6e84a3cc06b8d936240674636bd57c3c.d

# Conditional is required to prevent infinite recursion during a cross build
++ lib.optionals (!stdenv.buildPlatform.canExecute stdenv.hostPlatform) [
"-DQt6QmlTools_DIR=${pkgsBuildBuild.qt6.qtdeclarative}/lib/cmake/Qt6QmlTools"
"-DPython_EXECUTABLE=${lib.getExe pkgsBuildHost.python3}"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this not get detected if you put it in nativeBuildInputs? And if it doesn't get detected could you write

Suggested change
"-DPython_EXECUTABLE=${lib.getExe pkgsBuildHost.python3}"
"-DPython_EXECUTABLE=python3"

with it in nativeBuildInputs?

Though I guess how you have it here is most explicit.

Copy link
Copy Markdown
Member Author

@outfoxxed outfoxxed Sep 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like it was there previously for darwin. I would assume it didn't but I never tested darwin.

@outfoxxed
Copy link
Copy Markdown
Member Author

Trying some aarch64 cross from an x86_64 host and qtdeclarative seems to be trying to exec aarch64 binaries during the build

That's quite strange, especially because it builds fine from x86_64->riscv64. Maybe something changed in the rebase onto staging?. I'll try building for arm.

@LunNova
Copy link
Copy Markdown
Member

LunNova commented Sep 30, 2025

Trying some aarch64 cross from an x86_64 host and qtdeclarative seems to be trying to exec aarch64 binaries during the build

That's quite strange, especially because it builds fine from x86_64->riscv64. Maybe something changed in the rebase onto staging?. I'll try building for arm.

Do you have binfmt misc support turned on for riscv64 on the x86_64 box you're testing with? IIRC that can leak in and let a cross build succeed when it really ought not to. #61537

@outfoxxed
Copy link
Copy Markdown
Member Author

I have boot.binfmt.emulatedSystems but not binfmt_misc. I'll try building with binfmt off.

@outfoxxed
Copy link
Copy Markdown
Member Author

I was able to reproduce the shadertools issue.

@outfoxxed
Copy link
Copy Markdown
Member Author

outfoxxed commented Sep 30, 2025

This is unfortunate. It looks like the tooling lookup functions that check the host paths aren't actually used in a lot of cases, and many Qt packages hard-code QT_HOST_PATH instead, for example QtDeclarative below:

# Set up QT_HOST_PATH as an extra root path to look for the ShaderToolsTools package
# when cross-compiling.
if(NOT "${QT_HOST_PATH}" STREQUAL "")
     set(_qt_backup_qtdeclarative_CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH})
     set(_qt_backup_qtdeclarative_CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH})
     list(PREPEND CMAKE_PREFIX_PATH "${QT_HOST_PATH_CMAKE_DIR}")
     list(PREPEND CMAKE_FIND_ROOT_PATH "${QT_HOST_PATH}")
endif()

# This can't use the find_package(Qt6 COMPONENTS) signature, because Qt6Config uses NO_DEFAULT and
# won't look at the prepend extra find root paths.
find_package(Qt6ShaderToolsTools ${PROJECT_VERSION} CONFIG
    PATHS
            ${_qt_additional_packages_prefix_path}
            ${_qt_additional_packages_prefix_path_env}
)

if(NOT "${QT_HOST_PATH}" STREQUAL "")
     set(CMAKE_PREFIX_PATH ${_qt_backup_qtdeclarative_CMAKE_PREFIX_PATH})
     set(CMAKE_FIND_ROOT_PATH ${_qt_backup_qtdeclarative_CMAKE_FIND_ROOT_PATH})
endif()

Now the main options I see are

  1. Patch all the cmake files
  2. Manually provide all tool paths via cmakeFlags
  3. Create a symlink-join directory and populate QT_HOST_PATH, but I'm not aware of a way to do that from a hook.

Regardless of which option we pick here I think QT_ADDITIONAL_HOST_PACKAGES_PREFIX_PATH should still be populated for anything that does use Qt's tool lookup functions, because there are a few usages of those.

I'm going to ask if upstream has any recommendations.

@outfoxxed
Copy link
Copy Markdown
Member Author

Unfortunately I'm going to be away from my build/test setup for a couple weeks and won't be able to work on this until I'm back. I'll mark it as a draft till I have further progress.

@outfoxxed outfoxxed marked this pull request as draft October 4, 2025 18:37
@LunNova
Copy link
Copy Markdown
Member

LunNova commented Oct 4, 2025

I'm going to ask if upstream has any recommendations.

Is there an upstream discussion to follow for the shadertools issue?

@nixpkgs-ci nixpkgs-ci bot added the 2.status: merge conflict This PR has merge conflicts with the target branch label Oct 9, 2025
@doronbehar
Copy link
Copy Markdown
Contributor

Hey there,

I'm too interested in cross compiling qt6 apps, and I haven't experienced any substantial failures when cross building qt6.qtbase. I did notice though that a cross build of qt6.qtbase pulls in buildPackages.qt6.qtbase:

$ nix why-depends --precise --all -f. pkgsCross.armv7l-hf-multiplatform.qt6.qtbase qt6.qtbase
/i5zzrmq85zgb1j99h1cnymx6dfmpff1j-qtbase-armv7l-unknown-linux-gnueabihf-6.10.1
└───bin/qmake: …pt_dir_path"; pwd)`../nix/store/jq8mka96cq81mfzm4svzmbalna8asqfn-qtbase-6.10.1/bin/qmake6 -qtcon…
    bin/qmake6: …pt_dir_path"; pwd)`../nix/store/jq8mka96cq81mfzm4svzmbalna8asqfn-qtbase-6.10.1/bin/qmake6 -qtcon…
    bin/qtpaths: …pt_dir_path"; pwd)`../nix/store/jq8mka96cq81mfzm4svzmbalna8asqfn-qtbase-6.10.1/bin/qtpaths6 -qtc…
    bin/qtpaths6: …pt_dir_path"; pwd)`../nix/store/jq8mka96cq81mfzm4svzmbalna8asqfn-qtbase-6.10.1/bin/qtpaths6 -qtc…
    bin/target_qt.conf: …ttings=etc/xdg.HostPrefix=../../jq8mka96cq81mfzm4svzmbalna8asqfn-qtbase-6.10.1.HostBinaries=bin.…
    lib/cmake/Qt6/Qt6Dependencies.cmake: …nitial_qt_host_path "/nix/store/jq8mka96cq81mfzm4svzmbalna8asqfn-qtbase-6.10.1").set(__qt_platfo…
    → /jq8mka96cq81mfzm4svzmbalna8asqfn-qtbase-6.10.1

In #481338 , I'm trying to use the $dev output to avoid this issue:

$ nix why-depends --all --precise -f. pkgsCross.armv7l-hf-multiplatform.{qt6.qtbase,buildPackages.pkg-config.out}
/i5zzrmq85zgb1j99h1cnymx6dfmpff1j-qtbase-armv7l-unknown-linux-gnueabihf-6.10.1
└───mkspecs/qmodule.pri: …_CONFIG_EXECUTABLE = /nix/store/51sjl16b30wi14wmfa326lh56zpd08g9-armv7l-unknown-linux-gnueabihf-…
    → /51sjl16b30wi14wmfa326lh56zpd08g9-armv7l-unknown-linux-gnueabihf-pkg-config-wrapper-0.29.2

So maybe the motivation of this PR should be rephrased?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2.status: merge conflict This PR has merge conflicts with the target branch 6.topic: cross-compilation Building packages on a different platform than they will be used on 10.rebuild-darwin: 101-500 This PR causes between 101 and 500 packages to rebuild on Darwin. 10.rebuild-linux: 501+ This PR causes many rebuilds on Linux and should normally target the staging branches. 10.rebuild-linux: 1001-2500 This PR causes many rebuilds on Linux and should target the staging branches.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants