diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1bba99e..38153c3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -6,12 +6,30 @@ jobs: build-and-test: strategy: matrix: - ARCH: [x86_64, i386, aarch64, armhf] - UPDATE: ["1"] + include: + # regular builds: + - ARCH: x86_64 + BUILD_TYPE: appimage + RUNS_ON: ubuntu-24.04 + - ARCH: i386 + BUILD_TYPE: appimage + RUNS_ON: ubuntu-24.04 + - ARCH: aarch64 + BUILD_TYPE: appimage + RUNS_ON: ubuntu-24.04-arm + - ARCH: armhf + BUILD_TYPE: appimage + RUNS_ON: ubuntu-24.04-arm + + # test build + - ARCH: x86_64 + BUILD_TYPE: coverage + RUNS_ON: ubuntu-24.04 + fail-fast: false - name: ${{ matrix.ARCH }} - runs-on: ubuntu-latest + name: ${{ matrix.ARCH }} ${{ matrix.BUILD_TYPE }} + runs-on: ${{ matrix.RUNS_ON }} env: ARCH: ${{ matrix.ARCH }} @@ -20,30 +38,27 @@ jobs: steps: # check out once git command is available - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: recursive - - name: Set up QEMU integration for Docker - run: docker run --rm --privileged multiarch/qemu-user-static --reset -p yes - - name: Build and test AppImage run: bash ci/build-in-docker.sh - name: Archive artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: AppImage ${{ matrix.ARCH }} + name: AppImage ${{ matrix.ARCH }}${{ matrix.BUILD_TYPE }} path: linuxdeploy-plugin-qt-${{ matrix.ARCH }}.AppImage* upload: name: Create release and upload artifacts needs: - build-and-test - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - name: Download artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 - name: Inspect directory after downloading artifacts run: ls -alFR - name: Create release and upload artifacts @@ -52,4 +67,4 @@ jobs: run: | wget -q https://github.com/TheAssassin/pyuploadtool/releases/download/continuous/pyuploadtool-x86_64.AppImage chmod +x pyuploadtool-x86_64.AppImage - ./pyuploadtool-x86_64.AppImage **/linuxdeploy-plugin-qt*.AppImage* + ./pyuploadtool-x86_64.AppImage **/linuxdeploy*.AppImage* diff --git a/CMakeLists.txt b/CMakeLists.txt index 108ef11..1294ab1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,7 @@ find_package(nlohmann_json) if(NOT nlohmann_json_FOUND) message(STATUS "nlohmann_json not found on system, fetching from GitHub") + include(FetchContent) FetchContent_Declare( nlohmann_json GIT_REPOSITORY https://github.com/nlohmann/json @@ -26,8 +27,6 @@ if(NOT nlohmann_json_FOUND) ) FetchContent_MakeAvailable(nlohmann_json) - - add_library(nlohmann_json::nlohmann_json ALIAS nlohmann_json) endif() add_subdirectory(lib) diff --git a/README.md b/README.md index 9780f80..7d1a67c 100644 --- a/README.md +++ b/README.md @@ -56,10 +56,12 @@ Just like all linuxdeploy plugins, the Qt plugin's behavior can be configured so **Qt specific:** - `$QMAKE=/path/to/my/qmake`: use another `qmake` binary to detect paths of plugins and other resources (usually doesn't need to be set manually, most Qt environments ship scripts changing `$PATH`) -- `$EXTRA_QT_PLUGINS=pluginA;pluginB`: Plugins to deploy even if not found automatically by linuxdeploy-plugin-qt - - example: `EXTRA_QT_PLUGINS=svg;` if you want to use the module [QtSvg](https://doc.qt.io/qt-5/qtsvg-index.html) +- `$EXTRA_QT_MODULES=moduleA;moduleB`: Modules to deploy even if not found automatically by linuxdeploy-plugin-qt + - Example: `EXTRA_QT_MODULES=svg;` if you want to use the module [QtSvg](https://doc.qt.io/qt-5/qtsvg-index.html) + - To support Wayland, add `waylandcompositor` to this variable - `$EXTRA_PLATFORM_PLUGINS=platformA;platformB`: Platforms to deploy in addition to `libqxcb.so`. Platform must be available from `QT_INSTALL_PLUGINS/platforms`. + - To support Wayland, add `libqwayland-egl.so;libqwayland-generic.so` QML related: -- `$QML_SOURCES_PATHS`: directory containing the application's QML files — useful/needed if QML files are "baked" into the binaries. `$QT_INSTALL_QML` is prepended to this list internally. +- `$QML_SOURCES_PATHS`: directory containing the application's QML files — useful/needed if QML files are "baked" into the binaries. linuxdeploy-plugin-qt will look for all imported QML modules and include them. `$QT_INSTALL_QML` is prepended to this list internally. - `$QML_MODULES_PATHS`: extra directories containing imported QML files (normally doesn't need to be specified). diff --git a/ci/build-in-docker.sh b/ci/build-in-docker.sh old mode 100644 new mode 100755 index a7f7d9f..ae36b55 --- a/ci/build-in-docker.sh +++ b/ci/build-in-docker.sh @@ -18,7 +18,7 @@ error() { log_message 1 "[error] $*" } -if [[ "$ARCH" == "" ]]; then +if [[ "${ARCH:-}" == "" ]]; then error "Usage: env ARCH=... bash $0" exit 2 fi @@ -29,16 +29,16 @@ this_dir="$(readlink -f "$(dirname "${BASH_SOURCE[0]}")")" case "$ARCH" in x86_64) - docker_arch=amd64 + docker_platform=linux/amd64 ;; i386) - docker_arch=i386 + docker_platform=linux/386 ;; armhf) - docker_arch=arm32v7 + docker_platform=linux/arm/v7 ;; aarch64) - docker_arch=arm64v8 + docker_platform=linux/arm64/v8 ;; *) echo "Unsupported \$ARCH: $ARCH" @@ -49,7 +49,7 @@ esac # first, we need to build the image # we always attempt to build it, it will only be rebuilt if Docker detects changes # optionally, we'll pull the base image beforehand -info "Building Docker image for $ARCH (Docker arch: $docker_arch)" +info "Building Docker image for $ARCH (Docker platform: $docker_platform)" build_args=() if [[ "${UPDATE:-}" == "" ]]; then @@ -58,11 +58,11 @@ else build_args+=("--pull") fi -docker_image=linuxdeploy-plugin-qt-build:"$ARCH" +docker_image=linuxdeploy-plugin-qt-build docker build \ + --platform "$docker_platform" \ --build-arg ARCH="$ARCH" \ - --build-arg docker_arch="$docker_arch" \ "${build_args[@]}" \ -t "$docker_image" \ "$this_dir"/docker @@ -104,10 +104,12 @@ run_in_docker() { # b) allow the build scripts to "mv" the binaries into the /out directory docker run \ --rm \ + --platform "$docker_platform" \ -i \ --init \ - -e GITHUB_RUN_NUMBER \ -e ARCH \ + -e GITHUB_RUN_NUMBER \ + -e USE_STATIC_RUNTIME \ -e CI \ --user "$uid" \ "${docker_args[@]}" \ @@ -117,5 +119,10 @@ run_in_docker() { "$@" } +filename_suffix= +if [[ "${USE_STATIC_RUNTIME:-}" != "" ]]; then + filename_suffix="-static" +fi + run_in_docker bash ci/build.sh -run_in_docker bash ci/test.sh linuxdeploy-plugin-qt-"$ARCH".AppImage +run_in_docker bash ci/test.sh linuxdeploy-plugin-qt"$filename_suffix"-"$ARCH".AppImage diff --git a/ci/build.sh b/ci/build.sh index c29edf8..103d555 100755 --- a/ci/build.sh +++ b/ci/build.sh @@ -43,6 +43,17 @@ patchelf_path="$(which patchelf)" strip_path="$(which strip)" export UPD_INFO="gh-releases-zsync|linuxdeploy|linuxdeploy-plugin-qt|continuous|linuxdeploy-plugin-qt-$ARCH.AppImage" +export OUTPUT="linuxdeploy-plugin-qt-$ARCH.AppImage" + +# special set of builds using a different experimental runtime, used for testing purposes +if [[ "${USE_STATIC_RUNTIME:-}" != "" ]]; then + custom_runtime_url="https://github.com/AppImage/type2-runtime/releases/download/continuous/runtime-$ARCH" + wget "$custom_runtime_url" + runtime_filename="$(echo "$custom_runtime_url" | rev | cut -d/ -f1 | rev)" + LDAI_RUNTIME_FILE="$(readlink -f "$runtime_filename")" + export LDAI_RUNTIME_FILE + export OUTPUT="linuxdeploy-plugin-qt-static-$ARCH.AppImage" +fi wget "https://github.com/TheAssassin/linuxdeploy/releases/download/continuous/linuxdeploy-$ARCH.AppImage" # qemu is not happy about the AppImage type 2 magic bytes, so we need to "fix" that @@ -56,4 +67,4 @@ chmod +x linuxdeploy*.AppImage -e "$strip_path" \ --output appimage -mv linuxdeploy-plugin-qt-"$ARCH".AppImage* "$OLD_CWD"/ +mv "$OUTPUT"* "$OLD_CWD"/ diff --git a/ci/docker/Dockerfile b/ci/docker/Dockerfile index 143dfcf..0cc86b4 100644 --- a/ci/docker/Dockerfile +++ b/ci/docker/Dockerfile @@ -3,18 +3,12 @@ # needs to be re-run in CI every time as we cannot store auto-built Docker images due to GitHub's strict quota # it will save a lot of time in local development environments, though -ARG docker_arch - # we'll just use Debian as a base image for now, mainly because it produces less headache than Ubuntu with arm # a big pro is that they ship an up to date CMake in their stable distribution # also, they still provide IA-32 builds for some reason... # some people in the AppImage community do not (want to) realize i386 is dead for good # we are going to drop i686 in the future! -FROM ${docker_arch}/debian:stable - -# variables that need to be availabe during build and runtime must(!) be repeated after FROM -ARG ARCH - +FROM debian:stable SHELL ["bash", "-x", "-c"] diff --git a/lib/cmake-scripts b/lib/cmake-scripts index 21bd317..df32987 160000 --- a/lib/cmake-scripts +++ b/lib/cmake-scripts @@ -1 +1 @@ -Subproject commit 21bd317812e44f7ed925f3f3bffcb7136c30ae74 +Subproject commit df329871d82b9bbce76419aea59f595078dee024 diff --git a/lib/linuxdeploy b/lib/linuxdeploy index 76ec4f2..3fdc95e 160000 --- a/lib/linuxdeploy +++ b/lib/linuxdeploy @@ -1 +1 @@ -Subproject commit 76ec4f2c6a7bc9be3ddce41f7f4b4e31ead6d95e +Subproject commit 3fdc95e75b6512430c59d4db12b28fa9bf0559c0 diff --git a/src/deployers/BasicPluginsDeployer.cpp b/src/deployers/BasicPluginsDeployer.cpp index ba927c1..0aadbce 100644 --- a/src/deployers/BasicPluginsDeployer.cpp +++ b/src/deployers/BasicPluginsDeployer.cpp @@ -3,12 +3,12 @@ #include // library headers -#include +#include // local headers #include "BasicPluginsDeployer.h" -using namespace linuxdeploy::core::log; +using namespace linuxdeploy::log; using namespace linuxdeploy::core::appdir; using namespace linuxdeploy::plugin::qt; @@ -31,5 +31,30 @@ BasicPluginsDeployer::BasicPluginsDeployer(std::string moduleName, bool BasicPluginsDeployer::deploy() { // currently this is a no-op, but we might add more functionality later on, such as some kinds of default // attempts to copy data based on the moduleName + return doDeploy(); +} + +bool BasicPluginsDeployer::deployStandardQtPlugins(const std::vector& plugins) +{ + for (const auto &pluginName : plugins) { + ldLog() << "Deploying Qt" << pluginName << "plugins" << std::endl; + if (!fs::exists(qtPluginsPath / pluginName)) { + ldLog() << LD_WARNING << "No plugin path found for Qt" << pluginName << std::endl; + continue; + } + for (fs::directory_iterator i(qtPluginsPath / pluginName); i != fs::directory_iterator(); ++i) { + if (i->path().extension() == ".debug") { + ldLog() << LD_DEBUG << "skipping .debug file:" << i->path() << std::endl; + continue; + } + // add a trailing slash, so pluginName is used as a destination directory, not a file. + if (!appDir.deployLibrary(*i, appDir.path() / "usr/plugins" / pluginName / "")) + return false; + } + } + return true; +} + +bool BasicPluginsDeployer::doDeploy() { return true; } diff --git a/src/deployers/BasicPluginsDeployer.h b/src/deployers/BasicPluginsDeployer.h index 1394f53..0eaca0c 100644 --- a/src/deployers/BasicPluginsDeployer.h +++ b/src/deployers/BasicPluginsDeployer.h @@ -49,7 +49,24 @@ namespace linuxdeploy { virtual ~BasicPluginsDeployer() = default; public: - bool deploy() override; + /** + * This method might make some deployment preparation and calls \sa doDeploy() to finalize the deployment. + */ + bool deploy() override final; + + protected: + /** + * This method does the actual moduleName deployment, where any special case should be handled and + * \sa deployStandardQtPlugins () method should be called to deploy Qt plugins that follow the default + * name and path scheme. + */ + virtual bool doDeploy(); + + /** + * Deploys a list of Qt plugin that should be deployed and + * follow the default name and path scheme. + */ + bool deployStandardQtPlugins(const std::vector& plugins); }; } } diff --git a/src/deployers/BearerPluginsDeployer.cpp b/src/deployers/BearerPluginsDeployer.cpp index 5784060..96ffd14 100644 --- a/src/deployers/BearerPluginsDeployer.cpp +++ b/src/deployers/BearerPluginsDeployer.cpp @@ -1,28 +1,11 @@ // system headers #include -// library headers -#include - // local headers #include "BearerPluginsDeployer.h" using namespace linuxdeploy::plugin::qt; -using namespace linuxdeploy::core::log; - -namespace fs = std::filesystem; - -bool BearerPluginsDeployer::deploy() { - // calling the default code is optional, but it won't hurt for now - if (!BasicPluginsDeployer::deploy()) - return false; - - ldLog() << "Deploying bearer plugins" << std::endl; - - for (fs::directory_iterator i(qtPluginsPath / "bearer"); i != fs::directory_iterator(); ++i) { - if (!appDir.deployLibrary(*i, appDir.path() / "usr/plugins/bearer/")) - return false; - } - return true; +bool BearerPluginsDeployer::doDeploy() { + return deployStandardQtPlugins({"bearer"}); } diff --git a/src/deployers/BearerPluginsDeployer.h b/src/deployers/BearerPluginsDeployer.h index 91a8c77..f7e25d8 100644 --- a/src/deployers/BearerPluginsDeployer.h +++ b/src/deployers/BearerPluginsDeployer.h @@ -10,7 +10,7 @@ namespace linuxdeploy { // we can just use the base class's constructor using BasicPluginsDeployer::BasicPluginsDeployer; - bool deploy() override; + bool doDeploy() override; }; } } diff --git a/src/deployers/CMakeLists.txt b/src/deployers/CMakeLists.txt index 40e2429..b9b069d 100644 --- a/src/deployers/CMakeLists.txt +++ b/src/deployers/CMakeLists.txt @@ -14,6 +14,7 @@ set(CLASSES LocationPluginsDeployer Multimedia5PluginsDeployer Multimedia6PluginsDeployer + NetworkInformationPluginsDeployer WebEnginePluginsDeployer QmlPluginsDeployer Qt3DPluginsDeployer @@ -21,6 +22,7 @@ set(CLASSES PrintSupportPluginsDeployer TextToSpeechPluginsDeployer TlsBackendsDeployer + WaylandcompositorPluginsDeployer ) # TODO: CMake <= 3.7 (at least!) doesn't allow for using OBJECT libraries with target_link_libraries diff --git a/src/deployers/GamepadPluginsDeployer.cpp b/src/deployers/GamepadPluginsDeployer.cpp index 6ebedb7..4a2c8ee 100644 --- a/src/deployers/GamepadPluginsDeployer.cpp +++ b/src/deployers/GamepadPluginsDeployer.cpp @@ -1,28 +1,11 @@ // system headers #include -// library headers -#include - // local headers #include "GamepadPluginsDeployer.h" using namespace linuxdeploy::plugin::qt; -using namespace linuxdeploy::core::log; - -namespace fs = std::filesystem; - -bool GamepadPluginsDeployer::deploy() { - // calling the default code is optional, but it won't hurt for now - if (!BasicPluginsDeployer::deploy()) - return false; - - ldLog() << "Deploying Gamepad plugins" << std::endl; - - for (fs::directory_iterator i(qtPluginsPath / "gamepads"); i != fs::directory_iterator(); ++i) { - if (!appDir.deployLibrary(*i, appDir.path() / "usr/plugins/gamepads/")) - return false; - } - return true; +bool GamepadPluginsDeployer::doDeploy() { + return deployStandardQtPlugins({"gamepads"}); } diff --git a/src/deployers/GamepadPluginsDeployer.h b/src/deployers/GamepadPluginsDeployer.h index a0d28fa..f11c775 100644 --- a/src/deployers/GamepadPluginsDeployer.h +++ b/src/deployers/GamepadPluginsDeployer.h @@ -10,7 +10,7 @@ namespace linuxdeploy { // we can just use the base class's constructor using BasicPluginsDeployer::BasicPluginsDeployer; - bool deploy() override; + bool doDeploy() override; }; } } diff --git a/src/deployers/LocationPluginsDeployer.cpp b/src/deployers/LocationPluginsDeployer.cpp index 689f2c8..95c4bb0 100644 --- a/src/deployers/LocationPluginsDeployer.cpp +++ b/src/deployers/LocationPluginsDeployer.cpp @@ -1,28 +1,11 @@ // system headers #include -// library headers -#include - // local headers #include "LocationPluginsDeployer.h" using namespace linuxdeploy::plugin::qt; -using namespace linuxdeploy::core::log; - -namespace fs = std::filesystem; - -bool LocationPluginsDeployer::deploy() { - // calling the default code is optional, but it won't hurt for now - if (!BasicPluginsDeployer::deploy()) - return false; - - ldLog() << "Deploying Location plugins" << std::endl; - - for (fs::directory_iterator i(qtPluginsPath / "geoservices"); i != fs::directory_iterator(); ++i) { - if (!appDir.deployLibrary(*i, appDir.path() / "usr/plugins/geoservices/")) - return false; - } - return true; +bool LocationPluginsDeployer::doDeploy() { + return deployStandardQtPlugins({"geoservices"}); } diff --git a/src/deployers/LocationPluginsDeployer.h b/src/deployers/LocationPluginsDeployer.h index 645f32c..b4bb4e8 100644 --- a/src/deployers/LocationPluginsDeployer.h +++ b/src/deployers/LocationPluginsDeployer.h @@ -10,7 +10,7 @@ namespace linuxdeploy { // we can just use the base class's constructor using BasicPluginsDeployer::BasicPluginsDeployer; - bool deploy() override; + bool doDeploy() override; }; } } diff --git a/src/deployers/Multimedia5PluginsDeployer.cpp b/src/deployers/Multimedia5PluginsDeployer.cpp index 0718328..136ae71 100644 --- a/src/deployers/Multimedia5PluginsDeployer.cpp +++ b/src/deployers/Multimedia5PluginsDeployer.cpp @@ -1,35 +1,11 @@ // system headers #include -// library headers -#include - // local headers #include "Multimedia5PluginsDeployer.h" using namespace linuxdeploy::plugin::qt; -using namespace linuxdeploy::core::log; - -namespace fs = std::filesystem; - -bool Multimedia5PluginsDeployer::deploy() { - // calling the default code is optional, but it won't hurt for now - if (!BasicPluginsDeployer::deploy()) - return false; - - ldLog() << "Deploying mediaservice plugins" << std::endl; - - for (fs::directory_iterator i(qtPluginsPath / "mediaservice"); i != fs::directory_iterator(); ++i) { - if (!appDir.deployLibrary(*i, appDir.path() / "usr/plugins/mediaservice/")) - return false; - } - - ldLog() << "Deploying audio plugins" << std::endl; - - for (fs::directory_iterator i(qtPluginsPath / "audio"); i != fs::directory_iterator(); ++i) { - if (!appDir.deployLibrary(*i, appDir.path() / "usr/plugins/audio/")) - return false; - } - return true; +bool Multimedia5PluginsDeployer::doDeploy() { + return deployStandardQtPlugins({"mediaservice", "audio"}); } diff --git a/src/deployers/Multimedia5PluginsDeployer.h b/src/deployers/Multimedia5PluginsDeployer.h index b674ace..7e14150 100644 --- a/src/deployers/Multimedia5PluginsDeployer.h +++ b/src/deployers/Multimedia5PluginsDeployer.h @@ -10,7 +10,7 @@ namespace linuxdeploy { // we can just use the base class's constructor using BasicPluginsDeployer::BasicPluginsDeployer; - bool deploy() override; + bool doDeploy() override; }; } } diff --git a/src/deployers/Multimedia6PluginsDeployer.cpp b/src/deployers/Multimedia6PluginsDeployer.cpp index 2ea8fee..4004828 100644 --- a/src/deployers/Multimedia6PluginsDeployer.cpp +++ b/src/deployers/Multimedia6PluginsDeployer.cpp @@ -2,31 +2,21 @@ #include // library headers -#include +#include // local headers #include "Multimedia6PluginsDeployer.h" using namespace linuxdeploy::plugin::qt; -using namespace linuxdeploy::core::log; +using namespace linuxdeploy::log; namespace fs = std::filesystem; -bool Multimedia6PluginsDeployer::deploy() { - // calling the default code is optional, but it won't hurt for now - if (!BasicPluginsDeployer::deploy()) - return false; - +bool Multimedia6PluginsDeployer::doDeploy() { if (fs::exists(qtPluginsPath / "multimedia")) { - ldLog() << "Deploying multimedia plugins" << std::endl; - - for (fs::directory_iterator i(qtPluginsPath / "multimedia"); i != fs::directory_iterator(); ++i) { - if (!appDir.deployLibrary(*i, appDir.path() / "usr/plugins/multimedia/")) - return false; - } + return deployStandardQtPlugins({"multimedia"}); } else { ldLog() << LD_WARNING << "Missing Qt 6 multimedia plugins, skipping." << std::endl; + return true; } - - return true; } diff --git a/src/deployers/Multimedia6PluginsDeployer.h b/src/deployers/Multimedia6PluginsDeployer.h index 60d61cc..f4d2795 100644 --- a/src/deployers/Multimedia6PluginsDeployer.h +++ b/src/deployers/Multimedia6PluginsDeployer.h @@ -10,7 +10,7 @@ namespace linuxdeploy { // we can just use the base class's constructor using BasicPluginsDeployer::BasicPluginsDeployer; - bool deploy() override; + bool doDeploy() override; }; } } diff --git a/src/deployers/NetworkInformationPluginsDeployer.cpp b/src/deployers/NetworkInformationPluginsDeployer.cpp new file mode 100644 index 0000000..e922331 --- /dev/null +++ b/src/deployers/NetworkInformationPluginsDeployer.cpp @@ -0,0 +1,11 @@ +#include "NetworkInformationPluginsDeployer.h" + +namespace linuxdeploy { +namespace plugin { +namespace qt { +bool NetworkInformationPluginsDeployer::doDeploy() { + return deployStandardQtPlugins({"networkinformation"}); +} +} // namespace qt +} // namespace plugin +} // namespace linuxdeploy diff --git a/src/deployers/NetworkInformationPluginsDeployer.h b/src/deployers/NetworkInformationPluginsDeployer.h new file mode 100644 index 0000000..1c6c766 --- /dev/null +++ b/src/deployers/NetworkInformationPluginsDeployer.h @@ -0,0 +1,17 @@ +#pragma once + +#include "BasicPluginsDeployer.h" + +namespace linuxdeploy { +namespace plugin { +namespace qt { +class NetworkInformationPluginsDeployer : public BasicPluginsDeployer { +public: + // we can just use the base class's constructor + using BasicPluginsDeployer::BasicPluginsDeployer; + + bool doDeploy() override; +}; +} // namespace qt +} // namespace plugin +} // namespace linuxdeploy diff --git a/src/deployers/PlatformPluginsDeployer.cpp b/src/deployers/PlatformPluginsDeployer.cpp index 5d5076b..378d727 100644 --- a/src/deployers/PlatformPluginsDeployer.cpp +++ b/src/deployers/PlatformPluginsDeployer.cpp @@ -2,22 +2,18 @@ #include // library headers -#include +#include #include // local headers #include "PlatformPluginsDeployer.h" using namespace linuxdeploy::plugin::qt; -using namespace linuxdeploy::core::log; +using namespace linuxdeploy::log; namespace fs = std::filesystem; -bool PlatformPluginsDeployer::deploy() { - // calling the default code is optional, but it won't hurt for now - if (!BasicPluginsDeployer::deploy()) - return false; - +bool PlatformPluginsDeployer::doDeploy() { ldLog() << "Deploying platform plugins" << std::endl; // always deploy default platform @@ -31,17 +27,18 @@ bool PlatformPluginsDeployer::deploy() { ldLog() << "Deploying extra platform plugin: " << platformToDeploy << std::endl; if (!appDir.deployLibrary(qtPluginsPath / "platforms" / platformToDeploy, appDir.path() / "usr/plugins/platforms/")) return false; - } - } - for (fs::directory_iterator i(qtPluginsPath / "platforminputcontexts"); i != fs::directory_iterator(); ++i) { - if (!appDir.deployLibrary(*i, appDir.path() / "usr/plugins/platforminputcontexts/")) - return false; + using namespace linuxdeploy::util::misc; + if (stringStartsWith(platformToDeploy, "libqwayland")) { + if (!deployStandardQtPlugins({"wayland-decoration-client", "wayland-shell-integration"})) { + return false; + } + } + } } - for (fs::directory_iterator i(qtPluginsPath / "imageformats"); i != fs::directory_iterator(); ++i) { - if (!appDir.deployLibrary(*i, appDir.path() / "usr/plugins/imageformats/")) - return false; + if (!deployStandardQtPlugins({"platforminputcontexts", "imageformats"})) { + return false; } // TODO: platform themes -- https://github.com/probonopd/linuxdeployqt/issues/236 diff --git a/src/deployers/PlatformPluginsDeployer.h b/src/deployers/PlatformPluginsDeployer.h index 20379f8..ca4c9b6 100644 --- a/src/deployers/PlatformPluginsDeployer.h +++ b/src/deployers/PlatformPluginsDeployer.h @@ -10,7 +10,7 @@ namespace linuxdeploy { // we can just use the base class's constructor using BasicPluginsDeployer::BasicPluginsDeployer; - bool deploy() override; + bool doDeploy() override; }; } } diff --git a/src/deployers/PluginsDeployerFactory.cpp b/src/deployers/PluginsDeployerFactory.cpp index 72ea048..b3aa124 100644 --- a/src/deployers/PluginsDeployerFactory.cpp +++ b/src/deployers/PluginsDeployerFactory.cpp @@ -1,22 +1,24 @@ // local headers #include "PluginsDeployerFactory.h" #include "BasicPluginsDeployer.h" -#include "PlatformPluginsDeployer.h" #include "BearerPluginsDeployer.h" #include "GamepadPluginsDeployer.h" #include "LocationPluginsDeployer.h" #include "Multimedia5PluginsDeployer.h" #include "Multimedia6PluginsDeployer.h" -#include "PrintSupportPluginsDeployer.h" +#include "NetworkInformationPluginsDeployer.h" +#include "PlatformPluginsDeployer.h" #include "PositioningPluginsDeployer.h" +#include "PrintSupportPluginsDeployer.h" #include "QmlPluginsDeployer.h" #include "Qt3DPluginsDeployer.h" #include "SqlPluginsDeployer.h" #include "SvgPluginsDeployer.h" #include "TextToSpeechPluginsDeployer.h" +#include "TlsBackendsDeployer.h" +#include "WaylandcompositorPluginsDeployer.h" #include "WebEnginePluginsDeployer.h" #include "XcbglIntegrationPluginsDeployer.h" -#include "TlsBackendsDeployer.h" using namespace linuxdeploy::plugin::qt; using namespace linuxdeploy::core::appdir; @@ -50,8 +52,16 @@ std::vector> PluginsDeployerFactory::getDeploye if (moduleName == "network") { if (qtMajorVersion < 6) { return {getInstance(moduleName)}; - } else if (qtMinorVersion >= 2) { - return {getInstance(moduleName)}; + } else { + std::vector> deployers; + if (qtMinorVersion >= 1) { + deployers.push_back( + getInstance(moduleName)); + } + if (qtMinorVersion >= 2) { + deployers.push_back(getInstance(moduleName)); + } + return deployers; } } @@ -72,9 +82,9 @@ std::vector> PluginsDeployerFactory::getDeploye } if (moduleName == "multimedia") { - if (qtMajorVersion < 6) { + if (qtMajorVersion < 6) { return {getInstance(moduleName)}; - } else { + } else { return {getInstance(moduleName)}; } } @@ -103,6 +113,10 @@ std::vector> PluginsDeployerFactory::getDeploye return {getInstance(moduleName)}; } + if (moduleName == "waylandcompositor") { + return {getInstance(moduleName)}; + } + // fallback return {getInstance(moduleName)}; } diff --git a/src/deployers/PositioningPluginsDeployer.cpp b/src/deployers/PositioningPluginsDeployer.cpp index 5c95e7f..02d7459 100644 --- a/src/deployers/PositioningPluginsDeployer.cpp +++ b/src/deployers/PositioningPluginsDeployer.cpp @@ -1,28 +1,11 @@ // system headers #include -// library headers -#include - // local headers #include "PositioningPluginsDeployer.h" using namespace linuxdeploy::plugin::qt; -using namespace linuxdeploy::core::log; - -namespace fs = std::filesystem; - -bool PositioningPluginsDeployer::deploy() { - // calling the default code is optional, but it won't hurt for now - if (!BasicPluginsDeployer::deploy()) - return false; - - ldLog() << "Deploying positioning plugins" << std::endl; - - for (fs::directory_iterator i(qtPluginsPath / "position"); i != fs::directory_iterator(); ++i) { - if (!appDir.deployLibrary(*i, appDir.path() / "usr/plugins/position/")) - return false; - } - return true; +bool PositioningPluginsDeployer::doDeploy() { + return deployStandardQtPlugins({"position"}); } diff --git a/src/deployers/PositioningPluginsDeployer.h b/src/deployers/PositioningPluginsDeployer.h index c60e221..b39eb7c 100644 --- a/src/deployers/PositioningPluginsDeployer.h +++ b/src/deployers/PositioningPluginsDeployer.h @@ -10,7 +10,7 @@ namespace linuxdeploy { // we can just use the base class's constructor using BasicPluginsDeployer::BasicPluginsDeployer; - bool deploy() override; + bool doDeploy() override; }; } } diff --git a/src/deployers/PrintSupportPluginsDeployer.cpp b/src/deployers/PrintSupportPluginsDeployer.cpp index 15c1d86..d1b8ef5 100644 --- a/src/deployers/PrintSupportPluginsDeployer.cpp +++ b/src/deployers/PrintSupportPluginsDeployer.cpp @@ -1,28 +1,11 @@ // system headers #include -// library headers -#include - // local headers #include "PrintSupportPluginsDeployer.h" using namespace linuxdeploy::plugin::qt; -using namespace linuxdeploy::core::log; - -namespace fs = std::filesystem; - -bool PrintSupportPluginsDeployer::deploy() { - // calling the default code is optional, but it won't hurt for now - if (!BasicPluginsDeployer::deploy()) - return false; - - ldLog() << "Deploying printsupport plugins" << std::endl; - - for (fs::directory_iterator i(qtPluginsPath / "printsupport"); i != fs::directory_iterator(); ++i) { - if (!appDir.deployLibrary(*i, appDir.path() / "usr/plugins/printsupport/")) - return false; - } - return true; +bool PrintSupportPluginsDeployer::doDeploy() { + return deployStandardQtPlugins({"printsupport"}); } diff --git a/src/deployers/PrintSupportPluginsDeployer.h b/src/deployers/PrintSupportPluginsDeployer.h index 6780d06..797f4ed 100644 --- a/src/deployers/PrintSupportPluginsDeployer.h +++ b/src/deployers/PrintSupportPluginsDeployer.h @@ -10,7 +10,7 @@ namespace linuxdeploy { // we can just use the base class's constructor using BasicPluginsDeployer::BasicPluginsDeployer; - bool deploy() override; + bool doDeploy() override; }; } } diff --git a/src/deployers/QmlPluginsDeployer.cpp b/src/deployers/QmlPluginsDeployer.cpp index e538ea1..1b8c488 100644 --- a/src/deployers/QmlPluginsDeployer.cpp +++ b/src/deployers/QmlPluginsDeployer.cpp @@ -8,11 +8,7 @@ using namespace linuxdeploy::plugin::qt; namespace fs = std::filesystem; -bool QmlPluginsDeployer::deploy() { - // calling the default code is optional, but it won't hurt for now - if (!BasicPluginsDeployer::deploy()) - return false; - +bool QmlPluginsDeployer::doDeploy() { try { deployQml(appDir, qtInstallQmlPath); } catch (const QmlImportScannerError &) { diff --git a/src/deployers/QmlPluginsDeployer.h b/src/deployers/QmlPluginsDeployer.h index 28ddc0d..6c4e897 100644 --- a/src/deployers/QmlPluginsDeployer.h +++ b/src/deployers/QmlPluginsDeployer.h @@ -10,7 +10,7 @@ namespace linuxdeploy { // we can just use the base class's constructor using BasicPluginsDeployer::BasicPluginsDeployer; - bool deploy() override; + bool doDeploy() override; }; } } diff --git a/src/deployers/Qt3DPluginsDeployer.cpp b/src/deployers/Qt3DPluginsDeployer.cpp index 635ea04..4eaad20 100644 --- a/src/deployers/Qt3DPluginsDeployer.cpp +++ b/src/deployers/Qt3DPluginsDeployer.cpp @@ -1,33 +1,11 @@ // system headers #include -// library headers -#include - // local headers #include "Qt3DPluginsDeployer.h" using namespace linuxdeploy::plugin::qt; -using namespace linuxdeploy::core::log; - -namespace fs = std::filesystem; - -bool Qt3DPluginsDeployer::deploy() { - // calling the default code is optional, but it won't hurt for now - if (!BasicPluginsDeployer::deploy()) - return false; - - ldLog() << "Deploying Qt 3D plugins" << std::endl; - - for (fs::directory_iterator i(qtPluginsPath / "geometryloaders"); i != fs::directory_iterator(); ++i) { - if (!appDir.deployLibrary(*i, appDir.path() / "usr/plugins/geometryloaders/")) - return false; - } - - for (fs::directory_iterator i(qtPluginsPath / "sceneparsers"); i != fs::directory_iterator(); ++i) { - if (!appDir.deployLibrary(*i, appDir.path() / "usr/plugins/sceneparsers/")) - return false; - } - return true; +bool Qt3DPluginsDeployer::doDeploy() { + return deployStandardQtPlugins({"geometryloaders", "sceneparsers"}); } diff --git a/src/deployers/Qt3DPluginsDeployer.h b/src/deployers/Qt3DPluginsDeployer.h index 5810a34..96ed8c8 100644 --- a/src/deployers/Qt3DPluginsDeployer.h +++ b/src/deployers/Qt3DPluginsDeployer.h @@ -10,7 +10,7 @@ namespace linuxdeploy { // we can just use the base class's constructor using BasicPluginsDeployer::BasicPluginsDeployer; - bool deploy() override; + bool doDeploy() override; }; } } diff --git a/src/deployers/SqlPluginsDeployer.cpp b/src/deployers/SqlPluginsDeployer.cpp index 6d0111b..b7d241a 100644 --- a/src/deployers/SqlPluginsDeployer.cpp +++ b/src/deployers/SqlPluginsDeployer.cpp @@ -1,28 +1,11 @@ // system headers #include -// library headers -#include - // local headers #include "SqlPluginsDeployer.h" using namespace linuxdeploy::plugin::qt; -using namespace linuxdeploy::core::log; - -namespace fs = std::filesystem; - -bool SqlPluginsDeployer::deploy() { - // calling the default code is optional, but it won't hurt for now - if (!BasicPluginsDeployer::deploy()) - return false; - - ldLog() << "Deploying SQL plugins" << std::endl; - - for (fs::directory_iterator i(qtPluginsPath / "sqldrivers"); i != fs::directory_iterator(); ++i) { - if (!appDir.deployLibrary(*i, appDir.path() / "usr/plugins/sqldrivers/")) - return false; - } - return true; +bool SqlPluginsDeployer::doDeploy() { + return deployStandardQtPlugins({"sqldrivers"}); } diff --git a/src/deployers/SqlPluginsDeployer.h b/src/deployers/SqlPluginsDeployer.h index 9329aef..bad131f 100644 --- a/src/deployers/SqlPluginsDeployer.h +++ b/src/deployers/SqlPluginsDeployer.h @@ -10,7 +10,7 @@ namespace linuxdeploy { // we can just use the base class's constructor using BasicPluginsDeployer::BasicPluginsDeployer; - bool deploy() override; + bool doDeploy() override; }; } } diff --git a/src/deployers/SvgPluginsDeployer.cpp b/src/deployers/SvgPluginsDeployer.cpp index 90a628d..5e38cea 100644 --- a/src/deployers/SvgPluginsDeployer.cpp +++ b/src/deployers/SvgPluginsDeployer.cpp @@ -2,21 +2,17 @@ #include // library headers -#include +#include // local headers #include "SvgPluginsDeployer.h" using namespace linuxdeploy::plugin::qt; -using namespace linuxdeploy::core::log; +using namespace linuxdeploy::log; namespace fs = std::filesystem; -bool SvgPluginsDeployer::deploy() { - // calling the default code is optional, but it won't hurt for now - if (!BasicPluginsDeployer::deploy()) - return false; - +bool SvgPluginsDeployer::doDeploy() { ldLog() << "Deploying svg icon engine" << std::endl; if (!appDir.deployLibrary(qtPluginsPath / "iconengines/libqsvgicon.so", appDir.path() / "usr/plugins/iconengines/")) diff --git a/src/deployers/SvgPluginsDeployer.h b/src/deployers/SvgPluginsDeployer.h index 18466b6..5394c1f 100644 --- a/src/deployers/SvgPluginsDeployer.h +++ b/src/deployers/SvgPluginsDeployer.h @@ -10,7 +10,7 @@ namespace linuxdeploy { // we can just use the base class's constructor using BasicPluginsDeployer::BasicPluginsDeployer; - bool deploy() override; + bool doDeploy() override; }; } } diff --git a/src/deployers/TextToSpeechPluginsDeployer.cpp b/src/deployers/TextToSpeechPluginsDeployer.cpp index a0124d6..ddf5a3d 100644 --- a/src/deployers/TextToSpeechPluginsDeployer.cpp +++ b/src/deployers/TextToSpeechPluginsDeployer.cpp @@ -1,38 +1,8 @@ -// system headers -#include - -// library headers -#include - // local headers #include "TextToSpeechPluginsDeployer.h" using namespace linuxdeploy::plugin::qt; -using namespace linuxdeploy::core::log; - -namespace fs = std::filesystem; - -bool TextToSpeechPluginsDeployer::deploy() { - // calling the default code is optional, but it won't hurt for now - if (!BasicPluginsDeployer::deploy()) - return false; - - const std::string pluginsName = "texttospeech"; - - ldLog() << "Deploying" << pluginsName << "plugins" << std::endl; - - for (fs::directory_iterator i(qtPluginsPath / pluginsName); i != fs::directory_iterator(); ++i) { - if (i->path().extension() == ".debug") { - ldLog() << LD_DEBUG << "skipping .debug file:" << i->path() << std::endl; - continue; - } - - // terminate with a "/" to make sure the deployer will deploy the file into the target directory properly - // has to be cast to string, unfortunately, as std::filesystem doesn't allow for adding a terminating / - const auto targetPath = (appDir.path() / "usr/plugins/" / pluginsName).string() + "/"; - if (!appDir.deployLibrary(*i, targetPath)) - return false; - } - return true; +bool TextToSpeechPluginsDeployer::doDeploy() { + return deployStandardQtPlugins({"texttospeech"}); } diff --git a/src/deployers/TextToSpeechPluginsDeployer.h b/src/deployers/TextToSpeechPluginsDeployer.h index 2138723..9c540fd 100644 --- a/src/deployers/TextToSpeechPluginsDeployer.h +++ b/src/deployers/TextToSpeechPluginsDeployer.h @@ -10,7 +10,7 @@ namespace linuxdeploy { // we can just use the base class's constructor using BasicPluginsDeployer::BasicPluginsDeployer; - bool deploy() override; + bool doDeploy() override; }; } } diff --git a/src/deployers/TlsBackendsDeployer.cpp b/src/deployers/TlsBackendsDeployer.cpp index e6c84b9..aae471f 100644 --- a/src/deployers/TlsBackendsDeployer.cpp +++ b/src/deployers/TlsBackendsDeployer.cpp @@ -1,28 +1,11 @@ // system headers #include -// library headers -#include - // local headers #include "TlsBackendsDeployer.h" using namespace linuxdeploy::plugin::qt; -using namespace linuxdeploy::core::log; - -namespace fs = std::filesystem; - -bool TlsBackendsDeployer::deploy() { - // calling the default code is optional, but it won't hurt for now - if (!BasicPluginsDeployer::deploy()) - return false; - - ldLog() << "Deploying TLS backends" << std::endl; - - for (fs::directory_iterator i(qtPluginsPath / "tls"); i != fs::directory_iterator(); ++i) { - if (!appDir.deployLibrary(*i, appDir.path() / "usr/plugins/tls/")) - return false; - } - return true; +bool TlsBackendsDeployer::doDeploy() { + return deployStandardQtPlugins({"tls"}); } diff --git a/src/deployers/TlsBackendsDeployer.h b/src/deployers/TlsBackendsDeployer.h index e3aa3a2..460532b 100644 --- a/src/deployers/TlsBackendsDeployer.h +++ b/src/deployers/TlsBackendsDeployer.h @@ -10,7 +10,7 @@ namespace linuxdeploy { // we can just use the base class's constructor using BasicPluginsDeployer::BasicPluginsDeployer; - bool deploy() override; + bool doDeploy() override; }; } } diff --git a/src/deployers/WaylandcompositorPluginsDeployer.cpp b/src/deployers/WaylandcompositorPluginsDeployer.cpp new file mode 100644 index 0000000..55cfdc2 --- /dev/null +++ b/src/deployers/WaylandcompositorPluginsDeployer.cpp @@ -0,0 +1,13 @@ +// system headers +#include + +// local headers +#include "WaylandcompositorPluginsDeployer.h" + +using namespace linuxdeploy::plugin::qt; + +bool WaylandcompositorPluginsDeployer::doDeploy() { + return deployStandardQtPlugins({"wayland-decoration-client", + "wayland-graphics-integration-client", + "wayland-shell-integration",}); +} diff --git a/src/deployers/WaylandcompositorPluginsDeployer.h b/src/deployers/WaylandcompositorPluginsDeployer.h new file mode 100644 index 0000000..f27a5fb --- /dev/null +++ b/src/deployers/WaylandcompositorPluginsDeployer.h @@ -0,0 +1,17 @@ +#pragma once + +#include "BasicPluginsDeployer.h" + +namespace linuxdeploy { + namespace plugin { + namespace qt { + class WaylandcompositorPluginsDeployer : public BasicPluginsDeployer { + public: + // we can just use the base class's constructor + using BasicPluginsDeployer::BasicPluginsDeployer; + + bool doDeploy() override; + }; + } + } +} diff --git a/src/deployers/WebEnginePluginsDeployer.cpp b/src/deployers/WebEnginePluginsDeployer.cpp index f93ed1f..939b3c9 100644 --- a/src/deployers/WebEnginePluginsDeployer.cpp +++ b/src/deployers/WebEnginePluginsDeployer.cpp @@ -3,22 +3,18 @@ #include // library headers -#include +#include #include // local headers #include "WebEnginePluginsDeployer.h" using namespace linuxdeploy::plugin::qt; -using namespace linuxdeploy::core::log; +using namespace linuxdeploy::log; namespace fs = std::filesystem; -bool WebEnginePluginsDeployer::deploy() { - // calling the default code is optional, but it won't hurt for now - if (!BasicPluginsDeployer::deploy()) - return false; - +bool WebEnginePluginsDeployer::doDeploy() { ldLog() << "Deploying web engine plugins" << std::endl; const auto newLibexecPath = appDir.path() / "usr/libexec/"; @@ -43,7 +39,9 @@ bool WebEnginePluginsDeployer::deploy() { for (const auto &fileName : {"qtwebengine_resources.pak", "qtwebengine_devtools_resources.pak", "qtwebengine_resources_100p.pak", - "qtwebengine_resources_200p.pak", "icudtl.dat"}) { + "qtwebengine_resources_200p.pak", + "icudtl.dat", + "v8_context_snapshot.bin"}) { auto path = qtDataPath / "resources" / fileName; if (fs::is_regular_file(path)) diff --git a/src/deployers/WebEnginePluginsDeployer.h b/src/deployers/WebEnginePluginsDeployer.h index 64ba8bd..a76997b 100644 --- a/src/deployers/WebEnginePluginsDeployer.h +++ b/src/deployers/WebEnginePluginsDeployer.h @@ -10,7 +10,7 @@ namespace linuxdeploy { // we can just use the base class's constructor using BasicPluginsDeployer::BasicPluginsDeployer; - bool deploy() override; + bool doDeploy() override; }; } } diff --git a/src/deployers/XcbglIntegrationPluginsDeployer.cpp b/src/deployers/XcbglIntegrationPluginsDeployer.cpp index 21c54a4..6e2c390 100644 --- a/src/deployers/XcbglIntegrationPluginsDeployer.cpp +++ b/src/deployers/XcbglIntegrationPluginsDeployer.cpp @@ -1,18 +1,14 @@ // library headers -#include +#include // local headers #include "XcbglIntegrationPluginsDeployer.h" #include "deployment.h" using namespace linuxdeploy::plugin::qt; -using namespace linuxdeploy::core::log; - -bool XcbglIntegrationPluginsDeployer::deploy() { - // calling the default code is optional, but it won't hurt for now - if (!BasicPluginsDeployer::deploy()) - return false; +using namespace linuxdeploy::log; +bool XcbglIntegrationPluginsDeployer::doDeploy() { ldLog() << "Deploying xcb-gl integrations" << std::endl; return deployIntegrationPlugins(appDir, qtPluginsPath, {"xcbglintegrations/"}); diff --git a/src/deployers/XcbglIntegrationPluginsDeployer.h b/src/deployers/XcbglIntegrationPluginsDeployer.h index 23d1db5..eade482 100644 --- a/src/deployers/XcbglIntegrationPluginsDeployer.h +++ b/src/deployers/XcbglIntegrationPluginsDeployer.h @@ -10,7 +10,7 @@ namespace linuxdeploy { // we can just use the base class's constructor using BasicPluginsDeployer::BasicPluginsDeployer; - bool deploy() override; + bool doDeploy() override; }; } } diff --git a/src/deployment.h b/src/deployment.h index 04df3a1..5bac39a 100644 --- a/src/deployment.h +++ b/src/deployment.h @@ -7,7 +7,7 @@ // library includes #include #include -#include +#include #include // local includes @@ -19,7 +19,7 @@ namespace fs = std::filesystem; using namespace linuxdeploy::core; using namespace linuxdeploy::util::misc; -using namespace linuxdeploy::core::log; +using namespace linuxdeploy::log; // little helper called by other integration plugins inline bool deployIntegrationPlugins(appdir::AppDir& appDir, const fs::path& qtPluginsPath, const std::initializer_list& subDirs) { @@ -37,6 +37,10 @@ inline bool deployIntegrationPlugins(appdir::AppDir& appDir, const fs::path& qtP // otherwise, when the directory doesn't exist, it might just copy all files to files called like // destinationDir auto destinationDir = appDir.path() / "usr/plugins" / subDir / ""; + if (i->path().extension() == ".debug") { + ldLog() << LD_DEBUG << "skipping .debug file:" << i->path() << std::endl; + continue; + } if (!appDir.deployLibrary(*i, destinationDir)) return false; diff --git a/src/main.cpp b/src/main.cpp index 78b0655..db89e05 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,7 +9,7 @@ // library includes #include #include -#include +#include #include // local includes @@ -22,7 +22,7 @@ namespace fs = std::filesystem; using namespace linuxdeploy::core; using namespace linuxdeploy::util::misc; -using namespace linuxdeploy::core::log; +using namespace linuxdeploy::log; using namespace linuxdeploy::plugin::qt; @@ -34,10 +34,15 @@ int main(const int argc, const char *const *const argv) { args::ArgumentParser parser("linuxdeploy Qt plugin", "Bundles Qt resources. For use with an existing AppDir, created by linuxdeploy."); + args::HelpFlag help(parser, "help", "Display this help text", {'h', "help"}); + args::ValueFlag appDirPath(parser, "appdir path", "Path to an existing AppDir", {"appdir"}); - args::ValueFlagList extraPlugins(parser, "plugin", - "Extra Qt plugin to deploy (specified by name, filename or path)", - {'p', "extra-plugin"}); + args::ValueFlagList excludeLibraryPatterns(parser, "pattern", + "Shared library to exclude from deployment (glob pattern)", + {"exclude-library"}); + args::ValueFlagList extraModules(parser, "module", + "Extra Qt module to deploy (specified by name, filename or path)", + {'m', "extra-module"}); args::Flag pluginType(parser, "", "Print plugin type and exit", {"plugin-type"}); args::Flag pluginApiVersion(parser, "", "Print plugin API version and exit", {"plugin-api-version"}); @@ -46,6 +51,9 @@ int main(const int argc, const char *const *const argv) { try { parser.ParseCLI(argc, argv); + } catch (const args::Help &) { + std::cerr << parser; + return 0; } catch (const args::ParseError &) { std::cerr << parser; return 1; @@ -92,7 +100,7 @@ int main(const int argc, const char *const *const argv) { ldLog() << LD_ERROR << "No such file or directory:" << qmakePath << std::endl; return 1; } - + ldLog() << "Using qmake:" << qmakePath << std::endl; auto qmakeVars = queryQmake(qmakePath); @@ -130,6 +138,9 @@ int main(const int argc, const char *const *const argv) { ldLog() << std::endl << "Using Qt version: " << qtVersion << " (" << qtMajorVersion << ")" << std::endl; appdir::AppDir appDir(appDirPath.Get()); + if (const auto patterns = excludeLibraryPatterns.Get(); !patterns.empty()) { + appDir.setExcludeLibraryPatterns(patterns); + } // allow disabling copyright files deployment via environment variable if (getenv("DISABLE_COPYRIGHT_FILES_DEPLOYMENT") != nullptr) { @@ -194,18 +205,27 @@ int main(const int argc, const char *const *const argv) { }) != libraryNames.end(); }); - std::vector extraPluginsFromEnv; - const auto* const extraPluginsFromEnvData = getenv("EXTRA_QT_PLUGINS"); - if (extraPluginsFromEnvData != nullptr) - extraPluginsFromEnv = linuxdeploy::util::split(std::string(extraPluginsFromEnvData), ';'); + std::vector extraModulesFromEnv; + const auto* const extraModulesFromEnvData = []() -> char* { + auto* ret = getenv("EXTRA_QT_MODULES"); + if (ret == nullptr) { + ret = getenv("EXTRA_QT_PLUGINS"); + if (ret) { + ldLog() << std::endl << LD_WARNING << "Using deprecated EXTRA_QT_PLUGINS env var (renamed to EXTRA_QT_MODULES)" << std::endl; + } + } + return ret; + }(); + if (extraModulesFromEnvData != nullptr) + extraModulesFromEnv = linuxdeploy::util::split(std::string(extraModulesFromEnvData), ';'); - for (const auto& pluginsList : {static_cast>(extraPlugins.Get()), extraPluginsFromEnv}) { + for (const auto& modulesList : {static_cast>(extraModules.Get()), extraModulesFromEnv}) { std::copy_if(qtModules.begin(), qtModules.end(), std::back_inserter(extraQtModules), - [&matchesQtModule, &libraryNames, &pluginsList](const QtModule &module) { - return std::find_if(pluginsList.begin(), pluginsList.end(), + [&matchesQtModule, &libraryNames, &modulesList](const QtModule &module) { + return std::find_if(modulesList.begin(), modulesList.end(), [&matchesQtModule, &module](const std::string &libraryName) { return matchesQtModule(libraryName, module); - }) != pluginsList.end(); + }) != modulesList.end(); } ); } @@ -288,10 +308,14 @@ int main(const int argc, const char *const *const argv) { return 1; } - ldLog() << std::endl << "-- Creating AppRun hook --" << std::endl; - if (!createAppRunHook(appDir)) { - ldLog() << LD_ERROR << "Failed to create AppRun hook in AppDir" << std::endl; - return 1; + if (qtMajorVersion >= 6) { + ldLog() << std::endl << "-- Note: skipping AppRun hook creation on Qt " << qtMajorVersion << " --" << std::endl; + } else { + ldLog() << std::endl << "-- Creating AppRun hook --" << std::endl; + if (!createAppRunHook(appDir)) { + ldLog() << LD_ERROR << "Failed to create AppRun hook in AppDir" << std::endl; + return 1; + } } ldLog() << std::endl << "Done!" << std::endl; diff --git a/src/qml.cpp b/src/qml.cpp index 6bdf4ce..6f997c1 100644 --- a/src/qml.cpp +++ b/src/qml.cpp @@ -1,10 +1,14 @@ // system headers #include +#ifdef __FreeBSD__ +#include +#endif + // library includes #include #include -#include +#include #include #include #include @@ -14,7 +18,7 @@ #include "qml.h" using namespace linuxdeploy::core; -using namespace linuxdeploy::core::log; +using namespace linuxdeploy::log; using namespace linuxdeploy::subprocess; using namespace linuxdeploy::util; using namespace nlohmann; @@ -22,7 +26,18 @@ using namespace nlohmann; namespace fs = std::filesystem; fs::path findQmlImportScanner() { - return which("qmlimportscanner"); + auto path = which("qmlimportscanner"); + if (path.empty()) { + // at least on FreeBSD the qmlimportscanner binary is installed under + // QT_INSTALL_LIBEXECS for Qt 6 and QT_INSTALL_BINS for Qt5, + // so is not locatable via $PATH + auto qmakeVars = queryQmake(findQmake()); + path = which(qmakeVars["QT_INSTALL_LIBEXECS"] + "/qmlimportscanner"); + if (path.empty()) + path = which(qmakeVars["QT_INSTALL_BINS"] + "/qmlimportscanner"); + } + + return path; } std::string runQmlImportScanner(const std::vector &sourcesPaths, const std::vector &qmlImportPaths) { diff --git a/src/qt-modules.h b/src/qt-modules.h index 2741bb6..36246f7 100644 --- a/src/qt-modules.h +++ b/src/qt-modules.h @@ -70,6 +70,8 @@ static const std::vector Qt5Modules = { {"svg", "libQt5Svg", ""}, {"test", "libQt5Test", "qtbase"}, {"texttospeech", "libQt5TextToSpeech", ""}, + {"waylandclient", "libQt5WaylandClient", ""}, + {"waylandcompositor", "libQt5WaylandCompositor", ""}, {"webchannel", "libQt5WebChannel", ""}, {"webenginecore", "libQt5WebEngineCore", ""}, {"webengine", "libQt5WebEngine", "qtwebengine"}, diff --git a/src/util.cpp b/src/util.cpp index 3bd0d87..6dd662b 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -2,6 +2,7 @@ #include // library headers +#include #include #include @@ -13,7 +14,7 @@ using namespace linuxdeploy::subprocess; std::map queryQmake(const std::filesystem::path& qmakePath) { auto qmakeCall = subprocess({qmakePath.string(), "-query"}).run(); - using namespace linuxdeploy::core::log; + using namespace linuxdeploy::log; if (qmakeCall.exit_code() != 0) { ldLog() << LD_ERROR << "Call to qmake failed:" << qmakeCall.stderr_string() << std::endl; @@ -54,7 +55,7 @@ std::map queryQmake(const std::filesystem::path& qmake }; std::filesystem::path findQmake() { - using namespace linuxdeploy::core::log; + using namespace linuxdeploy::log; std::filesystem::path qmakePath; @@ -68,6 +69,9 @@ std::filesystem::path findQmake() { if (qmakePath.empty()) qmakePath = linuxdeploy::util::which("qmake"); + + if (qmakePath.empty()) + qmakePath = linuxdeploy::util::which("qmake6"); } return qmakePath; diff --git a/src/util.h b/src/util.h index 3d48755..f384662 100644 --- a/src/util.h +++ b/src/util.h @@ -10,7 +10,6 @@ // library includes #include -#include typedef struct { bool success; diff --git a/tests/test_deploy_qml.cpp b/tests/test_deploy_qml.cpp index 4ec945e..c6af3d1 100644 --- a/tests/test_deploy_qml.cpp +++ b/tests/test_deploy_qml.cpp @@ -52,10 +52,9 @@ namespace linuxdeploy { TEST_F(TestDeployQml, find_qmlimporter_path) { auto result = findQmlImportScanner(); - std::filesystem::path expected = "/usr/bin/qmlimportscanner"; ASSERT_FALSE(result.empty()); - ASSERT_EQ(result.string(), expected.string()); + ASSERT_EQ(result.filename().string(), "qmlimportscanner"); } TEST_F(TestDeployQml, runQmlImportScanner) {