From 5e556681738a1fa918dc9f0bf5879ace2e603e12 Mon Sep 17 00:00:00 2001 From: Nico Miguelino Date: Tue, 17 Sep 2024 13:32:56 -0700 Subject: [PATCH] Create a pipeline for building an x86-compatible WebView (#2056) --- webview/Dockerfile.x86 | 98 ++++++++++++++++++++++++++ webview/README.md | 22 +++++- webview/build_x86.sh | 124 +++++++++++++++++++++++++++++++++ webview/docker-compose.x86.yml | 14 ++++ 4 files changed, 256 insertions(+), 2 deletions(-) create mode 100644 webview/Dockerfile.x86 create mode 100755 webview/build_x86.sh create mode 100644 webview/docker-compose.x86.yml diff --git a/webview/Dockerfile.x86 b/webview/Dockerfile.x86 new file mode 100644 index 000000000..e8b21cefe --- /dev/null +++ b/webview/Dockerfile.x86 @@ -0,0 +1,98 @@ +FROM debian:bookworm + +# Avoid interactive prompts during package installation +ENV DEBIAN_FRONTEND=noninteractive + +# TODO: Remove unused packages. +RUN { \ + set -e && \ + apt-get update && apt-get install -y \ + autoconf \ + automake \ + bison \ + build-essential \ + ccache \ + cmake \ + flex \ + freeglut3-dev \ + gawk \ + gcc \ + gettext \ + git \ + gperf \ + less \ + libatspi2.0-dev \ + libbsd-dev \ + libbz2-dev \ + libclang-dev \ + libcups2-dev \ + libdb-dev \ + libdrm-dev \ + libexpat1-dev \ + libffi-dev \ + libfontconfig1-dev \ + libfreetype6-dev \ + libgdbm-dev \ + libgl1-mesa-dev \ + libglu1-mesa-dev \ + libgmp-dev \ + libisl-dev \ + liblzma-dev \ + libmpc-dev \ + libmpfr-dev \ + libncurses5-dev \ + libnss3-dev \ + libreadline-dev \ + libsqlite3-dev \ + libssl-dev \ + libtool \ + libx11-dev \ + libx11-xcb-dev \ + libxcb-glx0-dev \ + libxcb-icccm4-dev \ + libxcb-image0-dev \ + libxcb-keysyms1-dev \ + libxcb-randr0-dev \ + libxcb-render-util0-dev \ + libxcb-shape0-dev \ + libxcb-shm0-dev \ + libxcb-sync-dev \ + libxcb-util-dev \ + libxcb-xfixes0-dev \ + libxcb-xinerama0-dev \ + libxcb-xkb-dev \ + libxcb1-dev \ + libxext-dev \ + libxfixes-dev \ + libxi-dev \ + libxkbcommon-dev \ + libxkbcommon-x11-dev \ + libxrender-dev \ + m4 \ + make \ + ninja-build \ + nodejs \ + npm \ + patch \ + perl \ + pkg-config \ + python3 \ + python3-pip \ + rsync \ + sed \ + texinfo \ + wget \ + zlib1g-dev && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/*; \ +} 2>&1 | tee -a /build.log + +RUN pip install --upgrade pip --break-system-packages +RUN pip install html5lib --break-system-packages + +RUN mkdir -p /scripts /src + +# Set the working directory to /build +WORKDIR /build + +CMD ["bash"] diff --git a/webview/README.md b/webview/README.md index 48a9a039d..4b1afdc90 100644 --- a/webview/README.md +++ b/webview/README.md @@ -1,7 +1,9 @@ -## Building QT +## Building Qt and WebView **Warning:** To build this, you need **very** beefy hardware. We are building this on a VM with 32 vCPUs and 128GB RAM. If you're trying to build it locally, you likely need to tweak [MAKE_CORES](https://github.com/Screenly/screenly-ose/blob/master/webview/build_qt5.sh#L12) to something lower, but you would still need a powerful workstation (32GB RAM minimum) to make this build. +### Building for Raspberry Pi + Since our entire build environment resides inside a Docker container, you don't need to install any packages on the host system. Everything is confined to the Docker image. Do however note that as of this writing, the multi-platform support is still in beta so, you need to enable this. Instructions for how to get started with multi-platform builds can be found [here](https://medium.com/@artur.klauser/building-multi-architecture-docker-images-with-buildx-27d80f7e2408). ```bash @@ -42,7 +44,7 @@ $ docker rm qt-builder-instance You can learn more about this process in the blog post [Compiling Qt with Docker multi-stage and multi-platform](https://www.docker.com/blog/compiling-qt-with-docker-multi-stage-and-multi-platform/). -### Build Arguments +#### Build Arguments You can append the following environment variables to configure the build process: @@ -50,6 +52,22 @@ You can append the following environment variables to configure the build proces * `BUILD_WEBVIEW`: Set to `0` to disable the build of ScreenlyWebView. * `TARGET`: Specify a particular target (such as `pi3` or `pi4`) instead of all existing boards. +### Building for x86 + +```bash +$ cd webview +$ docker compose -f docker-compose.x86.yml up -d --build +$ docker compose -f docker-compose.x86.yml exec builder /webview/build_x86.sh +``` + +The resulting files will be placed in `~/tmp-x86/qt-build/release`. + +When you're done, you can stop and remove the container with the following commands: + +```bash +docker compose -f docker-compose.x86.yml down +``` + ## Usage DBus is used for communication. diff --git a/webview/build_x86.sh b/webview/build_x86.sh new file mode 100755 index 000000000..7bb5b4594 --- /dev/null +++ b/webview/build_x86.sh @@ -0,0 +1,124 @@ +#!/bin/bash + +set -euo pipefail + + +# Enable script debugging if the DEBUG environment variable is set and non-zero. +if [ "${DEBUG:-0}" -ne 0 ]; then + set -x +fi + +CORE_COUNT="$(expr $(nproc) - 2)" + +DEBIAN_VERSION='bookworm' + +QT_MAJOR='6' +QT_MINOR='6' +QT_PATCH='3' +QT_VERSION="${QT_MAJOR}.${QT_MINOR}.${QT_PATCH}" +QT6_HOST_STAGING_PATH="/usr/local/qt6" + +function install_qt() { + QT_RELEASES_URL="https://download.qt.io/official_releases/qt" + QT_DOWNLOAD_BASE_URL="${QT_RELEASES_URL}/${QT_MAJOR}.${QT_MINOR}/${QT_VERSION}/submodules" + QT_ARCHIVE_FILES=( + "qtbase-everywhere-src-${QT_VERSION}.tar.xz" + "qtshadertools-everywhere-src-${QT_VERSION}.tar.xz" + "qtdeclarative-everywhere-src-${QT_VERSION}.tar.xz" + "qtwebengine-everywhere-src-${QT_VERSION}.tar.xz" + ) + QT6_DIR="/build/qt6" + QT6_SRC_PATH="${QT6_DIR}/src" + QT6_HOST_BUILD_PATH="${QT6_DIR}/host-build" + + cd /build + mkdir -p qt6 qt6/host-build qt6/src /usr/local/qt6 + + cd ${QT6_SRC_PATH} + + for QT_ARCHIVE_FILE in "${QT_ARCHIVE_FILES[@]}"; do + if [ ! -f "${QT_ARCHIVE_FILE}" ]; then + wget "${QT_DOWNLOAD_BASE_URL}/${QT_ARCHIVE_FILE}" + else + echo "File ${QT_ARCHIVE_FILE} already exists. Skipping download..." + fi + done + + cd ${QT6_HOST_BUILD_PATH} + + for QT_ARCHIVE_FILE in "${QT_ARCHIVE_FILES[@]}"; do + tar xf ${QT6_SRC_PATH}/${QT_ARCHIVE_FILE} + done + + echo "Compile Qt Base for the Host" + cd ${QT6_HOST_BUILD_PATH}/qtbase-everywhere-src-${QT_VERSION} + cmake -GNinja -DCMAKE_BUILD_TYPE=Release \ + -DQT_BUILD_EXAMPLES=OFF \ + -DQT_BUILD_TESTS=OFF \ + -DQT_USE_CCACHE=ON \ + -DCMAKE_INSTALL_PREFIX=${QT6_HOST_STAGING_PATH} + cmake --build . --parallel "${CORE_COUNT}" + cmake --install . + + echo "Compile Qt Shader Tools for the Host" + cd ${QT6_HOST_BUILD_PATH}/qtshadertools-everywhere-src-${QT_VERSION} + ${QT6_HOST_STAGING_PATH}/bin/qt-configure-module . + cmake --build . --parallel "${CORE_COUNT}" + cmake --install . + + echo "Compile Qt Declarative for the Host" + cd ${QT6_HOST_BUILD_PATH}/qtdeclarative-everywhere-src-${QT_VERSION} + ${QT6_HOST_STAGING_PATH}/bin/qt-configure-module . + cmake --build . --parallel "${CORE_COUNT}" + cmake --install . + + echo "Compile Qt WebEngine for host" + cd ${QT6_HOST_BUILD_PATH}/qtwebengine-everywhere-src-${QT_VERSION} + ${QT6_HOST_STAGING_PATH}/bin/qt-configure-module . + cmake --build . --parallel "${CORE_COUNT}" + cmake --install . + + echo "Compilation is finished" +} + +function create_qt_archive() { + local ARCHIVE_NAME="qt${QT_MAJOR}-${QT_VERSION}-${DEBIAN_VERSION}-x86.tar.gz" + local ARCHIVE_DESTINATION="/build/release/${ARCHIVE_NAME}" + + cd /build + mkdir -p release && cd release + + cd /usr/local + tar cfz ${ARCHIVE_DESTINATION} qt6 + cd /build/release + sha256sum ${ARCHIVE_NAME} > ${ARCHIVE_DESTINATION}.sha256 +} + +function create_webview_archive() { + local ARCHIVE_NAME="webview-${QT_VERSION}-${DEBIAN_VERSION}-x86-$GIT_HASH.tar.gz" + local ARCHIVE_DESTINATION="/build/release/${ARCHIVE_NAME}" + + cp -rf /webview /build + cd /build/webview + ${QT6_HOST_STAGING_PATH}/bin/qmake + make -j${CORE_COUNT} + make install + + mkdir -p fakeroot/bin fakeroot/share/ScreenlyWebview + mv ScreenlyWebview fakeroot/bin/ + cp -rf /webview/res fakeroot/share/ScreenlyWebview/ + + cd fakeroot + + tar cfz ${ARCHIVE_DESTINATION} . + cd /build/release + sha256sum ${ARCHIVE_NAME} > ${ARCHIVE_DESTINATION}.sha256 +} + +function main() { + install_qt + create_qt_archive + create_webview_archive +} + +main diff --git a/webview/docker-compose.x86.yml b/webview/docker-compose.x86.yml new file mode 100644 index 000000000..19b1944a2 --- /dev/null +++ b/webview/docker-compose.x86.yml @@ -0,0 +1,14 @@ +services: + builder: + build: + context: . + dockerfile: Dockerfile.x86 + environment: + - GIT_HASH=${GIT_HASH} + stdin_open: true + tty: true + volumes: + - "~/tmp-x86/build:/build:Z" + - "~/tmp-x86/usr/local/qt6:/usr/local/qt6:Z" + - "./:/webview:ro" + - "./build_x86.sh:/scripts/build_x86.sh"