From 37ab1a5513d9522f9aa2264dc5dcd306347526d8 Mon Sep 17 00:00:00 2001 From: Stefan Date: Tue, 7 Jun 2022 12:58:06 +0200 Subject: [PATCH] chore(CPP/CI): basic CI setup for linux cmake build Linux dockerized build and AppDir generation for compilation errors Also added AppImage TODOs, basic setup for MacOS and Windows but they still need work to have at least validation running Temporary disable CPP windows/mac until limitations are addressed in a follow up commit Extra: add build configuration fixes for rest of the platforms closes: #5998 --- AppRun-cpp | 19 +++++++ app/CMakeLists.txt | 5 ++ app/README.md | 33 +++++++----- ci/Jenkinsfile.linux-cpp | 83 +++++++++++++++++++++++++++++ ci/Jenkinsfile.mac-cpp.todo | 75 ++++++++++++++++++++++++++ ci/Jenkinsfile.windows-cpp.todo | 76 ++++++++++++++++++++++++++ ci/cpp/Dockerfile-linux | 10 ++++ cmake/platform_specific.cmake | 2 + cmake/platform_specific/linux.cmake | 3 ++ libs/Assets/CMakeLists.txt | 6 +++ libs/Core/CMakeLists.txt | 6 +++ libs/Helpers/CMakeLists.txt | 6 +++ libs/Onboarding/CMakeLists.txt | 6 +++ libs/StatusGoQt/CMakeLists.txt | 6 +++ libs/StatusQ/CMakeLists.txt | 6 +++ status.desktop | 8 +++ ui/imports/assets/CMakeLists.txt | 6 +++ 17 files changed, 342 insertions(+), 14 deletions(-) create mode 100755 AppRun-cpp create mode 100644 ci/Jenkinsfile.linux-cpp create mode 100644 ci/Jenkinsfile.mac-cpp.todo create mode 100644 ci/Jenkinsfile.windows-cpp.todo create mode 100644 ci/cpp/Dockerfile-linux create mode 100644 cmake/platform_specific/linux.cmake create mode 100644 status.desktop diff --git a/AppRun-cpp b/AppRun-cpp new file mode 100755 index 0000000000..9b3a2c589a --- /dev/null +++ b/AppRun-cpp @@ -0,0 +1,19 @@ +#!/bin/bash +APPDIR="$(dirname "$(readlink -f "${0}")")" +export GST_PLUGIN_SCANNER="${APPDIR}/usr/lib/gstreamer1.0/gstreamer-1.0/gst-plugin-scanner" +export GST_PLUGIN_PATH="${APPDIR}/usr/lib/gstreamer-1.0" +export GST_PLUGIN_PATH_1_0="${APPDIR}/usr/lib/gstreamer-1.0" +export GST_PLUGIN_SYSTEM_PATH="${APPDIR}/usr/lib/gstreamer-1.0" +export GST_PLUGIN_SYSTEM_PATH_1_0="${APPDIR}/usr/lib/gstreamer-1.0" +export LD_LIBRARY_PATH="${APPDIR}/usr/lib/:${LD_LIBRARY_PATH}" +export QT_QPA_PLATFORM="xcb" + +DEFAULT_LANG=en_US.UTF-8 +if [[ "$LANG" == "C.UTF-8" ]] +then + export LANG=$DEFAULT_LANG +else + export LANG="${VARIABLE:=$DEFAULT_LANG}" +fi + +exec "${APPDIR}/usr/bin/status-desktop" "$@" diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 3e56aaa808..2a54b1f16e 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -64,3 +64,8 @@ target_link_libraries(${PROJECT_NAME} set(QML_IMPORT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/qml;${QML_IMPORT_PATH} CACHE STRING "For QtCreator" FORCE) list(REMOVE_DUPLICATES QML_IMPORT_PATH) +install( + TARGETS + ${PROJECT_NAME} + RUNTIME +) \ No newline at end of file diff --git a/app/README.md b/app/README.md index 4b3a0ff353..474670ceac 100644 --- a/app/README.md +++ b/app/README.md @@ -23,30 +23,29 @@ conan profile update settings.compiler.libcxx=libstdc++11 default ### 2. Install dependencies -```bash -conan install . --profile= -s build_type=Release --build=missing -if=build/conan -``` - Platform specific conan profile - Macos: - - Intel: `vendor/conan-configs/apple-arm64.ini` - - Apple silicon: `vendor/conan-configs/apple-x86_64.ini` + - Intel: `conan install . --profile=vendor/conan-configs/apple-arm64.ini -s build_type=Release --build=missing -if=build/conan` + - Apple silicon: `conan install . --profile=vendor/conan-configs/apple-x86_64.ini -s build_type=Release --build=missing -if=build/conan` - Windows: TODO -- Linux: TODO +- Linux: `conan install . -s build_type=Release --build=missing -if=build/conan` + ## Buid, test & run -Platform specific Qt prefix path - -- Macos: `$HOME/Qt/6.3.0/macos` -- Windows: TODO -- Linux: TODO +Update `CMake` to the [Latest Release](https://cmake.org/download/) ### Build with conan ```bash -CMAKE_PREFIX_PATH= conan build . -if=build/conan -bf=build +# linux +CMAKE_PREFIX_PATH="$HOME/Qt/6.4.0/gcc_64" conan build . -if=build/conan -bf=build + +# MacOS: CMAKE_PREFIX_PATH="$HOME/Qt/6.4.0/macos" conan build . -if=build/conan -bf=build + +# Windows: CMAKE_PREFIX_PATH="$HOME/Qt/6.4.0/mingw_64" conan build . -if=build/conan -bf=build + ctest -VV -C Release ./status-desktop ``` @@ -54,6 +53,12 @@ ctest -VV -C Release ### Build with cmake ```bash -cmake -B build -S . -DCMAKE_PREFIX_PATH= -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=build/conan/conan_toolchain.cmake +# linux +cmake -B build -S . -DCMAKE_PREFIX_PATH="$HOME/Qt/6.4.0/gcc_64" -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=build/conan/conan_toolchain.cmake + +# MacOS: cmake -B build -S . -DCMAKE_PREFIX_PATH="$HOME/Qt/6.4.0/macos" -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=build/conan/conan_toolchain.cmake + +# Windows: cmake -B build -S . -DCMAKE_PREFIX_PATH="$HOME/Qt/6.4.0/mingw_64" -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=build/conan/conan_toolchain.cmake + cmake --build build --config Release ``` diff --git a/ci/Jenkinsfile.linux-cpp b/ci/Jenkinsfile.linux-cpp new file mode 100644 index 0000000000..0709e7812f --- /dev/null +++ b/ci/Jenkinsfile.linux-cpp @@ -0,0 +1,83 @@ +library 'status-jenkins-lib@v1.3.4' + +pipeline { + agent { + dockerfile { + label 'linux' + dir 'ci/cpp' + filename 'Dockerfile-linux' + /* allows jenkins use cat and mounts '/dev/fuse' for linuxdeployqt */ + args '--entrypoint="" --cap-add SYS_ADMIN --security-opt apparmor:unconfined --device /dev/fuse' + } + } + + parameters { + booleanParam( + name: 'RELEASE', + description: 'Decides whether binaries are built with debug symbols.', + defaultValue: params.RELEASE ?: false + ) + } + + options { + timestamps() + /* Prevent Jenkins jobs from running forever */ + timeout(time: 20, unit: 'MINUTES') + /* manage how many builds we keep */ + buildDiscarder(logRotator( + numToKeepStr: '10', + daysToKeepStr: '30', + artifactNumToKeepStr: '3', + )) + } + + environment { + TARGET = 'linux-cpp' + /* Control output the filename */ + STATUS_CLIENT_APPIMAGE = "pkg/${utils.pkgFilename(ext: 'AppImage')}" + } + + // TODO: Move all stages to the Makefile as targets "*-linux-using-docker" + stages { + stage('CMake Build') { + steps { + sh "qt-cmake ${env.WORKSPACE} -G Ninja -B ${env.WORKSPACE}/build -DCMAKE_BUILD_TYPE=Release" + sh "cmake --build ${env.WORKSPACE}/build" + } + } + + stage('Package') { + steps { + sh "linuxdeploy --plugin qt --executable=${env.WORKSPACE}/build/status-desktop --appdir ${env.WORKSPACE}/build/AppDir --desktop-file=${env.WORKSPACE}/status.desktop --icon-file=${env.WORKSPACE}/status.svg --custom-apprun=${env.WORKSPACE}/AppRun-cpp" + sh "cmake --install ${env.WORKSPACE}/build --prefix=${env.WORKSPACE}/build/install" + sh "cp ${env.WORKSPACE}/build/install/lib/* ${env.WORKSPACE}/build/AppDir/usr/lib/" + // TODO enable after deploying appimage plugin in the corresponding docker + //sh "linuxdeploy --appdir ${env.WORKSPACE}/build/AppDir --output=appimage" + // sh "mkdir pkg && cp \"\$(find ${env.WORKSPACE}/build/AppDir -maxdepth 2 -type f -iname \"*.AppImage\")\" ${env.STATUS_CLIENT_APPIMAGE}" + } + } + + // TODO: enable after generating the AppImage + // stage('Parallel Upload') { + // parallel { + // stage('Upload') { + // steps { script { + // env.PKG_URL = s3.uploadArtifact(env.STATUS_CLIENT_APPIMAGE) + // jenkins.setBuildDesc(AppImage: env.PKG_URL) + // } } + // } + // stage('Archive') { + // steps { script { + // archiveArtifacts("${env.STATUS_CLIENT_APPIMAGE}*") + // } } + // } + // } + // } + } + + post { + success { script { github.notifyPR(true) } } + failure { script { github.notifyPR(false) } } + always { cleanWs() } + } +} diff --git a/ci/Jenkinsfile.mac-cpp.todo b/ci/Jenkinsfile.mac-cpp.todo new file mode 100644 index 0000000000..b2e4124266 --- /dev/null +++ b/ci/Jenkinsfile.mac-cpp.todo @@ -0,0 +1,75 @@ +library 'status-jenkins-lib@v1.3.4' + +pipeline { + agent { + docker { + label 'linux' + image 'stateoftheartio/qt6:6.3-macos-aqt' + } + } + + parameters { + booleanParam( + name: 'RELEASE', + description: 'Decides whether binaries are built with debug symbols.', + defaultValue: params.RELEASE ?: false + ) + } + + options { + timestamps() + /* Prevent Jenkins jobs from running forever */ + timeout(time: 20, unit: 'MINUTES') + /* manage how many builds we keep */ + buildDiscarder(logRotator( + numToKeepStr: '10', + daysToKeepStr: '30', + artifactNumToKeepStr: '3', + )) + } + + environment { + TARGET = 'macos-cpp' + /* Control output the filename */ + STATUS_CLIENT_DMG = "pkg/${utils.pkgFilename(ext: 'dmg')}" + } + + // TODO: Move all stages to the Makefile as targets "*-mac-using-docker" + stages { + stage('CMake Build') { + steps { + sh "qt-cmake ${env.WORKSPACE} -G Ninja -B ${env.WORKSPACE}/build -DCMAKE_BUILD_TYPE=Release" + sh "cmake --build ${env.WORKSPACE}/build" + } + } + + stage('Package') { + steps { + sh "macdeployqt ${env.WORKSPACE}/build/*.app -verbose=1 -dmg -qmldir=${env.WORKSPACE}" + sh "mkdir pkg && cp \"\$(find ${env.WORKSPACE}/build -maxdepth 2 -type f -iname \"*.dmg\")\" ${env.STATUS_CLIENT_DMG}" + } + } + + stage('Parallel Upload') { + parallel { + stage('Upload') { + steps { script { + env.PKG_URL = s3.uploadArtifact(env.STATUS_CLIENT_DMG) + jenkins.setBuildDesc(Dmg: env.PKG_URL) + } } + } + stage('Archive') { + steps { script { + archiveArtifacts(env.STATUS_CLIENT_DMG) + } } + } + } + } + } + + post { + success { script { github.notifyPR(true) } } + failure { script { github.notifyPR(false) } } + always { cleanWs() } + } +} diff --git a/ci/Jenkinsfile.windows-cpp.todo b/ci/Jenkinsfile.windows-cpp.todo new file mode 100644 index 0000000000..3ab5959579 --- /dev/null +++ b/ci/Jenkinsfile.windows-cpp.todo @@ -0,0 +1,76 @@ +library 'status-jenkins-lib@v1.3.4' + +pipeline { + agent { + docker { + label 'linux' + image 'stateoftheartio/qt6:6.3-mingw-aqt' + } + } + + parameters { + booleanParam( + name: 'RELEASE', + description: 'Decides whether binaries are built with debug symbols.', + defaultValue: params.RELEASE ?: false + ) + } + + options { + timestamps() + /* Prevent Jenkins jobs from running forever */ + timeout(time: 20, unit: 'MINUTES') + /* manage how many builds we keep */ + buildDiscarder(logRotator( + numToKeepStr: '10', + daysToKeepStr: '30', + artifactNumToKeepStr: '3', + )) + } + + environment { + TARGET = 'windows-cpp' + /* Control output the filename */ + STATUS_CLIENT_ZIP = "pkg/${utils.pkgFilename(ext: 'zip')}" + } + + // TODO: Move all stages to the Makefile as targets "*-windows-using-docker" + stages { + stage('CMake Build') { + steps { + sh "qt-cmake ${env.WORKSPACE} -G Ninja -B ${env.WORKSPACE}/build -DCMAKE_BUILD_TYPE=Release" + sh "cmake --build ${env.WORKSPACE}/build" + } + } + + stage('Package') { + steps { + sh "windeployqt --qmldir ${env.WORKSPACE} --dir ${env.WORKSPACE}/build/deploy --libdir ${env.WORKSPACE}/build/deploy/libs --plugindir ${env.WORKSPACE}/build/deploy/plugins ${env.WORKSPACE}/build/*.exe" + sh "zip -r ${STATUS_CLIENT_ZIP} build/deploy/" + } + } + + stage('Parallel Upload') { + parallel { + stage('Upload') { + steps { script { + exe_url = s3.uploadArtifact(env.STATUS_CLIENT_ZIP) + env.PKG_URL = exe_url + jenkins.setBuildDesc(Zip: zip_url, Exe: exe_url) + } } + } + stage('Archive') { + steps { script { + archiveArtifacts(env.STATUS_CLIENT_ZIP) + } } + } + } + } + } + + post { + success { script { github.notifyPR(true) } } + failure { script { github.notifyPR(false) } } + always { cleanWs() } + } +} diff --git a/ci/cpp/Dockerfile-linux b/ci/cpp/Dockerfile-linux new file mode 100644 index 0000000000..274b963dad --- /dev/null +++ b/ci/cpp/Dockerfile-linux @@ -0,0 +1,10 @@ +FROM stateoftheartio/qt6:6.3-gcc-aqt + +RUN export DEBIAN_FRONTEND=noninteractive \ + && sudo apt update -yq \ + && sudo apt install -yq libgl-dev libvulkan-dev libxcb*-dev libxkbcommon-x11-dev + +# TODO finish installing dependencies then enable building the appimage in CI +# RUN cd /tmp && git clone --single-branch --recursive https://github.com/AppImage/AppImageKit && cd AppImageKit/ && cmake -B ./build -S . +# If still needed +# RUN cd /tmp && git clone --single-branch --recursive https://github.com/linuxdeploy/linuxdeploy-plugin-appimage.git && cd AppImageKit/ && cmake -B ./build -S . \ No newline at end of file diff --git a/cmake/platform_specific.cmake b/cmake/platform_specific.cmake index b4dd4e3ee4..637c29e0e7 100644 --- a/cmake/platform_specific.cmake +++ b/cmake/platform_specific.cmake @@ -2,4 +2,6 @@ if(WIN32) include(${CMAKE_CURRENT_LIST_DIR}/platform_specific/windows.cmake) elseif(APPLE) include(${CMAKE_CURRENT_LIST_DIR}/platform_specific/macos.cmake) +else() + include(${CMAKE_CURRENT_LIST_DIR}/platform_specific/linux.cmake) endif() \ No newline at end of file diff --git a/cmake/platform_specific/linux.cmake b/cmake/platform_specific/linux.cmake new file mode 100644 index 0000000000..12752a6425 --- /dev/null +++ b/cmake/platform_specific/linux.cmake @@ -0,0 +1,3 @@ +function(configure_app_os_specific TARGET_ARG URL_ORGANIZATION_NAME DOMAIN_ARG VERSION_MAJOR VERSION_MINOR VERSION_PATCH) + # Noting here for now; helps simplifying main setup by removing platform if/else conditions +endfunction() \ No newline at end of file diff --git a/libs/Assets/CMakeLists.txt b/libs/Assets/CMakeLists.txt index 178dbab01d..440196fac3 100644 --- a/libs/Assets/CMakeLists.txt +++ b/libs/Assets/CMakeLists.txt @@ -37,3 +37,9 @@ target_link_libraries(${PROJECT_NAME} # QtCreator needs this set(QML_IMPORT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/qml;${QML_IMPORT_PATH} CACHE STRING "For QtCreator" FORCE) list(REMOVE_DUPLICATES QML_IMPORT_PATH) + +install( + TARGETS + ${PROJECT_NAME} + RUNTIME +) \ No newline at end of file diff --git a/libs/Core/CMakeLists.txt b/libs/Core/CMakeLists.txt index 5d193bfd3a..31952c08b9 100644 --- a/libs/Core/CMakeLists.txt +++ b/libs/Core/CMakeLists.txt @@ -30,3 +30,9 @@ target_link_libraries(${PROJECT_NAME} Qt6::Quick Qt6::Qml ) + +install( + TARGETS + ${PROJECT_NAME} + RUNTIME +) \ No newline at end of file diff --git a/libs/Helpers/CMakeLists.txt b/libs/Helpers/CMakeLists.txt index 93384c1082..1cd85ff052 100644 --- a/libs/Helpers/CMakeLists.txt +++ b/libs/Helpers/CMakeLists.txt @@ -55,3 +55,9 @@ target_link_libraries(${PROJECT_NAME} Qt6::Quick Qt6::Qml ) + +install( + TARGETS + ${PROJECT_NAME} + RUNTIME +) \ No newline at end of file diff --git a/libs/Onboarding/CMakeLists.txt b/libs/Onboarding/CMakeLists.txt index 76abc1355d..9f1a67aef2 100644 --- a/libs/Onboarding/CMakeLists.txt +++ b/libs/Onboarding/CMakeLists.txt @@ -30,3 +30,9 @@ target_link_libraries(${PROJECT_NAME} # QtCreator needs this set(QML_IMPORT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/qml;${QML_IMPORT_PATH} CACHE STRING "For QtCreator" FORCE) list(REMOVE_DUPLICATES QML_IMPORT_PATH) + +install( + TARGETS + ${PROJECT_NAME} + RUNTIME +) \ No newline at end of file diff --git a/libs/StatusGoQt/CMakeLists.txt b/libs/StatusGoQt/CMakeLists.txt index 71bef4259a..823d839a7c 100644 --- a/libs/StatusGoQt/CMakeLists.txt +++ b/libs/StatusGoQt/CMakeLists.txt @@ -29,3 +29,9 @@ target_link_libraries(${PROJECT_NAME} # Temporary workaround; TODO: see a better alternative that doesn't depend on target order (dedicated dependencies dir?) get_target_property(STATUSGO_LIBRARY_PATH statusgo_shared IMPORTED_LOCATION) configure_file(${STATUSGO_LIBRARY_PATH} ${CMAKE_CURRENT_BINARY_DIR} COPYONLY) + +install( + TARGETS + ${PROJECT_NAME} + RUNTIME +) \ No newline at end of file diff --git a/libs/StatusQ/CMakeLists.txt b/libs/StatusQ/CMakeLists.txt index c2f16e18be..82d6e70fb7 100644 --- a/libs/StatusQ/CMakeLists.txt +++ b/libs/StatusQ/CMakeLists.txt @@ -25,3 +25,9 @@ add_subdirectory(tests) # QtCreator needs this set(QML_IMPORT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/qml;${QML_IMPORT_PATH} CACHE STRING "For QtCreator" FORCE) list(REMOVE_DUPLICATES QML_IMPORT_PATH) + +install( + TARGETS + ${PROJECT_NAME} + RUNTIME +) \ No newline at end of file diff --git a/status.desktop b/status.desktop new file mode 100644 index 0000000000..63edf1d58d --- /dev/null +++ b/status.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Type=Application +Name=Status Desktop +Exec=status-desktop +Icon=status +Comment=Desktop client for the Status Network +Terminal=false +Categories=Network; diff --git a/ui/imports/assets/CMakeLists.txt b/ui/imports/assets/CMakeLists.txt index 3a28b57390..ab07ad83ae 100644 --- a/ui/imports/assets/CMakeLists.txt +++ b/ui/imports/assets/CMakeLists.txt @@ -38,3 +38,9 @@ target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Qml ) + +install( + TARGETS + ${PROJECT_NAME} + RUNTIME +) \ No newline at end of file