从源代码构建

重要

本页面主要介绍如何从源代码构建Qt for Python。 如果您只想安装PySide6,您需要运行:pip install pyside6

更多详情,请参阅我们的入门指南。此外,您可以查看与项目相关的常见问题解答

一般要求

在构建Qt for Python之前,必须安装以下先决条件。 在Linux上,您可以通过操作系统的包管理器获取它们,在macOS上, 您可以通过brew获取它们,而在Windows上,您可以从每个网站下载安装程序。

每个平台的指南

您可以参考以下页面获取平台特定的说明:

重要

Qt for Python 目前还不支持 WebAssembly 和移动操作系统(Android 或 iOS)。 大多数基于 Linux 的嵌入式操作系统都通过其官方包管理器提供 PySide(例如,RaspbianArchlinuxARM)。

一个正常的构建命令将如下所示:

python setup.py install --qtpaths=/path/to/qtpaths \
                        --ignore-git \
                        --debug \
                        --build-tests \
                        --parallel=8 \
                        --verbose-build \
                        --module-subset=Core,Gui,Widgets

这将构建并安装带有调试符号的项目,包括测试, 使用ninja(而不是make),并且仅考虑QtCoreQtGuiQtWidgets模块子集

CMake Unity Build Mode 默认用于加速。

Other important options to consider are:
  • --cmake,用于指定cmake二进制文件的路径,

  • --reuse-build,仅重建修改过的文件,

  • --openssl=/path/to/openssl/bin, 使用不同的路径来访问OpenSSL,

  • --standalone,将Qt库复制到最终包中,以便在其他机器上运行,

  • --build-docs,用于启用文档构建。

  • --doc-build-online, 使用在线模板构建文档(默认情况下使用离线模板)

测试安装

安装完成后,您将能够执行我们的任何示例:

python examples/widgets/widgets/tetrix/tetrix.py

运行测试

使用 --build-tests 选项将使我们能够在项目内运行所有自动测试:

python testrunner.py test > testlog.txt

注意

在Windows上,不要忘记将qtpaths添加到你的路径中 (set PATH=C:\Path\to\Qt\6.4.0\msvc2019_64\bin;%PATH%)

你也可以通过运行以下命令来运行特定的测试(例如 qpainter_test):

ctest -R qpainter_test --verbose

交叉编译

从6.3版本开始,可以交叉编译Shiboken(模块)和PySide。此功能仍处于技术预览阶段,这意味着在未来的版本中可能会有所变化。

重要

唯一支持的配置是使用主机Linux机器交叉编译到Linux目标平台。

跨平台编译软件是许多项目依赖的有效用例,然而,这是一个复杂的过程,可能会由于多种原因而失败。

在开始这个过程之前,了解构建系统的细节以及交叉编译的目标是很重要的。

在构建过程中,Host 是您当前用于编译的计算机,而 Target 是您为其编译的嵌入式设备。

Qt for Python 正在使用 setuptools 构建,并依赖于一个 setup.py 文件 该文件被递归调用以构建 Shiboken(模块)、 Shiboken(生成器)和 PySide。由于生成器正在创建 绑定的包装器,它不会为目标进行交叉编译。 只有 Shiboken(模块)和 PySide 是交叉编译的。

构建过程需要在主机和目标上安装Qt和Python解释器。两个平台上使用的Qt版本应具有相同的次要版本。也就是说,Qt 6.3(主机)不能与Qt 6.2(目标)一起使用,反之亦然。

注意

建议在主机和目标上使用相同版本的Qt,以避免可能出现的不常见错误。

先决条件

首先,您需要访问目标设备,因为您需要复制几个系统文件(sysroot)。我们推荐使用具有最新Qt版本的Linux操作系统,例如Manjaro ARMArchlinux ARM

  • (target) 使用包管理器在系统上安装 Qt 6.3+。

  • (host) 使用包管理器或Qt安装程序在系统上安装Qt 6.3+。

  • (target, host) 安装提供C++头文件、链接器、库和编译器的库和开发包。

  • (target, host) 安装 Python 解释器 v3.7 或更高版本

  • (target, host) 安装 CMake 3.17+

安装这些先决条件后,将target sysroot复制到您的host计算机上。这个过程很棘手,因为从另一台计算机复制系统文件可能会导致符号链接出现问题。在这里,您有两种选择来实现这一点。

选项A:复制文件

创建一个目录来复制目标设备的系统根目录, 例如 rpi-sysroot,并在您的主机电脑上执行复制操作:

rsync -vR --progress -rl --delete-after --safe-links \
    USERNAME@TARGET_IP:/{lib,usr,opt/vc/lib} rpi-sysroot/

请确保将USERNAMETARGET_IP替换为适合您系统的值。

选项 B:打包文件系统

为你的目标系统根目录创建一个包:

tar cfJ ~/sysroot.tar.xz /lib /usr /opt/vc/lib

将包从目标复制到您的主机:

rsync -vR --progress USERNAME@TARGET_IP:sysroot.tar.xz .

一旦你有了tar文件,请在rpi-sysroot目录内解压它。

设置工具链

要进行交叉编译,您需要一组特殊的编译器、库和头文件,这些工具在主机架构上运行,但为目标架构生成(二进制文件/可执行文件)。例如,从x86_64到aarch64。

建议使用官方的10.2 ARM开发者交叉编译器,您可以在他们的官方网站上找到。在本教程中,我们选择aarch64目标架构,并假设您已经下载了gcc-arm-10.2-2020.11-x86_64-aarch64-none-linux-gnu.tar.xz文件,并解压了它。

使用这些编译器,现在你需要一个CMake工具链文件。这是一个配置文件,用于设置编译器、系统根目录信息,以及编译标志等额外选项和其他细节。你可以使用以下文件作为示例,但请记住它们可能会有所不同:

# toolchain-aarch64.cmake
cmake_minimum_required(VERSION 3.18)
include_guard(GLOBAL)

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)

set(TARGET_SYSROOT /path/to/your/target/sysroot)
set(CROSS_COMPILER /path/to/your/crosscompiling/compilers/)

set(CMAKE_SYSROOT ${TARGET_SYSROOT})

set(ENV{PKG_CONFIG_PATH} "")
set(ENV{PKG_CONFIG_LIBDIR} ${CMAKE_SYSROOT}/usr/lib/pkgconfig:${CMAKE_SYSROOT}/usr/share/pkgconfig)
set(ENV{PKG_CONFIG_SYSROOT_DIR} ${CMAKE_SYSROOT})

set(CMAKE_C_COMPILER ${CROSS_COMPILER}/aarch64-none-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER ${CROSS_COMPILER}/aarch64-none-linux-gnu-g++)

set(QT_COMPILER_FLAGS "-march=armv8-a")
set(QT_COMPILER_FLAGS_RELEASE "-O2 -pipe")
set(QT_LINKER_FLAGS "-Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed")

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

include(CMakeInitializeConfigs)

function(cmake_initialize_per_config_variable _PREFIX _DOCSTRING)
  if (_PREFIX MATCHES "CMAKE_(C|CXX|ASM)_FLAGS")
    set(CMAKE_${CMAKE_MATCH_1}_FLAGS_INIT "${QT_COMPILER_FLAGS}")

    foreach (config DEBUG RELEASE MINSIZEREL RELWITHDEBINFO)
      if (DEFINED QT_COMPILER_FLAGS_${config})
        set(CMAKE_${CMAKE_MATCH_1}_FLAGS_${config}_INIT "${QT_COMPILER_FLAGS_${config}}")
      endif()
    endforeach()
  endif()

  if (_PREFIX MATCHES "CMAKE_(SHARED|MODULE|EXE)_LINKER_FLAGS")
    foreach (config SHARED MODULE EXE)
      set(CMAKE_${config}_LINKER_FLAGS_INIT "${QT_LINKER_FLAGS}")
    endforeach()
  endif()

  _cmake_initialize_per_config_variable(${ARGV})
endfunction()

你需要调整这两行中的路径:

set(TARGET_SYSROOT /path/to/your/target/sysroot)
set(CROSS_COMPILER /path/to/your/crosscompiling/compilers/)

并将它们替换为sysroot目录(我们称之为rpi-sysroot), 以及编译器(gcc-arm-10.2-2020.11-x86_64-aarch64-none-linux-gnu/bin目录)。

交叉编译PySide

在您安装了先决条件并复制了必要的文件后,您应该有以下内容:

  • 用于交叉编译的编译器 (gcc-argm-10.2-...),

  • 目标系统根目录 (rpi-sysroot),

  • 工具链 cmake 文件 (toolchain-aarch64.cmake),

  • pyside-setup 仓库,

一个setup.py调用的示例如下所示:

python setup.py bdist_wheel \
    --parallel=8 --ignore-git --reuse-build --standalone --limited-api=yes \
    --cmake-toolchain-file=/opt/toolchain-aarch64.cmake \
    --qt-host-path=/opt/Qt/6.3.0/gcc_64 \
    --plat-name=linux_aarch64

根据目标平台的不同,您可以使用 linux_armv7linux_aarch64 等。

对于嵌入式平台,通常没有完全构建的Qt及其工具,可以使用选项--no-qt-tools来防止工具的捆绑。

如果过程成功,您将在dist/目录中找到目标轮子,例如:

PySide6-6.3.0-6.3.0-cp36-abi3-manylinux2014_aarch64.whl
shiboken6-6.3.0-6.3.0-cp36-abi3-manylinux2014_aarch64.whl

故障排除

  • 如果自动检测机制无法找到目标设备中的Python或Qt安装,你可以使用两个额外的选项:

    --python-target-path=...
    

    以及:

    --qt-target-path=...
    
  • 如果主机Shiboken(生成器)的自动构建失败,您可以使用以下方式指定自定义路径:

    --shiboken-host-path=...
    

构建文档

从6.3版本开始,默认情况下不再构建文档。 当使用本节中描述的第二个选项时,请确保使用 --build-docs 选项。

在你的Python虚拟环境中安装特定的文档要求:

pip install -r requirements-doc.txt

你可以在仓库的根目录中找到requirements-doc.txt文件。

从5.15开始,有两种构建文档的选项:

1. 构建基础文档(无API)

解析Qt头文件以生成PySide API文档的过程可能需要几分钟,这意味着修改我们当前文档的特定部分可能会变得困难。您可能只关心基础文档,它包括除API文档之外的所有文档。

要生成这个,请执行以下命令:

python setup.py build_base_docs

这将生成一个html/目录,其结构如下:

html
└── pyside6
    ├── index.html
    ├── ...
    └── shiboken6
        ├── index.html
        └── ...

所以你可以在浏览器中打开主页面 html/pyside6/index.html 来检查生成的文件。

这在更新文档的通用部分、添加教程、修改构建说明等方面非常有用。

注意

如果你只对生成示例库感兴趣, 你需要运行python tools/example_gallery/main.py来 为库生成示例documentation。这也会被 build_base_docs目标内部使用。

2. 构建文档(基础 + API)

文档正在使用qdoc生成以获取API信息,同时使用sphinx生成本地Python相关笔记。

系统需要libxml2libxslt库。

安装graphviz(包含在requirements-doc.txt文件中)后, dot命令需要在PATH中,否则, 该过程将失败。系统范围内安装graphviz也是一个选项。

由于该过程依赖于Qt安装,您需要通过命令行选项--qt-src-dir指定Qt源代码树中qtbase目录的位置。

一旦常见的setup.py构建过程完成(记得使用 --build-docs来启用文档构建,以及--doc-build-online 来获取HTML文件),你可以前往生成的 build//build/pyside6目录,并运行:

ninja apidoc

你可以添加-j X,以使用X个进程并行执行构建过程。

注意

apidoc 构建目标默认生成离线文档,格式为 QCH(Qt 压缩帮助)。你可以通过配置选项 --doc-build-online 切换到生成在线使用的文档。

目标执行以下几个步骤:

  1. qdoc 工具在 Qt 源代码上运行,以生成 WebXML 格式的文档。

  2. shiboken6 用于从 WebXML 中提取存在绑定的函数并将其转换为 RST。

  3. sphinx 运行以生成HTML格式的文档。

重新运行命令不会执行步骤1,除非从构建树中删除文件 qdoc-output/webxml/qtcore-index.webxml。 同样,步骤2也不会执行,除非删除文件 base/PySide6/QtCore/index.rst

最后,你将得到一个包含所有生成文档的html目录。离线帮助文件PySide.qchShiboken.qch可以移动到您选择的任何目录。你可以在构建目录build//build/shiboken6/doc/html中找到Shiboken.qch

如果你想暂时更改一个.rst文件以检查对格式的影响,你可以在doc目录中重新运行sphinx

sphinx-build base html

查看离线文档

离线文档(QCH)可以使用Qt Creator IDE或Qt Assistant查看,后者是一个用于查看QCH文件的独立应用程序。

要使用Qt Creator查看QCH,请按照使用Qt Creator帮助模式中概述的说明进行操作。 如果您选择使用Qt Assistant,请在启动Qt Assistant之前使用以下命令注册QCH文件:

assistant -register PySide.qch

故障排除文档

文档使用 intersphinx 从 PySide 链接到 Shiboken 文档。如果以下情况发生,可能会失败:

  • 默认使用QCH格式;在这种情况下,不会生成所需的objects.inv文件。请使用--doc-build-online

  • 基础文档和完整文档构建混合在一起,导致CMake文件中的intersphinx位置值错误。重新运行cmake以修复此问题。

使用内部工具

pyside-setup仓库中的tools/目录下可以找到一组工具。

  • checklibs.py: 用于分析Mach-O二进制文件的动态库依赖关系的脚本。 要使用此工具,只需运行:

    python checklibs.py /path/to/some.app/Contents/MacOS/Some
    

    此脚本是从这个仓库获取的。

  • create_changelog.py: 用于创建CHANGELOG的脚本,你可以在dist/目录中找到它。使用方法:

    python create_changelog.py -r 6.0.1 -v v6.0.0..6.0 -t bug-fix
    
  • debug_windows.py: 该脚本可用于找出PySide模块加载失败的原因,例如DLL缺失或DLL中缺少符号等错误。

    你可以将其视为Windows版本的ldd / LD_DEBUG

    在底层,它使用了cdb.exe命令行调试器和gflags.exe工具,这些工具随最新的Windows Kit一起安装。

    其目的是帮助开发人员调试在Windows上使用PySide导入时可能遇到的问题。用户应提供生成的日志文件。

    顺便说一下,它也可以用于任何Windows可执行文件,而不仅仅是Python。要使用它,只需运行:

    python debug_windows.py
    
  • missing_bindings.py: 该脚本用于比较PySide和PyQt在可用模块和类方面的状态。此内容显示在我们的wiki页面上,并可以如下使用:

    python missing_bindings.py --qt-version 6.0.1 -w all
    

注意

该脚本依赖于BeautifulSoup来解析内容并生成缺失绑定的列表。