diff --git a/.github/workflows/build-linux-image.yml b/.github/workflows/build-linux-image.yml index 4245cd2..26ead49 100644 --- a/.github/workflows/build-linux-image.yml +++ b/.github/workflows/build-linux-image.yml @@ -26,8 +26,9 @@ concurrency: cancel-in-progress: true env: - IMAGE_NAME: crossdesk/ubuntu22.04 - STACK_TAG: buildenv-cuda12.6.3-xmake3.0.9-rust1.92.0 + IMAGE_NAME: crossdesk/ubuntu20.04 + STACK_TAG: buildenv-cuda12.6.3-gcc10-cmake3.31.6-pipewire0.3.48-xmake3.0.9-rust1.92.0 + CMAKE_VERSION: 3.31.6 XMAKE_VERSION: 3.0.9 RUST_VERSION: 1.92.0 RUSTUP_VERSION: 1.28.2 @@ -44,11 +45,11 @@ jobs: - arch: amd64 platform: linux/amd64 runner: ubuntu-24.04 - base_image: nvidia/cuda:12.6.3-devel-ubuntu22.04 + base_image: nvidia/cuda:12.6.3-devel-ubuntu20.04 - arch: arm64 platform: linux/arm64 runner: ubuntu-24.04-arm - base_image: ubuntu:22.04 + base_image: ubuntu:20.04 steps: - name: Set candidate tag id: image @@ -86,6 +87,7 @@ jobs: sbom: false build-args: | BASE_IMAGE=${{ matrix.base_image }} + CMAKE_VERSION=${{ env.CMAKE_VERSION }} XMAKE_VERSION=${{ env.XMAKE_VERSION }} RUST_VERSION=${{ env.RUST_VERSION }} RUSTUP_VERSION=${{ env.RUSTUP_VERSION }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f89cd1f..2a5ccab 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,12 +29,12 @@ jobs: include: - arch: amd64 runner: ubuntu-24.04 - image: crossdesk/ubuntu22.04:buildenv-cuda12.6.3-xmake3.0.9-rust1.92.0 + image: crossdesk/ubuntu20.04:buildenv-cuda12.6.3-gcc10-cmake3.31.6-pipewire0.3.48-xmake3.0.9-rust1.92.0 package_script: ./scripts/linux/pkg_amd64.sh - arch: arm64 runner: ubuntu-24.04-arm - image: crossdesk/ubuntu22.04:buildenv-cuda12.6.3-xmake3.0.9-rust1.92.0 + image: crossdesk/ubuntu20.04:buildenv-cuda12.6.3-gcc10-cmake3.31.6-pipewire0.3.48-xmake3.0.9-rust1.92.0 package_script: ./scripts/linux/pkg_arm64.sh container: @@ -106,26 +106,30 @@ jobs: - name: Ensure Wayland build dependencies shell: bash run: | - if pkg-config --exists dbus-1 libdrm libpipewire-0.3 libspa-0.2; then + if pkg-config --exists dbus-1 libdrm && \ + test -f /opt/crossdesk-pipewire-sdk/include/pipewire-0.3/pipewire/pipewire.h && \ + test -f /opt/crossdesk-pipewire-sdk/include/spa-0.2/spa/param/video/format-utils.h; then exit 0 fi apt-get update apt-get install -y --no-install-recommends \ libdbus-1-dev \ - libdrm-dev \ - libpipewire-0.3-dev \ - libspa-0.2-dev + libdrm-dev rm -rf /var/lib/apt/lists/* - pkg-config --exists dbus-1 libdrm libpipewire-0.3 libspa-0.2 + install-crossdesk-pipewire-sdk + pkg-config --exists dbus-1 libdrm + test -f /opt/crossdesk-pipewire-sdk/include/pipewire-0.3/pipewire/pipewire.h + test -f /opt/crossdesk-pipewire-sdk/include/spa-0.2/spa/param/video/format-utils.h - name: Build CrossDesk env: CUDA_PATH: /usr/local/cuda XMAKE_GLOBALDIR: /data run: | - xmake f --CROSSDESK_VERSION=${LEGAL_VERSION} --USE_CUDA=true --USE_WAYLAND=true --root -y + xmake f --CROSSDESK_VERSION=${LEGAL_VERSION} --USE_CUDA=true --USE_WAYLAND=true \ + --cc=gcc-10 --cxx=g++-10 --root -y xmake b -vy --root crossdesk - name: Package @@ -133,13 +137,19 @@ jobs: chmod +x ${{ matrix.package_script }} ${{ matrix.package_script }} ${LEGAL_VERSION} - - name: Verify packaged Ubuntu 22.04 glibc baseline + - name: Verify Ubuntu 20.04 package dependency resolution + run: | + PACKAGE_FILE="${GITHUB_WORKSPACE}/crossdesk-linux-${{ matrix.arch }}-${LEGAL_VERSION}.deb" + apt-get update + apt-get install --simulate "${PACKAGE_FILE}" + + - name: Verify packaged Ubuntu 20.04 glibc baseline run: | PACKAGE_FILE="${GITHUB_WORKSPACE}/crossdesk-linux-${{ matrix.arch }}-${LEGAL_VERSION}.deb" VERIFY_DIR="${RUNNER_TEMP}/crossdesk-glibc-${{ matrix.arch }}" install -d "${VERIFY_DIR}" dpkg-deb --extract "${PACKAGE_FILE}" "${VERIFY_DIR}" - verify-crossdesk-glibc-baseline "${VERIFY_DIR}" 2.35 + verify-crossdesk-glibc-baseline "${VERIFY_DIR}" 2.31 - name: Upload artifact uses: actions/upload-artifact@v6 diff --git a/README.md b/README.md index d63e401..ed640d4 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ CrossDesk 是 [MiniRTC](https://github.com/kunkundi/minirtc.git) 实时音视频 |----------------|---------------------------| | **Windows** | Windows 10 及以上 (64 位) | | **macOS** | macOS Intel 15.0 及以上 ( 大于 14.0 小于 15.0 的版本可自行编译实现兼容 )
macOS Apple Silicon 14.0 及以上 | -| **Linux** | Ubuntu 22.04 及以上 ( 低版本可自行编译实现兼容 ) | +| **Linux** | Ubuntu 20.04 及以上 | ## 使用 @@ -80,27 +80,39 @@ Windows 安装包会自动打包 `crossdesk_service.exe` 和 `crossdesk_session_ 依赖: - [xmake](https://xmake.io/#/guide/installation) -- [cmake](https://cmake.org/download/) +- [cmake](https://cmake.org/download/) 3.21 及以上 ### Linux -Linux 构建目前支持 Ubuntu 22.04 及以上版本的 amd64 和 arm64。先安装基础编译依赖: +Linux 构建支持 Ubuntu 20.04 及以上版本的 amd64 和 arm64。发布安装包以 +Ubuntu 20.04/glibc 2.31 为兼容基线。先安装基础编译依赖: ```bash sudo apt-get update sudo apt-get install -y \ - git curl unzip build-essential cmake pkg-config binutils dpkg-dev \ + git curl unzip build-essential gcc-10 g++-10 python3-pip \ + pkg-config binutils dpkg-dev \ libx11-dev libxext-dev libxrender-dev libxft-dev libxrandr-dev \ libxinerama-dev libxcursor-dev libxi-dev libxfixes-dev libxv-dev \ libxtst-dev libxcb-randr0-dev libxcb-xtest0-dev libxcb-xinerama0-dev \ libxcb-shape0-dev libxcb-xkb-dev libxcb-xfixes0-dev libxcb-shm0-dev \ libasound2-dev libsndio-dev libpulse-dev + +# Ubuntu 20.04 自带的 CMake 3.16 不满足 Slint 1.17 的要求 +python3 -m pip install --user cmake==3.31.6 +export PATH="$HOME/.local/bin:$PATH" ``` +Ubuntu 20.04 默认的 GCC 9 缺少 Slint C++ API 所需的部分 C++20 标准库, +因此上述命令同时安装并在后续配置中指定 GCC 10。 + 需要启用 Wayland 捕获或 DRM 捕获时,再安装对应依赖: ```bash -sudo apt-get install -y libdbus-1-dev libpipewire-0.3-dev libdrm-dev +sudo apt-get install -y libdbus-1-dev libdrm-dev + +# Ubuntu 22.04 及以上也可以直接安装系统开发包 +# sudo apt-get install -y libpipewire-0.3-dev libspa-0.2-dev ``` 下载子模块并编译 Release 版本: @@ -112,7 +124,11 @@ cd crossdesk # 已经克隆过仓库时执行这一行 git submodule update --init --recursive -xmake f -m release --USE_CUDA=false -y +# Ubuntu 20.04 没有 PipeWire 0.3 开发包,安装仅用于编译的头文件 SDK。 +# 已安装发行版 PipeWire 0.3 开发包时可跳过此步骤。 +sudo ./docker/linux-build/install-pipewire-sdk.sh + +xmake f -m release --USE_CUDA=false --cc=gcc-10 --cxx=g++-10 -y xmake b -vy crossdesk ``` @@ -121,7 +137,8 @@ amd64 构建结果位于 `build/linux/x86_64/release/crossdesk`,arm64 构建 启用 Wayland 和 DRM 的配置示例: ```bash -xmake f -m release --USE_WAYLAND=true --USE_DRM=true --USE_CUDA=false -y +xmake f -m release --USE_WAYLAND=true --USE_DRM=true --USE_CUDA=false \ + --cc=gcc-10 --cxx=g++-10 -y xmake b -vy crossdesk ``` @@ -136,6 +153,8 @@ xmake b -vy crossdesk ``` 打包脚本会将 Slint 共享运行库安装到软件包私有目录 `/usr/lib/crossdesk`,无需用户另外安装 `libslint_cpp.so`。 +PipeWire 不属于强制运行时依赖:程序在运行时检测宿主系统的 PipeWire 0.3, +没有该运行库时仍可使用 X11(以及构建时启用的 DRM)捕获。 ### 通用编译选项 @@ -158,7 +177,7 @@ xmake r crossdesk ### 无 CUDA 环境下的开发支持 -对于**未安装 CUDA 环境的 Linux 开发者,如果希望编译后的成果物拥有硬件编解码能力**,这里提供了预配置的 [Ubuntu 22.04 Docker 镜像](https://hub.docker.com/r/crossdesk/ubuntu22.04)。该镜像内置必要的构建依赖,可在容器中开箱即用,无需额外配置即可直接编译项目。 +对于**未安装 CUDA 环境的 Linux 开发者,如果希望编译后的成果物拥有硬件编解码能力**,这里提供了预配置的 [Ubuntu 20.04 兼容构建镜像](https://hub.docker.com/r/crossdesk/ubuntu20.04)。该镜像内置必要的构建依赖,可生成兼容 glibc 2.31 的单一 Linux 安装包。 进入容器,下载工程后执行: ``` diff --git a/README_EN.md b/README_EN.md index 0e7dd17..cf8c81d 100644 --- a/README_EN.md +++ b/README_EN.md @@ -32,7 +32,7 @@ CrossDesk is an experimental application of [MiniRTC](https://github.com/kunkund |-----------|-----------------| | **Windows** | Windows 10 or later (64-bit) | | **macOS** | macOS Intel 15.0 or later *(versions between 14.0 and 15.0 can be built manually for compatibility)*
macOS Apple Silicon 14.0 or later | -| **Linux** | Ubuntu 22.04 or later *(older versions can be built manually for compatibility)* | +| **Linux** | Ubuntu 20.04 or later | ## Usage @@ -85,27 +85,41 @@ If the remote Windows service is not installed, not running, or temporarily unav Requirements: - [xmake](https://xmake.io/#/guide/installation) -- [cmake](https://cmake.org/download/) +- [cmake](https://cmake.org/download/) 3.21 or later ### Linux -Linux builds currently support Ubuntu 22.04 or later on amd64 and arm64. Install the base build dependencies first: +Linux builds support Ubuntu 20.04 or later on amd64 and arm64. Release packages +use Ubuntu 20.04/glibc 2.31 as their compatibility baseline. Install the base +build dependencies first: ```bash sudo apt-get update sudo apt-get install -y \ - git curl unzip build-essential cmake pkg-config binutils dpkg-dev \ + git curl unzip build-essential gcc-10 g++-10 python3-pip \ + pkg-config binutils dpkg-dev \ libx11-dev libxext-dev libxrender-dev libxft-dev libxrandr-dev \ libxinerama-dev libxcursor-dev libxi-dev libxfixes-dev libxv-dev \ libxtst-dev libxcb-randr0-dev libxcb-xtest0-dev libxcb-xinerama0-dev \ libxcb-shape0-dev libxcb-xkb-dev libxcb-xfixes0-dev libxcb-shm0-dev \ libasound2-dev libsndio-dev libpulse-dev + +# Ubuntu 20.04's CMake 3.16 is too old for Slint 1.17. +python3 -m pip install --user cmake==3.31.6 +export PATH="$HOME/.local/bin:$PATH" ``` +Ubuntu 20.04's default GCC 9 lacks parts of the C++20 standard library needed +by Slint's C++ API, so the commands above install GCC 10 and the configuration +below selects it explicitly. + Install the optional dependencies when Wayland capture or DRM capture is enabled: ```bash -sudo apt-get install -y libdbus-1-dev libpipewire-0.3-dev libdrm-dev +sudo apt-get install -y libdbus-1-dev libdrm-dev + +# Ubuntu 22.04 and later can alternatively use the distribution packages. +# sudo apt-get install -y libpipewire-0.3-dev libspa-0.2-dev ``` Clone the submodules and build a release binary: @@ -117,7 +131,12 @@ cd crossdesk # Run this when the repository has already been cloned git submodule update --init --recursive -xmake f -m release --USE_CUDA=false -y +# Ubuntu 20.04 has no PipeWire 0.3 development package. Install the +# header-only SDK used during compilation. Skip this when the distribution's +# PipeWire 0.3 development packages are already installed. +sudo ./docker/linux-build/install-pipewire-sdk.sh + +xmake f -m release --USE_CUDA=false --cc=gcc-10 --cxx=g++-10 -y xmake b -vy crossdesk ``` @@ -126,7 +145,8 @@ The amd64 binary is written to `build/linux/x86_64/release/crossdesk`; the arm64 Example configuration with Wayland and DRM capture enabled: ```bash -xmake f -m release --USE_WAYLAND=true --USE_DRM=true --USE_CUDA=false -y +xmake f -m release --USE_WAYLAND=true --USE_DRM=true --USE_CUDA=false \ + --cc=gcc-10 --cxx=g++-10 -y xmake b -vy crossdesk ``` @@ -141,6 +161,9 @@ Build a Debian package after compiling a release binary on the matching architec ``` The package scripts install the shared Slint runtime in the private `/usr/lib/crossdesk` directory, so users do not need to install `libslint_cpp.so` separately. +PipeWire is not a mandatory runtime dependency. CrossDesk detects the host's +PipeWire 0.3 runtime dynamically and can still use X11 capture (and DRM when +enabled at build time) when it is unavailable. ### Common build options @@ -163,8 +186,8 @@ xmake r crossdesk #### Development Without CUDA Environment -For **Linux developers who do not have a CUDA environment installed and want to enable hardware codec feature**, a preconfigured [Ubuntu 22.04 Docker image](https://hub.docker.com/r/crossdesk/ubuntu22.04) is provided. -This image comes with all required build dependencies and allows you to build the project directly inside the container without any additional setup. +For **Linux developers who do not have a CUDA environment installed and want to enable hardware codec feature**, a preconfigured [Ubuntu 20.04 compatibility build image](https://hub.docker.com/r/crossdesk/ubuntu20.04) is provided. +This image contains the required build dependencies and produces a single Linux package compatible with the glibc 2.31 baseline. After entering the container, download the project and run: ``` diff --git a/docker/linux-build/Dockerfile b/docker/linux-build/Dockerfile index a545dd2..c11e134 100644 --- a/docker/linux-build/Dockerfile +++ b/docker/linux-build/Dockerfile @@ -1,15 +1,16 @@ # syntax=docker/dockerfile:1.7 -ARG BASE_IMAGE=nvidia/cuda:12.6.3-devel-ubuntu22.04 +ARG BASE_IMAGE=nvidia/cuda:12.6.3-devel-ubuntu20.04 FROM ${BASE_IMAGE} ARG TARGETARCH +ARG CMAKE_VERSION=3.31.6 ARG XMAKE_VERSION=3.0.9 ARG RUST_VERSION=1.92.0 ARG RUSTUP_VERSION=1.28.2 LABEL org.opencontainers.image.title="CrossDesk Linux build environment" \ - org.opencontainers.image.description="Ubuntu 22.04 build environment for CrossDesk" \ + org.opencontainers.image.description="Ubuntu 20.04 compatibility build environment for CrossDesk" \ org.opencontainers.image.source="https://github.com/kunkundi/crossdesk" \ org.opencontainers.image.licenses="GPL-3.0-only" @@ -22,6 +23,8 @@ ENV DEBIAN_FRONTEND=noninteractive \ XMAKE_GLOBALDIR=/data \ XMAKE_ROOT=y \ CUDA_PATH=/usr/local/cuda \ + CC=/usr/bin/gcc-10 \ + CXX=/usr/bin/g++-10 \ PATH=/root/.local/bin:/opt/cargo/bin:/usr/local/bin:${PATH} SHELL ["/bin/bash", "-o", "pipefail", "-c"] @@ -35,13 +38,14 @@ RUN apt-get update \ build-essential \ ca-certificates \ ccache \ - cmake \ curl \ dbus \ dpkg-dev \ file \ flex \ gettext \ + gcc-10 \ + g++-10 \ git \ libasound2-dev \ libdbus-1-dev \ @@ -52,11 +56,9 @@ RUN apt-get update \ libfreetype6-dev \ libgl1-mesa-dev \ libmount-dev \ - libpipewire-0.3-dev \ libpulse-dev \ libreadline-dev \ libsndio-dev \ - libspa-0.2-dev \ libssl-dev \ libtool \ libx11-dev \ @@ -95,6 +97,22 @@ RUN apt-get update \ zlib1g-dev \ && rm -rf /var/lib/apt/lists/* +# Slint 1.17 requires CMake 3.21 or newer, while Ubuntu 20.04 provides 3.16. +# PyPI publishes pinned manylinux2014 wheels for both amd64 and arm64. +RUN python3 -m pip install --no-cache-dir "cmake==${CMAKE_VERSION}" \ + && cmake --version | grep -F "cmake version ${CMAKE_VERSION}" + +# Ubuntu 20.04 only ships PipeWire 0.2. Install the Ubuntu 22.04-era 0.3.48 +# headers as a build-only SDK. CrossDesk loads the host's PipeWire 0.3 runtime +# with dlopen(), so no PipeWire shared library is copied into release packages. +COPY docker/linux-build/install-pipewire-sdk.sh \ + /usr/local/bin/install-crossdesk-pipewire-sdk + +RUN chmod 0755 /usr/local/bin/install-crossdesk-pipewire-sdk \ + && install-crossdesk-pipewire-sdk \ + && grep -F "#define PW_MICRO 48" \ + /opt/crossdesk-pipewire-sdk/include/pipewire-0.3/pipewire/version.h + RUN export GITHUB_ACTIONS=true \ && curl -fsSL https://xmake.io/shget.text \ | bash -s -- "v${XMAKE_VERSION}" \ @@ -136,7 +154,8 @@ COPY submodules/minirtc/thirdparty ./submodules/minirtc/thirdparty # CrossDesk's exact dependency graph. Source files are intentionally excluded # from the Docker context; source-only changes therefore reuse this layer. RUN xmake repo -u --root \ - && xmake f -m release --USE_CUDA=true --USE_WAYLAND=true --root -y \ + && xmake f -m release --USE_CUDA=true --USE_WAYLAND=true \ + --cc=gcc-10 --cxx=g++-10 --root -y \ && rm -rf /data/.xmake/cache /tmp/crossdesk-dependencies \ && mkdir -p /workspace diff --git a/docker/linux-build/README.md b/docker/linux-build/README.md index 6a08774..b25e3e3 100644 --- a/docker/linux-build/README.md +++ b/docker/linux-build/README.md @@ -1,7 +1,8 @@ # CrossDesk Linux 构建镜像 -这个目录维护 CrossDesk 专用的 Ubuntu 22.04 构建环境。镜像包含 xmake、 -Rust、Linux 开发库(包括 D-Bus、DRM、PipeWire 和 SPA)以及根据项目 +这个目录维护 CrossDesk 专用的 Ubuntu 20.04 兼容构建环境。镜像包含 GCC 10、 +CMake 3.31、xmake、Rust、Linux 开发库(包括 D-Bus、DRM,以及仅用于编译的 +PipeWire 0.3/SPA 头文件 SDK)以及根据项目 `xmake.lua` 提前编译好的依赖。 ## 发布方式 @@ -11,14 +12,19 @@ Rust、Linux 开发库(包括 D-Bus、DRM、PipeWire 和 SPA)以及根据项 全部通过后再合并为同一个 multi-arch 镜像: ```text -crossdesk/ubuntu22.04:buildenv-cuda12.6.3-xmake3.0.9-rust1.92.0 +crossdesk/ubuntu20.04:buildenv-cuda12.6.3-gcc10-cmake3.31.6-pipewire0.3.48-xmake3.0.9-rust1.92.0 ``` Docker 会根据运行机器自动选择正确架构。amd64 变体以 -`nvidia/cuda:12.6.3-devel-ubuntu22.04` 为基础;arm64 变体不包含当前构建 -用不到的 CUDA SDK。两个变体都使用 Ubuntu 22.04/glibc 2.35。 -因此该镜像生成的 Linux 安装包最低支持 Ubuntu 22.04,不再保证兼容 -Ubuntu 20.04。 +`nvidia/cuda:12.6.3-devel-ubuntu20.04` 为基础;arm64 变体不包含当前构建 +用不到的 CUDA SDK。两个变体都使用 Ubuntu 20.04/glibc 2.31,因此生成的 +单一 Linux 安装包可运行在 Ubuntu 20.04 及更高版本。 + +Ubuntu 20.04 仓库只提供 PipeWire 0.2。镜像通过 +`install-pipewire-sdk.sh` 安装固定版本的 PipeWire 0.3.48/SPA 头文件,但不 +安装或打包 PipeWire 动态库。CrossDesk 在运行时通过 `dlopen()` 使用宿主系统 +提供的 PipeWire 0.3:Ubuntu 20.04 没有该运行库时仍可使用 X11(以及构建时 +启用的 DRM),Ubuntu 22.04 及更高版本则可使用 Wayland 捕获。 每次成功发布还会生成 `sha-<完整提交 SHA>`,用于精确回滚;`latest` 和上面的 工具链版本 tag 只会在两个架构都验证成功后更新。 @@ -27,7 +33,7 @@ Ubuntu 20.04。 在仓库的 Actions secrets 中配置: -- `DOCKERHUB_USERNAME`:有权推送 `crossdesk/ubuntu22.04` 的 Docker Hub 用户名 +- `DOCKERHUB_USERNAME`:有权推送 `crossdesk/ubuntu20.04` 的 Docker Hub 用户名 - `DOCKERHUB_TOKEN`:该用户的 Docker Hub access token 工作流文件进入默认分支后,也可以从 Actions 页面手动运行。为了避免首次发布 diff --git a/docker/linux-build/install-pipewire-sdk.sh b/docker/linux-build/install-pipewire-sdk.sh new file mode 100755 index 0000000..964f421 --- /dev/null +++ b/docker/linux-build/install-pipewire-sdk.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +set -euo pipefail + +PIPEWIRE_VERSION="0.3.48" +PIPEWIRE_ARCHIVE_SHA256="0d218be86b3d2b548c06259c47ad8d110ee1c09f071e17c4393eeef5c880fa6f" +INSTALL_PREFIX="${1:-/opt/crossdesk-pipewire-sdk}" +IFS='.' read -r PIPEWIRE_VERSION_MAJOR PIPEWIRE_VERSION_MINOR \ + PIPEWIRE_VERSION_MICRO <<< "${PIPEWIRE_VERSION}" + +if [[ "${INSTALL_PREFIX}" != /* ]]; then + echo "Install prefix must be an absolute path: ${INSTALL_PREFIX}" >&2 + exit 2 +fi + +WORK_DIR="$(mktemp -d "${TMPDIR:-/tmp}/crossdesk-pipewire-sdk.XXXXXX")" +trap 'rm -rf "${WORK_DIR}"' EXIT + +ARCHIVE_PATH="${WORK_DIR}/pipewire-${PIPEWIRE_VERSION}.tar.gz" +SOURCE_DIR="${WORK_DIR}/pipewire-${PIPEWIRE_VERSION}" +ARCHIVE_URL="https://gitlab.freedesktop.org/pipewire/pipewire/-/archive/${PIPEWIRE_VERSION}/pipewire-${PIPEWIRE_VERSION}.tar.gz" + +curl --proto '=https' --tlsv1.2 --fail --silent --show-error --location \ + --retry 3 "${ARCHIVE_URL}" -o "${ARCHIVE_PATH}" +echo "${PIPEWIRE_ARCHIVE_SHA256} ${ARCHIVE_PATH}" | sha256sum --check - +tar -xzf "${ARCHIVE_PATH}" -C "${WORK_DIR}" + +PIPEWIRE_INCLUDE_DIR="${INSTALL_PREFIX}/include/pipewire-0.3/pipewire" +SPA_INCLUDE_DIR="${INSTALL_PREFIX}/include/spa-0.2/spa" + +while IFS= read -r -d '' header_path; do + relative_path="${header_path#${SOURCE_DIR}/src/pipewire/}" + install -D -m 0644 "${header_path}" \ + "${PIPEWIRE_INCLUDE_DIR}/${relative_path}" +done < <(find "${SOURCE_DIR}/src/pipewire" -type f -name '*.h' -print0) + +while IFS= read -r -d '' header_path; do + relative_path="${header_path#${SOURCE_DIR}/spa/include/spa/}" + install -D -m 0644 "${header_path}" \ + "${SPA_INCLUDE_DIR}/${relative_path}" +done < <(find "${SOURCE_DIR}/spa/include/spa" -type f -name '*.h' -print0) + +sed \ + -e "s/@PIPEWIRE_VERSION_MAJOR@/${PIPEWIRE_VERSION_MAJOR}/g" \ + -e "s/@PIPEWIRE_VERSION_MINOR@/${PIPEWIRE_VERSION_MINOR}/g" \ + -e "s/@PIPEWIRE_VERSION_MICRO@/${PIPEWIRE_VERSION_MICRO}/g" \ + -e 's/@PIPEWIRE_API_VERSION@/"0.3"/g' \ + "${SOURCE_DIR}/src/pipewire/version.h.in" \ + > "${PIPEWIRE_INCLUDE_DIR}/version.h" +chmod 0644 "${PIPEWIRE_INCLUDE_DIR}/version.h" + +test -f "${PIPEWIRE_INCLUDE_DIR}/pipewire.h" +test -f "${PIPEWIRE_INCLUDE_DIR}/version.h" +test -f "${SPA_INCLUDE_DIR}/param/video/format-utils.h" + +echo "Installed PipeWire ${PIPEWIRE_VERSION} header SDK under ${INSTALL_PREFIX}" diff --git a/docker/linux-build/verify-build-image.sh b/docker/linux-build/verify-build-image.sh index d7adc29..fc8ff5b 100644 --- a/docker/linux-build/verify-build-image.sh +++ b/docker/linux-build/verify-build-image.sh @@ -2,19 +2,22 @@ set -euo pipefail EXPECTED_ARCH="${EXPECTED_ARCH:-}" +EXPECTED_CMAKE_VERSION="${EXPECTED_CMAKE_VERSION:-3.31.6}" EXPECTED_XMAKE_VERSION="${EXPECTED_XMAKE_VERSION:-3.0.9}" EXPECTED_RUST_VERSION="${EXPECTED_RUST_VERSION:-1.92.0}" +BUILD_CC="${CC:-/usr/bin/gcc-10}" +BUILD_CXX="${CXX:-/usr/bin/g++-10}" # shellcheck disable=SC1091 source /etc/os-release -if [[ "${ID}" != "ubuntu" || "${VERSION_ID}" != "22.04" ]]; then - echo "Expected Ubuntu 22.04, found ${ID:-unknown} ${VERSION_ID:-unknown}" >&2 +if [[ "${ID}" != "ubuntu" || "${VERSION_ID}" != "20.04" ]]; then + echo "Expected Ubuntu 20.04, found ${ID:-unknown} ${VERSION_ID:-unknown}" >&2 exit 1 fi GLIBC_VERSION="$(getconf GNU_LIBC_VERSION | awk '{print $2}')" -if [[ "${GLIBC_VERSION}" != "2.35" ]]; then - echo "Expected glibc 2.35, found ${GLIBC_VERSION}" >&2 +if [[ "${GLIBC_VERSION}" != "2.31" ]]; then + echo "Expected glibc 2.31, found ${GLIBC_VERSION}" >&2 exit 1 fi @@ -28,13 +31,23 @@ XMAKE_VERSION_OUTPUT="$(xmake --version 2>&1)" grep -F "v${EXPECTED_XMAKE_VERSION}" <<<"${XMAKE_VERSION_OUTPUT}" >/dev/null rustc --version | grep -F "rustc ${EXPECTED_RUST_VERSION}" >/dev/null cargo --version >/dev/null -cmake --version >/dev/null -g++ --version >/dev/null +cmake --version | grep -F "cmake version ${EXPECTED_CMAKE_VERSION}" >/dev/null +"${BUILD_CC}" --version | grep -F 'gcc-10' >/dev/null +"${BUILD_CXX}" --version | grep -F 'g++-10' >/dev/null +printf '%s\n' \ + '#include ' \ + '#include ' \ + 'template concept TestConcept = true;' \ + 'int main() {' \ + ' int value = 0;' \ + ' std::span values(&value, 1);' \ + ' static_assert(TestConcept);' \ + ' return values.empty();' \ + '}' \ + | "${BUILD_CXX}" -std=c++20 -fsyntax-only -x c++ - for pkg_config_package in \ dbus-1 \ libdrm \ - libpipewire-0.3 \ - libspa-0.2 \ xft; do if ! pkg-config --exists "${pkg_config_package}"; then echo "Required pkg-config package is missing: ${pkg_config_package}" >&2 @@ -42,6 +55,25 @@ for pkg_config_package in \ fi done +for sdk_header in \ + /opt/crossdesk-pipewire-sdk/include/pipewire-0.3/pipewire/pipewire.h \ + /opt/crossdesk-pipewire-sdk/include/pipewire-0.3/pipewire/version.h \ + /opt/crossdesk-pipewire-sdk/include/spa-0.2/spa/param/video/format-utils.h; do + if [[ ! -f "${sdk_header}" ]]; then + echo "Required PipeWire build SDK header is missing: ${sdk_header}" >&2 + exit 1 + fi +done + +printf '%s\n' \ + '#include ' \ + '#include ' \ + 'static_assert(PW_CHECK_VERSION(0, 3, 48));' \ + 'int main() { return 0; }' \ + | "${BUILD_CXX}" -std=c++17 -fsyntax-only -x c++ \ + -I/opt/crossdesk-pipewire-sdk/include/pipewire-0.3 \ + -I/opt/crossdesk-pipewire-sdk/include/spa-0.2 - + for package_path in \ "s/slint" \ "l/libdatachannel" \ diff --git a/docker/linux-build/verify-glibc-baseline.sh b/docker/linux-build/verify-glibc-baseline.sh index 17ffd64..8a53167 100644 --- a/docker/linux-build/verify-glibc-baseline.sh +++ b/docker/linux-build/verify-glibc-baseline.sh @@ -7,7 +7,7 @@ if [[ $# -lt 1 || $# -gt 2 ]]; then fi INPUT_PATH="$1" -MAXIMUM_VERSION="${2:-2.35}" +MAXIMUM_VERSION="${2:-2.31}" verify_elf() { local elf_file="$1" diff --git a/scripts/linux/package_deb.sh b/scripts/linux/package_deb.sh index 9b804cd..775dfb3 100755 --- a/scripts/linux/package_deb.sh +++ b/scripts/linux/package_deb.sh @@ -104,6 +104,15 @@ OUTPUT_FILE="$PROJECT_ROOT/${PKG_NAME}-linux-${DEBIAN_ARCH}-${APP_VERSION}.deb" install -d "$DEBIAN_DIR" "$BIN_DIR" "$PRIVATE_DIR" "$DESKTOP_DIR" install -m 0755 "$BUILD_BINARY" "$PRIVATE_DIR/crossdesk-bin" +# PipeWire is deliberately optional. The Wayland capturer resolves PipeWire +# 0.3 with dlopen() so the same package can run on Ubuntu 20.04 without the +# runtime while using the host runtime on newer Ubuntu releases. +if readelf -d "$BUILD_BINARY" \ + | grep -qE 'Shared library: \[libpipewire-0\.3\.so'; then + echo "CrossDesk must not link directly to the optional PipeWire runtime" >&2 + exit 1 +fi + # Slint is intentionally built as a shared library. Keep that runtime private # to CrossDesk instead of relying on a non-existent distribution package. SLINT_NEEDED="$(readelf -d "$BUILD_BINARY" | sed -n \ @@ -147,7 +156,7 @@ Version: $DEB_VERSION Architecture: $DEBIAN_ARCH Maintainer: $MAINTAINER Description: $DESCRIPTION -Depends: libc6 (>= 2.35), libstdc++6 (>= 9), libx11-6, libxext6, +Depends: libc6 (>= 2.31), libstdc++6 (>= 10), libx11-6, libxext6, libxrender1, libxft2, libxrandr2, libxfixes3, libxcb1, libxcb-randr0, libxcb-xtest0, libxcb-xinerama0, libxcb-shape0, libxcb-xkb1, libxcb-xfixes0, libxv1, libxtst6, $ALSA_RUNTIME_DEP, libsndio7.0, diff --git a/xmake/platform.lua b/xmake/platform.lua index 7280391..cbf8150 100644 --- a/xmake/platform.lua +++ b/xmake/platform.lua @@ -64,10 +64,12 @@ function setup_platform_settings() "/usr/local/include/pipewire-0.3", "/usr/include/pipewire", "/usr/local/include/pipewire", + "/opt/crossdesk-pipewire-sdk/include/pipewire-0.3", "/usr/include/spa-0.2", "/usr/local/include/spa-0.2", "/usr/include/spa", - "/usr/local/include/spa" + "/usr/local/include/spa", + "/opt/crossdesk-pipewire-sdk/include/spa-0.2" }, {system = true}) for _, include_dir in ipairs(collect_dbus_arch_include_dirs()) do add_includedirs(include_dir, {system = true})