From 9cc20a32a8a654b3944895380b955887cc56c1fe Mon Sep 17 00:00:00 2001 From: Bindea Cristian Date: Mon, 4 Nov 2024 14:34:28 +0200 Subject: [PATCH 1/4] ci/arm: change folder name from armhf to arm Signed-off-by: Bindea Cristian --- .github/workflows/appimage-armhf.yml | 6 +++--- ci/{armhf => arm}/.dockerignore | 0 ci/{armhf => arm}/AppRun | 0 ci/{armhf => arm}/armhf_build_config.sh | 0 ci/{armhf => arm}/armhf_build_process.sh | 0 ci/{armhf => arm}/build_qt.sh | 0 ci/{armhf => arm}/cmake_toolchain.cmake | 0 ci/{armhf => arm}/copy-deps.sh | 0 ci/{armhf => arm}/create_docker_image.sh | 0 ci/{armhf => arm}/create_sysroot.sh | 0 ci/{armhf => arm}/docker/Dockerfile | 0 ci/{armhf => arm}/inside_chroot.sh | 0 ci/{armhf => arm}/local_build_scopy_for_kuiper.sh | 0 ci/{armhf => arm}/qt_patch.patch | 0 ci/{armhf => arm}/runtime-armhf | Bin ci/{armhf => arm}/scopy.desktop | 0 16 files changed, 3 insertions(+), 3 deletions(-) rename ci/{armhf => arm}/.dockerignore (100%) rename ci/{armhf => arm}/AppRun (100%) rename ci/{armhf => arm}/armhf_build_config.sh (100%) rename ci/{armhf => arm}/armhf_build_process.sh (100%) rename ci/{armhf => arm}/build_qt.sh (100%) rename ci/{armhf => arm}/cmake_toolchain.cmake (100%) rename ci/{armhf => arm}/copy-deps.sh (100%) rename ci/{armhf => arm}/create_docker_image.sh (100%) rename ci/{armhf => arm}/create_sysroot.sh (100%) rename ci/{armhf => arm}/docker/Dockerfile (100%) rename ci/{armhf => arm}/inside_chroot.sh (100%) rename ci/{armhf => arm}/local_build_scopy_for_kuiper.sh (100%) rename ci/{armhf => arm}/qt_patch.patch (100%) rename ci/{armhf => arm}/runtime-armhf (100%) rename ci/{armhf => arm}/scopy.desktop (100%) diff --git a/.github/workflows/appimage-armhf.yml b/.github/workflows/appimage-armhf.yml index 3841593ef8..474139ebb6 100644 --- a/.github/workflows/appimage-armhf.yml +++ b/.github/workflows/appimage-armhf.yml @@ -24,8 +24,8 @@ jobs: run: | cd $GITHUB_WORKSPACE sudo apt update - ./ci/armhf/create_sysroot.sh install_packages install_qemu - ./ci/armhf/armhf_build_process.sh generate_ci_envs + ./ci/arm/create_sysroot.sh install_packages install_qemu + ./ci/arm/arm_build_process.sh generate_ci_envs docker run \ --mount type=bind,source="$GITHUB_WORKSPACE",target=/home/runner/scopy \ @@ -34,7 +34,7 @@ jobs: /bin/bash -c 'cd $HOME && \ sudo chown -R runner:runner scopy && \ cd $HOME/scopy && \ - ./ci/armhf/armhf_build_process.sh install_packages move_tools move_sysroot build_scopy build_iio-emu create_appdir create_appimage move_appimage + ./ci/arm/arm_build_process.sh arm32 install_packages move_tools move_sysroot build_scopy build_iio-emu create_appdir create_appimage move_appimage ' - name: Set short git commit SHA shell: bash diff --git a/ci/armhf/.dockerignore b/ci/arm/.dockerignore similarity index 100% rename from ci/armhf/.dockerignore rename to ci/arm/.dockerignore diff --git a/ci/armhf/AppRun b/ci/arm/AppRun similarity index 100% rename from ci/armhf/AppRun rename to ci/arm/AppRun diff --git a/ci/armhf/armhf_build_config.sh b/ci/arm/armhf_build_config.sh similarity index 100% rename from ci/armhf/armhf_build_config.sh rename to ci/arm/armhf_build_config.sh diff --git a/ci/armhf/armhf_build_process.sh b/ci/arm/armhf_build_process.sh similarity index 100% rename from ci/armhf/armhf_build_process.sh rename to ci/arm/armhf_build_process.sh diff --git a/ci/armhf/build_qt.sh b/ci/arm/build_qt.sh similarity index 100% rename from ci/armhf/build_qt.sh rename to ci/arm/build_qt.sh diff --git a/ci/armhf/cmake_toolchain.cmake b/ci/arm/cmake_toolchain.cmake similarity index 100% rename from ci/armhf/cmake_toolchain.cmake rename to ci/arm/cmake_toolchain.cmake diff --git a/ci/armhf/copy-deps.sh b/ci/arm/copy-deps.sh similarity index 100% rename from ci/armhf/copy-deps.sh rename to ci/arm/copy-deps.sh diff --git a/ci/armhf/create_docker_image.sh b/ci/arm/create_docker_image.sh similarity index 100% rename from ci/armhf/create_docker_image.sh rename to ci/arm/create_docker_image.sh diff --git a/ci/armhf/create_sysroot.sh b/ci/arm/create_sysroot.sh similarity index 100% rename from ci/armhf/create_sysroot.sh rename to ci/arm/create_sysroot.sh diff --git a/ci/armhf/docker/Dockerfile b/ci/arm/docker/Dockerfile similarity index 100% rename from ci/armhf/docker/Dockerfile rename to ci/arm/docker/Dockerfile diff --git a/ci/armhf/inside_chroot.sh b/ci/arm/inside_chroot.sh similarity index 100% rename from ci/armhf/inside_chroot.sh rename to ci/arm/inside_chroot.sh diff --git a/ci/armhf/local_build_scopy_for_kuiper.sh b/ci/arm/local_build_scopy_for_kuiper.sh similarity index 100% rename from ci/armhf/local_build_scopy_for_kuiper.sh rename to ci/arm/local_build_scopy_for_kuiper.sh diff --git a/ci/armhf/qt_patch.patch b/ci/arm/qt_patch.patch similarity index 100% rename from ci/armhf/qt_patch.patch rename to ci/arm/qt_patch.patch diff --git a/ci/armhf/runtime-armhf b/ci/arm/runtime-armhf similarity index 100% rename from ci/armhf/runtime-armhf rename to ci/arm/runtime-armhf diff --git a/ci/armhf/scopy.desktop b/ci/arm/scopy.desktop similarity index 100% rename from ci/armhf/scopy.desktop rename to ci/arm/scopy.desktop From d2e488d1403d66987eecc7ba339a6035c53456b5 Mon Sep 17 00:00:00 2001 From: Bindea Cristian Date: Mon, 4 Nov 2024 14:45:07 +0200 Subject: [PATCH 2/4] ci/arm: add new workflow for scopy-arm64 Signed-off-by: Bindea Cristian --- .github/workflows/appimage-arm64.yml | 46 +++++++ .github/workflows/appimage-armhf.yml | 4 +- .gitignore | 14 +- ci/arm/.dockerignore | 7 +- ci/arm/arm_build_config.sh | 106 +++++++++++++++ ..._build_process.sh => arm_build_process.sh} | 117 +++++++++------- ci/arm/armhf_build_config.sh | 64 --------- ci/arm/build_qt.sh | 60 +++++++-- ci/arm/cmake_toolchain.cmake | 107 ++++++++------- ci/arm/copy-deps.sh | 20 +-- ci/arm/create_docker_image.sh | 31 ++++- ci/arm/create_sysroot.sh | 10 +- ci/arm/docker/Dockerfile | 25 ++-- ci/arm/inside_chroot.sh | 58 -------- ci/arm/inside_chroot_arm64.sh | 36 +++++ ci/arm/inside_chroot_armhf.sh | 42 ++++++ ci/arm/local_build_scopy_for_kuiper.sh | 65 ++++----- ci/arm/qt_patch.patch | 126 ------------------ ci/arm/qt_patch_arm64.patch | 41 ++++++ ci/arm/qt_patch_armhf.patch | 54 ++++++++ ci/arm/runtime-aarch64 | Bin 0 -> 196992 bytes ci/x86_64/copy-deps.sh | 3 +- 22 files changed, 604 insertions(+), 432 deletions(-) create mode 100644 .github/workflows/appimage-arm64.yml create mode 100644 ci/arm/arm_build_config.sh rename ci/arm/{armhf_build_process.sh => arm_build_process.sh} (77%) delete mode 100644 ci/arm/armhf_build_config.sh delete mode 100644 ci/arm/inside_chroot.sh create mode 100644 ci/arm/inside_chroot_arm64.sh create mode 100644 ci/arm/inside_chroot_armhf.sh delete mode 100644 ci/arm/qt_patch.patch create mode 100644 ci/arm/qt_patch_arm64.patch create mode 100644 ci/arm/qt_patch_armhf.patch create mode 100644 ci/arm/runtime-aarch64 diff --git a/.github/workflows/appimage-arm64.yml b/.github/workflows/appimage-arm64.yml new file mode 100644 index 0000000000..c134fd867d --- /dev/null +++ b/.github/workflows/appimage-arm64.yml @@ -0,0 +1,46 @@ +name: Scopy arm64 AppImage Build + +on: [push, pull_request] + +env: + BUILD_HOST: ubuntu-20.04 + USERNAME: github-actions + +jobs: + + build_scopy_arm64_appimage: + runs-on: ubuntu-20.04 + + steps: + - uses: actions/checkout@v4 + with: + set-safe-directory: 'true' + + - name: Pull the Docker Image + run: docker pull cristianbindea/scopy2-arm64-appimage:latest + + - name: Create Scopy AppImage + shell: bash + run: | + cd $GITHUB_WORKSPACE + sudo apt update + ./ci/arm/create_sysroot.sh arm64 install_packages install_qemu + ./ci/arm/arm_build_process.sh arm64 generate_ci_envs + + docker run \ + --mount type=bind,source="$GITHUB_WORKSPACE",target=/home/runner/scopy \ + --env-file $GITHUB_WORKSPACE/ci/general/gh-actions.envs \ + cristianbindea/scopy2-arm64-appimage:latest \ + /bin/bash -c 'cd $HOME && \ + sudo chown -R runner:runner scopy && \ + cd $HOME/scopy && \ + ./ci/arm/arm_build_process.sh arm64 install_packages move_tools move_sysroot build_scopy build_iio-emu create_appdir create_appimage move_appimage + ' + - name: Set short git commit SHA + shell: bash + run: echo "commit_sha=$(git rev-parse --short ${{ github.sha }})" >> "$GITHUB_ENV" + + - uses: actions/upload-artifact@v4 + with: + name: scopy-linux-arm64-${{ env.commit_sha }} + path: ${{ github.workspace }}/Scopy-arm64.AppImage diff --git a/.github/workflows/appimage-armhf.yml b/.github/workflows/appimage-armhf.yml index 474139ebb6..d729ada587 100644 --- a/.github/workflows/appimage-armhf.yml +++ b/.github/workflows/appimage-armhf.yml @@ -24,8 +24,8 @@ jobs: run: | cd $GITHUB_WORKSPACE sudo apt update - ./ci/arm/create_sysroot.sh install_packages install_qemu - ./ci/arm/arm_build_process.sh generate_ci_envs + ./ci/arm/create_sysroot.sh arm32 install_packages install_qemu + ./ci/arm/arm_build_process.sh arm32 generate_ci_envs docker run \ --mount type=bind,source="$GITHUB_WORKSPACE",target=/home/runner/scopy \ diff --git a/.gitignore b/.gitignore index c5590c69a7..a90b0c196c 100644 --- a/.gitignore +++ b/.gitignore @@ -37,12 +37,14 @@ build/* ci/general/gh-actions.envs ci/ubuntu/staging ci/macOS/staging -ci/armhf/staging -ci/armhf/docker/sysroot* -ci/armhf/scopy.AppDir -ci/armhf/staging -ci/armhf/scopy.AppDir -ci/armhf/scopy.squashfs +ci/arm/staging +ci/arm/docker/sysroot* +ci/arm/scopy.AppDir +ci/arm/staging +ci/arm/scopy.AppDir +ci/arm/scopy.squashfs +ci/arm/squashfs-root +ci/arm/sysroot ci/x86_64/staging ci/x86_64/scopy.AppDir ci/windows/staging diff --git a/ci/arm/.dockerignore b/ci/arm/.dockerignore index d1925e0386..5ded1c6247 100644 --- a/ci/arm/.dockerignore +++ b/ci/arm/.dockerignore @@ -1,10 +1,11 @@ * !sysroot.tar.gz -!armhf_build_process.sh -!armhf_build_config.sh +!arm_build_process.sh +!arm_build_config.sh !cmake_toolchain.cmake !create_sysroot.sh !copy-deps.sh !inside_chroot.sh !build_qt.sh -!qt_patch.patch \ No newline at end of file +!qt_patch_armhf.patch +!qt_patch_arm64.patch \ No newline at end of file diff --git a/ci/arm/arm_build_config.sh b/ci/arm/arm_build_config.sh new file mode 100644 index 0000000000..5c4d27266f --- /dev/null +++ b/ci/arm/arm_build_config.sh @@ -0,0 +1,106 @@ +#!/bin/bash + +if [ "$1" == "arm64" ];then + echo "Building for aarch64" + TOOLCHAIN_HOST="aarch64-linux-gnu" +elif [ "$1" == "arm32" ]; then + echo "Building for armhf" + TOOLCHAIN_HOST="arm-linux-gnueabihf" +else + echo "$1 is invalid. Enter first argument arm32 or arm64 to choose the toolchain" + exit +fi + +LIBSERIALPORT_BRANCH=scopy-v2 +LIBIIO_VERSION=v0.26 +LIBAD9361_BRANCH=main +GLOG_BRANCH=v0.4.0 +LIBM2K_BRANCH=main +SPDLOG_BRANCH=v1.x +VOLK_BRANCH=main +GNURADIO_BRANCH=scopy2-maint-3.10 +GRSCOPY_BRANCH=3.10 +GRM2K_BRANCH=main +LIBSIGROKDECODE_BRANCH=master +QWT_BRANCH=qwt-multiaxes-updated +LIBTINYIIOD_BRANCH=master +IIOEMU_BRANCH=main +KDDOCK_BRANCH=2.1 + +export APPIMAGE=1 + +SRC_SCRIPT=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +[ $CI_SCRIPT == "ON" ] && STAGING_AREA=$HOME/scopy/ci/arm/staging || STAGING_AREA=$SRC_SCRIPT/staging +SYSROOT=$STAGING_AREA/sysroot +SYSROOT_TAR=$STAGING_AREA/sysroot.tar.gz +TOOLCHAIN=$STAGING_AREA/cross-pi-gcc +TOOLCHAIN_BIN=$TOOLCHAIN/bin +TOOLCHAIN_FILE=$SRC_SCRIPT/cmake_toolchain.cmake +QT_LOCATION=$SYSROOT/usr/lib/$TOOLCHAIN_HOST/qt5 + +CMAKE_BIN=$STAGING_AREA/cmake/bin/cmake +QMAKE_BIN=$QT_LOCATION/bin/qmake +JOBS=-j14 + +APP_DIR=$SRC_SCRIPT/scopy.AppDir +APP_IMAGE=$SRC_SCRIPT/Scopy.AppImage +APP_RUN=$SRC_SCRIPT/AppRun +APP_DESKTOP=$SRC_SCRIPT/scopy.desktop +APP_SQUASHFS=$SRC_SCRIPT/scopy.squashfs + +# Runetimes downloaded from https://github.com/AppImage/AppImageKit/releases/continuous Mar 9, 2023 +if [ $TOOLCHAIN_HOST == "aarch64-linux-gnu" ]; then + RUNTIME_ARM=$SRC_SCRIPT/runtime-aarch64 +elif [ $TOOLCHAIN_HOST == "arm-linux-gnueabihf" ]; then + RUNTIME_ARM=$SRC_SCRIPT/runtime-armhf +fi + +if [ $TOOLCHAIN_HOST == "aarch64-linux-gnu" ]; then + CMAKE_SYSTEM_PROCESSOR=aarch64 + CMAKE_LIBRARY_ARCHITECTURE=aarch64-linux-gnu +elif [ $TOOLCHAIN_HOST == "arm-linux-gnueabihf" ]; then + CMAKE_SYSTEM_PROCESSOR=arm + CMAKE_LIBRARY_ARCHITECTURE=arm-linux-gnueabihf +fi + +# The exports below ensure these variables are available to the toolchain file. +export CMAKE_SYSROOT="$SYSROOT" +export QT_LOCATION="$QT_LOCATION" +export STAGING_AREA="$STAGING_AREA" +export CMAKE_SYSTEM_PROCESSOR="$CMAKE_SYSTEM_PROCESSOR" +export CMAKE_LIBRARY_ARCHITECTURE="$CMAKE_LIBRARY_ARCHITECTURE" + +CMAKE_OPTS=(\ + -DCMAKE_INSTALL_PREFIX="$SYSROOT" \ + -DCMAKE_TOOLCHAIN_FILE="$TOOLCHAIN_FILE" \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + ) + +CMAKE="$CMAKE_BIN ${CMAKE_OPTS[*]}" + +if [ $TOOLCHAIN_HOST == "aarch64-linux-gnu" ]; then + QT_DEVICE=linux-rasp-pi4-aarch64 +elif [ $TOOLCHAIN_HOST == "arm-linux-gnueabihf" ]; then + QT_DEVICE="linux-rasp-pi4-v3d-g++" +fi + +QT_BUILD_LOCATION=$QT_LOCATION # the location where Qt will be installed in the system +QT_SYSTEM_LOCATION=/usr/lib/$TOOLCHAIN_HOST/qt5 # the Qt location relative to the sysroot folder +CROSS_COMPILER=$STAGING_AREA/cross-pi-gcc + +if [ $TOOLCHAIN_HOST == "aarch64-linux-gnu" ]; then + CROSSCOMPILER_DOWNLOAD_LINK=https://sourceforge.net/projects/raspberry-pi-cross-compilers/files/Bonus%20Raspberry%20Pi%20GCC%2064-Bit%20Toolchains/Raspberry%20Pi%20GCC%2064-Bit%20Cross-Compiler%20Toolchains/Bookworm/GCC%2012.2.0/cross-gcc-12.2.0-pi_64.tar.gz +elif [ $TOOLCHAIN_HOST == "arm-linux-gnueabihf" ]; then + CROSSCOMPILER_DOWNLOAD_LINK=https://sourceforge.net/projects/raspberry-pi-cross-compilers/files/Raspberry%20Pi%20GCC%20Cross-Compiler%20Toolchains/Bullseye/GCC%2010.2.0/Raspberry%20Pi%203A%2B%2C%203B%2B%2C%204%2C%205/cross-gcc-10.2.0-pi_3%2B.tar.gz +fi + +CMAKE_DOWNLOAD_LINK=https://github.com/Kitware/CMake/releases/download/v3.29.0-rc2/cmake-3.29.0-rc2-linux-x86_64.tar.gz +KUIPER_DOWNLOAD_LINK=https://swdownloads.analog.com/cse/kuiper/image_2023-12-13-ADI-Kuiper-full.zip + +if [ $TOOLCHAIN_HOST == "aarch64-linux-gnu" ]; then + QT_DOWNLOAD_LINK=https://download.qt.io/archive/qt/5.15/5.15.10/single/qt-everywhere-opensource-src-5.15.10.tar.xz +elif [ $TOOLCHAIN_HOST == "arm-linux-gnueabihf" ]; then + QT_DOWNLOAD_LINK=http://download.qt.io/archive/qt/5.15/5.15.2/single/qt-everywhere-src-5.15.2.tar.xz +fi + +SYSROOT_RELATIVE_LINKS=https://raw.githubusercontent.com/abhiTronix/rpi_rootfs/master/scripts/sysroot-relativelinks.py diff --git a/ci/arm/armhf_build_process.sh b/ci/arm/arm_build_process.sh similarity index 77% rename from ci/arm/armhf_build_process.sh rename to ci/arm/arm_build_process.sh index 30af9f4a50..412a04f379 100755 --- a/ci/arm/armhf_build_process.sh +++ b/ci/arm/arm_build_process.sh @@ -7,19 +7,20 @@ SRC_SCRIPT=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) BUILD_STATUS_FILE=$SRC_SCRIPT/build-status -source $SRC_SCRIPT/armhf_build_config.sh +source $SRC_SCRIPT/arm_build_config.sh $1 echo -- USING CMAKE COMMAND: echo $CMAKE -echo -- USING QT: $QT +echo -- USING QT: $QT_LOCATION echo -- USING QMAKE: $QMAKE_BIN +echo -- SYSROOT: $SYSROOT build_with_cmake() { BUILD_FOLDER=$PWD/build rm -rf $BUILD_FOLDER mkdir -p $BUILD_FOLDER cd $BUILD_FOLDER - $CMAKE $CURRENT_BUILD_CMAKE_OPTS ../ + eval "$CMAKE $CURRENT_BUILD_CMAKE_OPTS ../" make $JOBS CURRENT_BUILD_CMAKE_OPTS="" @@ -29,31 +30,38 @@ build_with_cmake() { set_config_opts() { CPP="${TOOLCHAIN_BIN}/${TOOLCHAIN_HOST}-cpp" - CC="${TOOLCHAIN_BIN}/${TOOLCHAIN_HOST}-gcc" + CC="${TOOLCHAIN_BIN}/${TOOLCHAIN_HOST}-gcc -v" CXX="${TOOLCHAIN_BIN}/${TOOLCHAIN_HOST}-g++" LD="${TOOLCHAIN_BIN}/${TOOLCHAIN_HOST}-ld" AS="${TOOLCHAIN_BIN}/${TOOLCHAIN_HOST}-as" AR="${TOOLCHAIN_BIN}/${TOOLCHAIN_HOST}-ar" RANLIB="${TOOLCHAIN_BIN}/${TOOLCHAIN_HOST}-ranlib" - CFLAGS=" -I${SYSROOT}/include -I${SYSROOT}/include/arm-linux-gnueabihf -I${SYSROOT}/usr/include -I${SYSROOT}/usr/include/arm-linux-gnueabihf -I${TOOLCHAIN}/include- -fPIC" + CFLAGS=" -I${SYSROOT}/include -I${SYSROOT}/include/${TOOLCHAIN_HOST} -I${SYSROOT}/usr/include -I${SYSROOT}/usr/include/${TOOLCHAIN_HOST} -I${TOOLCHAIN}/include- -fPIC" CPPFLAGS="-fexceptions ${CFLAGS}" - LDFLAGS="-Wl,-rpath=XORIGIN -L${TOOLCHAIN}/arm-linux-gnueabihf/lib -L${TOOLCHAIN}/arm-linux-gnueabihf/libc/lib -L${TOOLCHAIN}/arm-linux-gnueabihf/libc/usr/lib -L${SYSROOT}/lib -L${SYSROOT}/usr/lib -L${SYSROOT}/usr/lib/arm-linux-gnueabihf -L${SYSROOT}/usr/lib/arm-linux-gnueabihf" + LDFLAGS="--sysroot=${SYSROOT} -Wl,-rpath=XORIGIN -L${SYSROOT}/lib -L${SYSROOT}/usr/lib -L${SYSROOT}/usr/lib/${TOOLCHAIN_HOST} -L${SYSROOT}/usr/lib/${TOOLCHAIN_HOST}" CONFIG_OPTS=() CONFIG_OPTS+=("--prefix=${SYSROOT}") CONFIG_OPTS+=("--host=${TOOLCHAIN_HOST}") CONFIG_OPTS+=("--with-sysroot=${SYSROOT}") - CONFIG_OPTS+=("CFLAGS=${CFLAGS}") - CONFIG_OPTS+=("CPPFLAGS=${CPPFLAGS}") - CONFIG_OPTS+=("LDFLAGS=${LDFLAGS}") - CONFIG_OPTS+=("PKG_CONFIG=${SYSROOT}/usr/bin/arm-linux-gnueabihf-pkg-config" ) CONFIG_OPTS+=("PKG_CONFIG_DIR=") - CONFIG_OPTS+=("PKG_CONFIG_LIBDIR=${SYSROOT}/usr/lib/arm-linux-gnueabihf/pkgconfig:${SYSROOT}/usr/share/pkgconfig:${SYSROOT}/usr/lib/arm-linux-gnueabihf/pkgconfig:${SYSROOT}/usr/local/lib/pkgconfig") + CONFIG_OPTS+=("PKG_CONFIG_LIBDIR=${SYSROOT}/usr/lib/${TOOLCHAIN_HOST}/pkgconfig:${SYSROOT}/usr/share/pkgconfig:${SYSROOT}/usr/lib/${TOOLCHAIN_HOST}/pkgconfig:${SYSROOT}/usr/local/lib/pkgconfig") CONFIG_OPTS+=("PKG_CONFIG_SYSROOT=${SYSROOT}") CONFIG_OPTS+=("PKG_CONFIG_SYSROOT_DIR=${SYSROOT}") - CONFIG_OPTS+=("PKG_CONFIG_PATH=${SYSROOT}/usr/bin/arm-linux-gnueabihf-pkg-config") + + if [ "$TOOLCHAIN_HOST" == "aarch64-linux-gnu" ]; then + CONFIG_OPTS+=("PKG_CONFIG_PATH=${SYSROOT}/usr/lib/${TOOLCHAIN_HOST}/pkgconfig") + CONFIG_OPTS+=("PKG_CONFIG=/usr/bin/${TOOLCHAIN_HOST}-pkg-config" ) + elif [ "$TOOLCHAIN_HOST" == "arm-linux-gnueabihf" ]; then + CONFIG_OPTS+=("PKG_CONFIG_PATH=${SYSROOT}/usr/bin/arm-linux-gnueabihf-pkg-config") + CONFIG_OPTS+=("PKG_CONFIG=${SYSROOT}/usr/bin/${TOOLCHAIN_HOST}-pkg-config" ) + fi + CONFIG_OPTS+=("PKG_CONFIG_ALLOW_CROSS=1") + CONFIG_OPTS+=("LDFLAGS=${LDFLAGS}") + CONFIG_OPTS+=("CFLAGS=${CFLAGS}") + CONFIG_OPTS+=("CPPFLAGS=${CPPFLAGS}") CONFIG_OPTS+=("CPP=${CPP}") CONFIG_OPTS+=("CC=${CC}") CONFIG_OPTS+=("CXX=${CXX}") @@ -66,8 +74,8 @@ set_config_opts() { install_packages() { sudo apt update sudo apt install -y build-essential cmake unzip gfortran gcc git bison libtool \ - ${PYTHON_VERSION}-full pip gperf pkg-config gdb-multiarch g++ flex texinfo gawk openssl \ - pigz libncurses-dev autoconf automake tar figlet liborc-0.4-dev* patchelf libc6-dev-armhf-cross squashfs-tools + python3 pip gperf pkg-config gdb-multiarch g++ flex texinfo gawk openssl pkg-config-aarch64-linux-gnu \ + pigz libncurses-dev autoconf automake tar figlet liborc-0.4-dev* patchelf libc6-dev-arm64-cross squashfs-tools pip install mako } @@ -116,6 +124,7 @@ clone() { [ -d 'KDDockWidgets' ] || git clone --recursive https://github.com/KDAB/KDDockWidgets.git -b $KDDOCK_BRANCH KDDockWidgets popd } + build_libserialport(){ echo "### Building libserialport - branch $LIBSERIALPORT_BRANCH" pushd $STAGING_AREA/libserialport @@ -143,14 +152,10 @@ build_libiio() { -DPYTHON_BINDINGS:BOOL=OFF \ -DWITH_SERIAL_BACKEND:BOOL=ON \ -DENABLE_IPV6:BOOL=OFF \ - -DINSTALL_UDEV_RULE:BOOL=OFF + -DINSTALL_UDEV_RULE:BOOL=OFF \ " - if [ -d 'build' ];then - echo "### IIO-EMU already built --- skipping" - else build_with_cmake sudo make install - fi popd } @@ -180,7 +185,7 @@ build_libm2k() { -DBUILD_EXAMPLES=OFF \ -DENABLE_TOOLS=OFF \ -DINSTALL_UDEV_RULES=OFF \ - -DENABLE_LOG=OFF + -DENABLE_LOG=OFF \ " build_with_cmake sudo make install @@ -206,7 +211,7 @@ build_gnuradio() { -DENABLE_GR_FFT=ON \ -DENABLE_GR_FILTER=ON \ -DENABLE_GR_IIO=ON \ - -DENABLE_POSTINSTALL=OFF + -DENABLE_POSTINSTALL=OFF \ " build_with_cmake sudo make install @@ -226,7 +231,7 @@ build_grm2k() { pushd $STAGING_AREA/gr-m2k CURRENT_BUILD_CMAKE_OPTS="\ -DENABLE_PYTHON=OFF \ - -DDIGITAL=OFF + -DDIGITAL=OFF \ " build_with_cmake sudo make install @@ -238,7 +243,7 @@ build_qwt() { pushd $STAGING_AREA/qwt git clean -xdf sed -i 's|/usr/local/qwt-$$QWT_VERSION-ma|/usr/local|g' qwtconfig.pri - $QMAKE_BIN INCLUDEPATH=$SYSROOT/include LIBS=-L$SYSROOT/lib qwt.pro + $QMAKE_BIN INCLUDEPATH=$SYSROOT/include LIBS=-L$SYSROOT/lib LIBS+=-L$SYSROOT/lib/$TOOLCHAIN_HOST qwt.pro make $JOBS patchelf --force-rpath --set-rpath \$ORIGIN $STAGING_AREA/qwt/lib/libqwt.so sudo make INSTALL_ROOT=$SYSROOT install @@ -287,6 +292,7 @@ build_iio-emu(){ pushd $STAGING_AREA [ -d 'iio-emu' ] || git clone --recursive https://github.com/analogdevicesinc/iio-emu -b $IIOEMU_BRANCH iio-emu pushd $STAGING_AREA/iio-emu + CURRENT_BUILD_CMAKE_OPTS="-DCMAKE_EXE_LINKER_FLAGS=\"-ldl -lz -licuuc -licudata -llzma\"" # ??? build_with_cmake sudo make install popd @@ -300,7 +306,6 @@ build_scopy() { CURRENT_BUILD_CMAKE_OPTS="\ -DENABLE_PLUGIN_TEST=ON \ -DENABLE_TESTING=ON \ - -DPYTHON_EXECUTABLE=/usr/bin/python3.9 " build_with_cmake popd @@ -317,7 +322,7 @@ create_appdir(){ EMU_CONFIG=$SRC_DIR/resources/scopy_emu_options_config.json TRANSLATIONS_QM=$(find $BUILD_FOLDER/translations -type f -name "*.qm") STYLE_FOLDER=$BUILD_FOLDER/style - COPY_DEPS=$SRC_DIR/ci/armhf/copy-deps.sh + COPY_DEPS=$SRC_DIR/ci/arm/copy-deps.sh rm -rf $APP_DIR mkdir -p $APP_DIR @@ -353,10 +358,10 @@ create_appdir(){ mkdir -p $APP_DIR/usr/lib/scopy/plugins/resources cp $EMU_CONFIG $APP_DIR/usr/lib/scopy/plugins/resources - $COPY_DEPS $APP_DIR/usr/bin/scopy $APP_DIR/usr/lib - $COPY_DEPS $APP_DIR/usr/bin/iio-emu $APP_DIR/usr/lib - $COPY_DEPS $APP_DIR/usr/bin/scopy $APP_DIR/usr/lib - $COPY_DEPS "$APP_DIR/usr/lib/scopy/plugins/*.so" $APP_DIR/usr/lib + $COPY_DEPS ${TOOLCHAIN_HOST} $APP_DIR/usr/bin/scopy $APP_DIR/usr/lib + $COPY_DEPS ${TOOLCHAIN_HOST} $APP_DIR/usr/bin/iio-emu $APP_DIR/usr/lib + $COPY_DEPS ${TOOLCHAIN_HOST} $APP_DIR/usr/bin/scopy $APP_DIR/usr/lib + $COPY_DEPS ${TOOLCHAIN_HOST} "$APP_DIR/usr/lib/scopy/plugins/*.so" $APP_DIR/usr/lib cp -r $QT_LOCATION/plugins $APP_DIR/usr # search for the python version linked by cmake and copy inside the appimage the same version @@ -369,17 +374,18 @@ create_appdir(){ cp $QT_LOCATION/lib/libQt5XcbQpa.so* $APP_DIR/usr/lib cp $QT_LOCATION/lib/libQt5EglFSDeviceIntegration.so* $APP_DIR/usr/lib cp $QT_LOCATION/lib/libQt5DBus.so* $APP_DIR/usr/lib - cp $SYSROOT/lib/arm-linux-gnueabihf/libGLESv2.so* $APP_DIR/usr/lib - cp $SYSROOT/lib/arm-linux-gnueabihf/libbsd.so* $APP_DIR/usr/lib - cp $SYSROOT/lib/arm-linux-gnueabihf/libXdmcp.so* $APP_DIR/usr/lib - cp $SYSROOT/usr/lib/arm-linux-gnueabihf/libXau.so* $APP_DIR/usr/lib - cp $SYSROOT/usr/lib/arm-linux-gnueabihf/libffi.so* $APP_DIR/usr/lib + cp $QT_LOCATION/lib/libQt5OpenGL.so* $APP_DIR/usr/lib + cp $SYSROOT/lib/${TOOLCHAIN_HOST}/libGLESv2.so* $APP_DIR/usr/lib + cp $SYSROOT/lib/${TOOLCHAIN_HOST}/libbsd.so* $APP_DIR/usr/lib + cp $SYSROOT/lib/${TOOLCHAIN_HOST}/libXdmcp.so* $APP_DIR/usr/lib + cp $SYSROOT/usr/lib/${TOOLCHAIN_HOST}/libXau.so* $APP_DIR/usr/lib + cp $SYSROOT/usr/lib/${TOOLCHAIN_HOST}/libffi.so* $APP_DIR/usr/lib } create_appimage(){ rm -rf $APP_IMAGE mksquashfs $APP_DIR $APP_SQUASHFS -root-owned -noappend - cat $RUNTIME_ARMHF >> $APP_IMAGE + cat $RUNTIME_ARM >> $APP_IMAGE cat $APP_SQUASHFS >> $APP_IMAGE chmod a+x $APP_IMAGE } @@ -406,7 +412,11 @@ move_tools(){ # move and rename the AppImage artifact move_appimage(){ - mv $APP_IMAGE $SRC_DIR/Scopy-armhf.AppImage + if [ $TOOLCHAIN_HOST == "aarch64-linux-gnu" ]; then + mv $APP_IMAGE $SRC_DIR/Scopy-arm64.AppImage + elif [ $TOOLCHAIN_HOST == "arm-linux-gnueabihf" ]; then + mv $APP_IMAGE $SRC_DIR/Scopy-armhf.AppImage + fi } generate_ci_envs() @@ -419,6 +429,7 @@ generate_ci_envs() # Helper functions # build_deps(){ + clone build_libserialport build_libiio build_libad9361 @@ -431,13 +442,12 @@ build_deps(){ build_qwt build_libsigrokdecode build_libtinyiiod - #build_kddock + # build_kddock temporary disabled } run_workflow(){ install_packages - download_cmake - download_crosscompiler + move_tools move_sysroot build_iio-emu build_scopy @@ -448,8 +458,7 @@ run_workflow(){ get_tools(){ install_packages - download_cmake - download_crosscompiler + move_tools move_sysroot } @@ -461,26 +470,32 @@ generate_appimage(){ } dev_setup(){ - # for the local development of Scopy armhf the easyest method is to download the docker image - # a temporary docker volume is created to bridge the local environment and the docker container - # the compiling is done inside the container unsing the already prepared filesystem - docker pull cristianbindea/scopy2-armhf-appimage:latest + # for the local development of Scopy arm the easyest method is to download the docker image + # after that, a temporary docker volume is created to bridge the local environment and the docker container + # and the compiling is done inside the container unsing the already prepared filesystem + + # for example, if you want to develop for ARMHF architecture, you would execute: + docker pull cristianbindea/scopy2-armhf-appimage:latest # to download the image + + # and to run the image, while creating a docker volume, you would run: docker run -it \ --mount type=bind,source="$SRC_DIR",target=/home/runner/scopy \ cristianbindea/scopy2-armhf-appimage:latest + + # now this repository folder it shared with the docker container - # to compile the application use "scopy/ci/armhf/armhf_build_process.sh get_tools generate_appimage" - # after the first compilation just use "scopy/ci/armhf/armhf_build_process.sh generate_appimage" - # to continue using the same docker container use docker start (container id) and "docker attach (container id)" + # to compile and package the application use "scopy/ci/arm/arm_build_process.sh run_workflow" + + # to continue using the same docker container use "docker start (container id)" and "docker attach (container id)" # finally after the development is done use this to clean the system # "docker container rm -v (container id)" - # "docker image rm cristianbindea/scopy2-armhf-appimage:latest" + # "docker image rm cristianbindea/scopy2-arm-appimage:latest" - # to get the container id use "docker container ls -a" + # **to get the container id use "docker container ls -a" } -for arg in $@; do +for arg in "${@:2}"; do $arg done diff --git a/ci/arm/armhf_build_config.sh b/ci/arm/armhf_build_config.sh deleted file mode 100644 index 2f74524984..0000000000 --- a/ci/arm/armhf_build_config.sh +++ /dev/null @@ -1,64 +0,0 @@ -#!/bin/bash - -LIBSERIALPORT_BRANCH=scopy-v2 -LIBIIO_VERSION=v0.26 -LIBAD9361_BRANCH=main -GLOG_BRANCH=v0.4.0 -LIBM2K_BRANCH=main -SPDLOG_BRANCH=v1.x -VOLK_BRANCH=main -GNURADIO_BRANCH=scopy2-maint-3.10 -GRSCOPY_BRANCH=3.10 -GRM2K_BRANCH=main -LIBSIGROKDECODE_BRANCH=master -QWT_BRANCH=qwt-multiaxes-updated -LIBTINYIIOD_BRANCH=master -IIOEMU_BRANCH=main -KDDOCK_BRANCH=2.1 - -export APPIMAGE=1 - -PYTHON_VERSION=python3.9 # default python version used in CI scripts, can be changed to match locally installed python - -SRC_SCRIPT=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -[ $CI_SCRIPT == "ON" ] && STAGING_AREA=$HOME/scopy/ci/armhf/staging || STAGING_AREA=$SRC_SCRIPT/staging -SYSROOT=$STAGING_AREA/sysroot -SYSROOT_TAR=$STAGING_AREA/sysroot.tar.gz -TOOLCHAIN=$STAGING_AREA/cross-pi-gcc -TOOLCHAIN_BIN=$TOOLCHAIN/bin -TOOLCHAIN_HOST="arm-linux-gnueabihf" -TOOLCHAIN_FILE=$SRC_SCRIPT/cmake_toolchain.cmake -QT_LOCATION=$SYSROOT/usr/local/qt5.15 - -CMAKE_BIN=$STAGING_AREA/cmake/bin/cmake -QMAKE_BIN=$QT_LOCATION/bin/qmake -JOBS=-j14 - -APP_DIR=$SRC_SCRIPT/scopy.AppDir -APP_IMAGE=$SRC_SCRIPT/Scopy.AppImage -APP_RUN=$SRC_SCRIPT/AppRun -APP_DESKTOP=$SRC_SCRIPT/scopy.desktop -APP_SQUASHFS=$SRC_SCRIPT/scopy.squashfs -RUNTIME_ARMHF=$SRC_SCRIPT/runtime-armhf - -CMAKE_OPTS=(\ - -DCMAKE_SYSROOT="$SYSROOT" \ - -DQT_LOCATION="$QT_LOCATION" \ - -DSTAGING_AREA="$STAGING_AREA" \ - -DCMAKE_INSTALL_PREFIX="$SYSROOT" \ - -DCMAKE_TOOLCHAIN_FILE="$TOOLCHAIN_FILE" \ - -DCMAKE_BUILD_TYPE=RelWithDebInfo \ - -DCMAKE_VERBOSE_MAKEFILE=ON \ - ) - -CMAKE="$CMAKE_BIN ${CMAKE_OPTS[*]}" - -QT_BUILD_LOCATION=$QT_LOCATION # the location where Qt will be installed in the system -QT_SYSTEM_LOCATION=/usr/local/qt5.15 # the Qt location relative to the sysroot folder -CROSS_COMPILER=$STAGING_AREA/cross-pi-gcc - -CROSSCOMPILER_DOWNLOAD_LINK=https://sourceforge.net/projects/raspberry-pi-cross-compilers/files/Raspberry%20Pi%20GCC%20Cross-Compiler%20Toolchains/Bullseye/GCC%2010.2.0/Raspberry%20Pi%203A%2B%2C%203B%2B%2C%204%2C%205/cross-gcc-10.2.0-pi_3%2B.tar.gz -CMAKE_DOWNLOAD_LINK=https://github.com/Kitware/CMake/releases/download/v3.29.0-rc2/cmake-3.29.0-rc2-linux-x86_64.tar.gz -KUIPER_DOWNLOAD_LINK=https://swdownloads.analog.com/cse/kuiper/image_2023-12-13-ADI-Kuiper-full.zip -QT_DOWNLOAD_LINK=http://download.qt.io/archive/qt/5.15/5.15.2/single/qt-everywhere-src-5.15.2.tar.xz -SYSROOT_RELATIVE_LINKS=https://raw.githubusercontent.com/abhiTronix/rpi_rootfs/master/scripts/sysroot-relativelinks.py diff --git a/ci/arm/build_qt.sh b/ci/arm/build_qt.sh index 40b3f16df4..0c13129917 100755 --- a/ci/arm/build_qt.sh +++ b/ci/arm/build_qt.sh @@ -2,23 +2,28 @@ set -ex SRC_SCRIPT=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -source $SRC_SCRIPT/armhf_build_config.sh +source $SRC_SCRIPT/arm_build_config.sh $1 install_packages(){ sudo apt install -y build-essential cmake unzip gfortran gcc git bison \ - python gperf pkg-config gdb-multiarch g++ flex texinfo gawk openssl \ + gperf pkg-config gdb-multiarch g++ flex texinfo gawk openssl \ pigz libncurses-dev autoconf automake tar figlet libclang-dev } -# Download and extract QT Source (QT 5.15.2) +# Download and extract QT Source (QT 5.15.2 for armhf and QT 5.15.10 for arm64) download_qt(){ mkdir -p ${STAGING_AREA} pushd ${STAGING_AREA} if [ ! -d qt-everywhere-src ];then wget --progress=dot:giga ${QT_DOWNLOAD_LINK} - tar -xf qt-everywhere-src-*.tar.xz && rm qt-everywhere-src-*.tar.xz && mv qt-everywhere-src-* qt-everywhere-src # unzip and rename + tar -xf qt-everywhere-*.tar.xz && rm qt-everywhere-*.tar.xz && mv qt-everywhere-* qt-everywhere-src # unzip and rename cd qt-everywhere-src - patch -p1 < $SRC_SCRIPT/qt_patch.patch # Patch QT Source + # Patch QT Source + if [ $TOOLCHAIN_HOST == "aarch64-linux-gnu" ]; then + patch -p1 -R < $SRC_SCRIPT/qt_patch_arm64.patch + elif [ $TOOLCHAIN_HOST == "arm-linux-gnueabihf" ]; then + patch -p1 < $SRC_SCRIPT/qt_patch_armhf.patch + fi else echo "QT already downloaded" fi @@ -37,23 +42,50 @@ download_crosscompiler(){ popd } -build_qt5.15.2(){ - mkdir -p $STAGING_AREA/build-qt5.15.2 && cd $STAGING_AREA/build-qt5.15.2 +build(){ + mkdir -p "$STAGING_AREA"/build-qt && cd "$STAGING_AREA"/build-qt ../qt-everywhere-src/configure \ -v \ -release \ -opensource \ -confirm-license \ - -sysroot $SYSROOT \ - -prefix $QT_SYSTEM_LOCATION \ - -extprefix $QT_BUILD_LOCATION \ + -sysroot "$SYSROOT" \ + -prefix "$QT_SYSTEM_LOCATION" \ + -extprefix "$QT_BUILD_LOCATION" \ + -egl \ -eglfs \ + -reduce-exports \ -opengl desktop \ - -device linux-rasp-pi4-v3d-g++ \ - -device-option CROSS_COMPILE=$CROSS_COMPILER/bin/arm-linux-gnueabihf- \ + -device $QT_DEVICE \ + -device-option CROSS_COMPILE="$CROSS_COMPILER"/bin/"$TOOLCHAIN_HOST"- \ + -skip qtandroidextras \ + -skip qtcharts \ + -skip qtdatavis3d \ + -skip qtdoc \ + -skip qtgamepad \ + -skip qtgraphicaleffects \ + -skip qtlocation \ + -skip qtlottie \ + -skip qtmacextras \ + -skip qtnetworkauth \ + -skip qtquick3d \ + -skip qtquickcontrols \ + -skip qtquickcontrols2 \ + -skip qtquicktimeline \ + -skip qtremoteobjects \ -skip qtscript \ + -skip qtsensors \ + -skip qtspeech \ + -skip qttranslations \ + -skip qtvirtualkeyboard \ -skip qtwayland \ + -skip qtwebchannel \ -skip qtwebengine \ + -skip qtwebglplugin \ + -skip qtwebsockets \ + -skip qtwebview \ + -skip qtwinextras \ + -nomake examples -no-compile-examples \ -nomake tests \ -make libs \ -pkg-config \ @@ -64,12 +96,12 @@ build_qt5.15.2(){ -bundled-xcb-xinput \ -qt-pcre \ -qpa eglfs \ - -L$SYSROOT/usr/lib/arm-linux-gnueabihf -I$SYSROOT/usr/include/arm-linux-gnueabihf + -L"$SYSROOT"/usr/lib/"$TOOLCHAIN_HOST" -I"$SYSROOT"/usr/include/"$TOOLCHAIN_HOST" make -j14 sudo make install # installs to $QT_BUILD_LOCATION } -for arg in $@; do +for arg in "${@:2}"; do $arg done diff --git a/ci/arm/cmake_toolchain.cmake b/ci/arm/cmake_toolchain.cmake index d7ebfb16aa..8900723914 100644 --- a/ci/arm/cmake_toolchain.cmake +++ b/ci/arm/cmake_toolchain.cmake @@ -1,88 +1,105 @@ cmake_minimum_required(VERSION 3.18) set(CMAKE_SYSTEM_NAME Linux) -set(CMAKE_SYSTEM_PROCESSOR arm) -set(CMAKE_LIBRARY_ARCHITECTURE arm-linux-gnueabihf) -# In this case the variables CMAKE_SYSROOT and STAGING_AREA are defined as parameters to the cmake command +#[[ + - CMAKE_SYSROOT + - CMAKE_INSTALL_PREFIX + - STAGING_AREA + - CMAKE_SYSTEM_PROCESSOR + - CMAKE_LIBRARY_ARCHITECTURE +are exported from the arm_build_config.sh script +]] + +set(CMAKE_SYSROOT $ENV{CMAKE_SYSROOT}) +set(QT_LOCATION $ENV{QT_LOCATION}) +set(STAGING_AREA $ENV{STAGING_AREA}) +set(CMAKE_SYSROOT $ENV{CMAKE_SYSROOT}) +set(CMAKE_SYSTEM_PROCESSOR $ENV{CMAKE_SYSTEM_PROCESSOR}) +set(CMAKE_LIBRARY_ARCHITECTURE $ENV{CMAKE_LIBRARY_ARCHITECTURE}) + set(TOOLCHAIN_FILE ${STAGING_AREA}/cross-pi-gcc) set(TOOLCHAIN_BIN ${TOOLCHAIN_FILE}/bin) set(CMAKE_PREFIX_PATH ${QT_LOCATION}) -list(APPEND CMAKE_PREFIX_PATH "${CMAKE_SYSROOT}/usr/lib/arm-linux-gnueabihf") -list(APPEND CMAKE_PREFIX_PATH "${CMAKE_SYSROOT}/lib") -set(CMAKE_VERBOSE ON) +list(APPEND CMAKE_PREFIX_PATH "${CMAKE_SYSROOT}/usr/lib") +list(APPEND CMAKE_PREFIX_PATH "${CMAKE_SYSROOT}/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}") -set(PKG_CONFIG_EXECUTABLE "${CMAKE_SYSROOT}/usr/bin/arm-linux-gnueabihf-pkg-config" CACHE PATH "PKG_CONFIG_EXECUTABLE" - FORCE -) +if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64") + set(PKG_CONFIG_EXECUTABLE ${CMAKE_LIBRARY_ARCHITECTURE}-pkg-config CACHE PATH "PKG_CONFIG_EXECUTABLE" FORCE) + set(ENV{PKG_CONFIG_DIR} "") +else() + set(PKG_CONFIG_EXECUTABLE "${CMAKE_SYSROOT}/usr/bin/${CMAKE_LIBRARY_ARCHITECTURE}-pkg-config" + CACHE PATH "PKG_CONFIG_EXECUTABLE" FORCE + ) +endif() + +set(ENV{PKG_CONFIG_EXECUTABLE} ${PKG_CONFIG_EXECUTABLE}) set(ENV{PKG_CONFIG_ALLOW_CROSS} 1) set(PKG_CONFIG_USE_CMAKE_PREFIX_PATH ON) -set(RPI_PKG_CONFIG_LIBDIR "${CMAKE_SYSROOT}/usr/lib/arm-linux-gnueabihf/pkgconfig:${RPI_PKG_CONFIG_LIBDIR}") +set(RPI_PKG_CONFIG_LIBDIR "${CMAKE_SYSROOT}/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}/pkgconfig:${RPI_PKG_CONFIG_LIBDIR}") set(RPI_PKG_CONFIG_LIBDIR "${CMAKE_SYSROOT}/usr/share/pkgconfig:${RPI_PKG_CONFIG_LIBDIR}") set(RPI_PKG_CONFIG_LIBDIR "${CMAKE_SYSROOT}/usr/lib/pkgconfig:${RPI_PKG_CONFIG_LIBDIR}") set(RPI_PKG_CONFIG_LIBDIR "${CMAKE_SYSROOT}/usr/local/lib/pkgconfig:${RPI_PKG_CONFIG_LIBDIR}") set(ENV{PKG_CONFIG_LIBDIR} "${RPI_PKG_CONFIG_LIBDIR}") -set(ENV{PKG_CONFIG} "${CMAKE_SYSROOT}/usr/bin/arm-linux-gnueabihf-pkg-config") +set(ENV{PKG_CONFIG} "${CMAKE_SYSROOT}/usr/bin/${CMAKE_LIBRARY_ARCHITECTURE}-pkg-config") set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:${CMAKE_SYSROOT}/include:") set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:${CMAKE_SYSROOT}/usr/include:") -set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:${CMAKE_SYSROOT}/usr/include/arm-linux-gnueabihf:") +set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:${CMAKE_SYSROOT}/usr/include/${CMAKE_LIBRARY_ARCHITECTURE}:") set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:${CMAKE_SYSROOT}/usr/share/include:") - set(ENV{PKG_CONFIG_SYSROOT_DIR} "${CMAKE_SYSROOT}") -set(ENV{LD_LIBRARY_PATH} "${CMAKE_SYSROOT}/usr/lib/arm-linux-gnueabihf:$ENV{LD_LIBRARY_PATH}") - -set(CMAKE_LIBRARY_PATH "${CMAKE_SYSROOT}/usr/lib") -set(CMAKE_LIBRARY_PATH "${CMAKE_LIBRARY_PATH} ${CMAKE_SYSROOT}/usr/lib/arm-linux-gnueabihf") -set(CMAKE_LIBRARY_PATH "${CMAKE_LIBRARY_PATH} ${CMAKE_SYSROOT}/usr/local/lib") -set(CMAKE_LIBRARY_PATH "${CMAKE_LIBRARY_PATH} ${CMAKE_SYSROOT}/usr/local/lib/arm-linux-gnueabihf") -set(CMAKE_AR ${TOOLCHAIN_BIN}/arm-linux-gnueabihf-ar) -set(CMAKE_ASM_COMPILER ${TOOLCHAIN_BIN}/arm-linux-gnueabihf-gcc) -set(CMAKE_C_COMPILER ${TOOLCHAIN_BIN}/arm-linux-gnueabihf-gcc) -set(CMAKE_CXX_COMPILER ${TOOLCHAIN_BIN}/arm-linux-gnueabihf-g++) -set(CMAKE_LINKER ${TOOLCHAIN_BIN}/arm-linux-gnueabihf-ld) -set(CMAKE_OBJCOPY ${TOOLCHAIN_BIN}/arm-linux-gnueabihf-objcopy) -set(CMAKE_RANLIB ${TOOLCHAIN_BIN}/arm-linux-gnueabihf-ranlib) -set(CMAKE_SIZE ${TOOLCHAIN_BIN}/arm-linux-gnueabihf-size) -set(CMAKE_STRIP ${TOOLCHAIN_BIN}/arm-linux-gnueabihf-strip) +set(CMAKE_AR ${TOOLCHAIN_BIN}/${CMAKE_LIBRARY_ARCHITECTURE}-ar) +set(CMAKE_ASM_COMPILER ${TOOLCHAIN_BIN}/${CMAKE_LIBRARY_ARCHITECTURE}-gcc) +set(CMAKE_C_COMPILER ${TOOLCHAIN_BIN}/${CMAKE_LIBRARY_ARCHITECTURE}-gcc) +set(CMAKE_CXX_COMPILER ${TOOLCHAIN_BIN}/${CMAKE_LIBRARY_ARCHITECTURE}-g++) +set(CMAKE_LINKER ${TOOLCHAIN_BIN}/${CMAKE_LIBRARY_ARCHITECTURE}-ld) +set(CMAKE_OBJCOPY ${TOOLCHAIN_BIN}/${CMAKE_LIBRARY_ARCHITECTURE}-objcopy) +set(CMAKE_RANLIB ${TOOLCHAIN_BIN}/${CMAKE_LIBRARY_ARCHITECTURE}-ranlib) +set(CMAKE_SIZE ${TOOLCHAIN_BIN}/${CMAKE_LIBRARY_ARCHITECTURE}-size) +set(CMAKE_STRIP ${TOOLCHAIN_BIN}/${CMAKE_LIBRARY_ARCHITECTURE}-strip) -set(CMAKE_C_FLAGS "-march=armv7-a -mfloat-abi=hard -mfpu=vfp") +set(CMAKE_C_FLAGS "-march=armv8-a") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${CMAKE_SYSROOT}/include") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${CMAKE_SYSROOT}/usr/include") -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${CMAKE_SYSROOT}/usr/include/arm-linux-gnueabihf") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${CMAKE_SYSROOT}/usr/include/${CMAKE_LIBRARY_ARCHITECTURE}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${CMAKE_SYSROOT}/usr/share/include") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") set(CMAKE_CXX_FLAGS "-fexceptions -frtti ${CMAKE_C_FLAGS}") set(CMAKE_CXX_FLAGS_DEBUG "-Os -g") set(CMAKE_CXX_FLAGS_RELEASE "-Os -DNDEBUG") -set(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,-O1 -Wl,--hash-style=gnu -mthumb -lpthread -pthread") -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SYSROOT}/usr/lib/arm-linux-gnueabihf") +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed -Wl,-O1 -Wl,--hash-style=gnu") +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lpthread -lboost_program_options") +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SYSROOT}/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SYSROOT}/usr/lib") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_SYSROOT}/usr/local/lib") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${QT_LOCATION}/lib") -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${TOOLCHAIN_FILE}/arm-linux-gnueabihf/lib") -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${TOOLCHAIN_FILE}/arm-linux-gnueabihf/libc/lib") +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${TOOLCHAIN_FILE}/${CMAKE_LIBRARY_ARCHITECTURE}/lib") +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L${TOOLCHAIN_FILE}/${CMAKE_LIBRARY_ARCHITECTURE}/libc/lib") + set(CMAKE_SHARED_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS}) #[[ -# Debug Mode -set(PKG_CONFIG_ARGN "--debug") -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--verbose ") +Debug Mode + set(CMAKE_VERBOSE ON) + set(CMAKE_VERBOSE_MAKEFILE ON) + set(PKG_CONFIG_ARGN "--debug") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--verbose") + set(CMAKE_FIND_DEBUG_MODE TRUE) ]] -set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) # Perform compiler test with static library set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) -set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE) set(CMAKE_INSTALL_RPATH "$ORIGIN" "$ORIGIN/../lib" - "/lib/arm-linux-gnueabihf" - "/lib" - "/usr/local/qt5.15/lib" + "/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}" + "/usr/lib" + "/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}/qt5/lib" ) + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) -set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH) diff --git a/ci/arm/copy-deps.sh b/ci/arm/copy-deps.sh index cae9d95065..1d2ca90b58 100755 --- a/ci/arm/copy-deps.sh +++ b/ci/arm/copy-deps.sh @@ -3,21 +3,25 @@ set -e SRC_DIR=$(git rev-parse --show-toplevel 2>/dev/null ) || \ SRC_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && cd ../../ && pwd ) -source $SRC_DIR/ci/armhf/armhf_build_config.sh +source $SRC_DIR/ci/arm/arm_build_config.sh $1 -BINARY=$1 -LOCATION=$2 +BINARY=$2 +LOCATION=$3 LIBS_ARRAY=() BLACKLISTED=($(wget --quiet https://raw.githubusercontent.com/probonopd/AppImages/master/excludelist -O - | sort | uniq | cut -d '#' -f 1 | grep -v "^#.*" | grep "[^-\s]")) -if [ ! -f "${SRC_DIR}"/ci/armhf/ldd-mod ]; then - sed 's|.*RTLDLIST=.*|RTLDLIST="/usr/arm-linux-gnueabihf/lib/ld-2.31.so /usr/arm-linux-gnueabihf/lib/ld-linux-armhf.so.3"|' /usr/bin/ldd | tee "${SRC_DIR}"/ci/armhf/ldd-mod - chmod +x "${SRC_DIR}"/ci/armhf/ldd-mod +if [ ! -f "${SRC_DIR}"/ci/arm/ldd-mod ]; then + if [ ${TOOLCHAIN_HOST} == "aarch64-linux-gnu" ];then + sed 's|.*RTLDLIST=.*|RTLDLIST="/usr/aarch64-linux-gnu/lib/ld-2.31.so /usr/aarch64-linux-gnu/lib/ld-linux-aarch64.so.1"|' /usr/bin/ldd | tee "${SRC_DIR}"/ci/arm/ldd-mod + elif [ ${TOOLCHAIN_HOST} == "arm-linux-gnueabihf" ]; then + sed 's|.*RTLDLIST=.*|RTLDLIST="/usr/arm-linux-gnueabihf/lib/ld-2.31.so /usr/arm-linux-gnueabihf/lib/ld-linux-armhf.so.3"|' /usr/bin/ldd | tee "${SRC_DIR}"/ci/arm/ldd-mod + fi + chmod +x "${SRC_DIR}"/ci/arm/ldd-mod fi -export LD_LIBRARY_PATH="${APP_DIR}/usr/lib:${SYSROOT}/lib:${SYSROOT}/lib/arm-linux-gnueabihf:${SYSROOT}/usr/arm-linux-gnueabihf/lib:${SYSROOT}/usr/local/qt5.15/lib:${SYSROOT}/usr/local/lib:${SRC_DIR}/build" +export LD_LIBRARY_PATH="${APP_DIR}/usr/lib:${SYSROOT}/lib:${SYSROOT}/lib/${TOOLCHAIN_HOST}:${SYSROOT}/usr/${TOOLCHAIN_HOST}/lib:${SYSROOT}/usr/local/qt5.15/lib:${SYSROOT}/usr/local/lib:${SRC_DIR}/build" run_ldd(){ - for library in $("${SRC_DIR}"/ci/armhf/ldd-mod "$1" | cut -d '>' -f 2 | awk '{print $1}') + for library in $("${SRC_DIR}"/ci/arm/ldd-mod "$1" | cut -d '>' -f 2 | awk '{print $1}') do # check if the library exists at that path and if it was processed already or blacklisted if ! [[ "${BLACKLISTED[*]}" =~ "${library##*/}" ]]; then diff --git a/ci/arm/create_docker_image.sh b/ci/arm/create_docker_image.sh index fbcf190636..c75d7e5a25 100755 --- a/ci/arm/create_docker_image.sh +++ b/ci/arm/create_docker_image.sh @@ -3,7 +3,8 @@ set -ex SRC_DIR=$(git rev-parse --show-toplevel 2>/dev/null ) || \ SRC_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && cd ../../ && pwd ) -source $SRC_DIR/ci/armhf/armhf_build_config.sh +ARCH=$1 +source $SRC_DIR/ci/arm/arm_build_config.sh "$ARCH" # install docker install_packages(){ @@ -16,7 +17,7 @@ install_packages(){ } create_sysroot(){ - $SRC_DIR/ci/armhf/create_sysroot.sh \ + $SRC_DIR/ci/arm/create_sysroot.sh "$ARCH" \ install_packages \ download_kuiper \ install_qemu \ @@ -28,18 +29,34 @@ create_sysroot(){ tar_and_move_sysroot(){ pushd $STAGING_AREA sudo tar -czf "${SYSROOT_TAR##*/}" sysroot - sudo mv $SYSROOT_TAR $SRC_DIR/ci/armhf + sudo mv $SYSROOT_TAR $SRC_DIR/ci/arm popd } create_image(){ - pushd ${SRC_DIR}/ci/armhf - docker build --load --progress plain --tag cristianbindea/scopy2-armhf-appimage:testing -f docker/Dockerfile . - # DOCKER_BUILDKIT=0 docker build --tag cristianbindea/scopy2-armhf-appimage:testing . # build the image using old backend + pushd ${SRC_DIR}/ci/arm + if [ "${ARCH}" == "arm32" ]; then + DOCKER_TAG=cristianbindea/scopy2-armhf-appimage:testing + elif [ "${ARCH}" == "arm64" ]; then + DOCKER_TAG=cristianbindea/scopy2-arm64-appimage:testing + fi + + # docker build \ + # --load \ + # --progress plain \ + # --tag ${DOCKER_TAG} \ + # -f docker/Dockerfile \ + # --build-arg ARCH=${ARCH} . + + # build the image using old backend + DOCKER_BUILDKIT=0 docker build \ + --tag ${DOCKER_TAG} \ + -f docker/Dockerfile \ + --build-arg ARCH=${ARCH} . popd } -#install_packages +install_packages create_sysroot tar_and_move_sysroot create_image diff --git a/ci/arm/create_sysroot.sh b/ci/arm/create_sysroot.sh index 29e3d2607d..276c18d41d 100755 --- a/ci/arm/create_sysroot.sh +++ b/ci/arm/create_sysroot.sh @@ -3,7 +3,7 @@ set -ex SRC_SCRIPT=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) -source $SRC_SCRIPT/armhf_build_config.sh +source $SRC_SCRIPT/arm_build_config.sh $1 IMAGE_FILE=2023-12-13-ADI-Kuiper-full.img @@ -62,7 +62,11 @@ extract_sysroot(){ # execute chroot inside the sysroot folder and install/remove packages using apt configure_sysroot(){ - cat $SRC_SCRIPT/inside_chroot.sh | sudo chroot ${SYSROOT} + if [ $TOOLCHAIN_HOST == "aarch64-linux-gnu" ]; then + cat $SRC_SCRIPT/inside_chroot_arm64.sh | sudo chroot ${SYSROOT} + elif [ $TOOLCHAIN_HOST == "arm-linux-gnueabihf" ]; then + cat $SRC_SCRIPT/inside_chroot_armhf.sh | sudo chroot ${SYSROOT} + fi } move_and_extract_sysroot(){ @@ -81,7 +85,7 @@ fix_relativelinks(){ popd } -for arg in $@; do +for arg in "${@:2}"; do $arg done diff --git a/ci/arm/docker/Dockerfile b/ci/arm/docker/Dockerfile index becb3c1808..8ce362bea3 100644 --- a/ci/arm/docker/Dockerfile +++ b/ci/arm/docker/Dockerfile @@ -1,5 +1,6 @@ FROM --platform=linux/amd64 ubuntu:20.04 AS start SHELL ["/bin/bash", "-c"] +ARG ARCH ARG USER=runner ENV DEBIAN_FRONTEND=noninteractive ENV TZ=Europe/Bucharest @@ -26,19 +27,20 @@ WORKDIR /home/${USER} FROM start AS sysroot_builder ARG USER=runner +ARG ARCH ENV DEBIAN_FRONTEND=noninteractive -#Copy all scopy/ci/armhf folder inside the image -COPY * /home/${USER} -RUN ./create_sysroot.sh \ +#Copy all scopy/ci/arm folder inside the image +COPY * /home/${USER}/ +RUN ./create_sysroot.sh ${ARCH} \ install_packages \ move_and_extract_sysroot \ fix_relativelinks -RUN ./build_qt.sh \ +RUN ./build_qt.sh ${ARCH} \ install_packages \ download_qt \ download_crosscompiler \ - build_qt5.15.2 -RUN ./armhf_build_process.sh \ + build +RUN ./arm_build_process.sh ${ARCH} \ install_packages \ download_cmake \ download_crosscompiler \ @@ -49,10 +51,11 @@ RUN ./armhf_build_process.sh \ FROM start ARG USER=runner +ARG ARCH ENV DEBIAN_FRONTEND=noninteractive -ARG STAGING=/home/${USER}/scopy/ci/armhf/staging -COPY --from=sysroot_builder /home/${USER}/armhf_build_process.sh /home/${USER} -COPY --from=sysroot_builder /home/${USER}/armhf_build_config.sh /home/${USER} +ARG STAGING=/home/${USER}/scopy/ci/arm/staging +COPY --from=sysroot_builder /home/${USER}/arm_build_process.sh /home/${USER} +COPY --from=sysroot_builder /home/${USER}/arm_build_config.sh /home/${USER} COPY --from=sysroot_builder /home/${USER}/build-status /home/${USER}/build-status RUN mkdir -p /home/${USER}/sysroot COPY --from=sysroot_builder ${STAGING}/sysroot/usr /home/${USER}/sysroot/usr @@ -61,6 +64,6 @@ COPY --from=sysroot_builder ${STAGING}/sysroot/include /home/${USER}/sysroot/inc WORKDIR /home/${USER}/sysroot RUN ln -s usr/bin bin && ln -s usr/lib lib && ln -s usr/sbin sbin WORKDIR /home/${USER} -RUN /home/${USER}/armhf_build_process.sh install_packages download_cmake download_crosscompiler && \ +RUN /home/${USER}/arm_build_process.sh ${ARCH} install_packages download_cmake download_crosscompiler && \ mv ${STAGING} /home/${USER} && \ - rm -rf /home/${USER}/armhf_build_process.sh /home/${USER}/armhf_build_config.sh /home/${USER}/scopy + rm -rf /home/${USER}/arm_build_process.sh /home/${USER}/arm_build_config.sh /home/${USER}/scopy diff --git a/ci/arm/inside_chroot.sh b/ci/arm/inside_chroot.sh deleted file mode 100644 index c90afa85ea..0000000000 --- a/ci/arm/inside_chroot.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/bash - -export DEBIAN_FRONTEND=noninteractive -ln -snf /usr/share/zoneinfo/Europe/Bucharest /etc/localtime && echo "Europe/Bucharest" > /etc/timezone -echo "LC_ALL=en_US.UTF-8" | tee -a /etc/environment -echo "LANG=en_US.UTF-8" | tee -a /etc/locale.conf -locale-gen en_US.UTF-8 - -sed -i 's/#deb-src/deb-src/' /etc/apt/sources.list - -apt -y purge openjdk* tex-common -apt -y remove gnuradio gnuradio-* libgnuradio-* libvolk* -apt -y remove qt* libqt5* -apt -y autoremove -apt update && apt -y upgrade -apt -y dist-upgrade -dpkg --configure -a - -rm -rf /usr/local/include/volk /usr/local/lib/libvolk* \ - /usr/local/lib/cmake/volk -rm -rf /usr/lib/arm-linux-gnueabihf/libiio.so* \ - usr/local/src/libiio \ - /usr/lib/arm-linux-gnueabihf/pkgconfig/libiio.pc -rm -rf /usr/local/lib/cmake/m2k \ - /usr/local/lib/arm-linux-gnueabihf/pkgconfig/libm2k.pc \ - /usr/local/lib/arm-linux-gnueabihf/pkgconfig/gnuradio-m2k.pc \ - /usr/local/lib/arm-linux-gnueabihf/libgnuradio-m2k.so* \ - /usr/local/lib/arm-linux-gnueabihf/libm2k.so* \ - /usr/local/lib/arm-linux-gnueabihf/cmake/libm2k \ - /usr/local/include/libm2k /usr/local/include/m2k -rm -rf /usr/local/lib/arm-linux-gnueabihf/libgnuradio-iio.so* \ - /usr/local/lib/arm-linux-gnueabihf/pkgconfig/gnuradio-iio.pc \ - /usr/local/lib/cmake/iio -rm -rf /usr/lib/arm-linux-gnueabihf/libad9361.so* \ - /usr/lib/arm-linux-gnueabihf/pkgconfig/libad9361.pc \ - /usr/lib/libad9166.so* \ - /usr/lib/pkgconfig/libad9166.pc - -apt -y build-dep qtbase5-dev || true -apt -y install build-essential gcc g++ gdb-multiarch cmake autoconf automake bison flex git wget pkg-config figlet gawk unzip libsndfile1-dev \ - libudev-dev libinput-dev libts-dev libxcb-xinerama0-dev libxcb-xinerama0 gdbserver libspeechd-dev perl \ - libgl1-mesa-dev libxcb-composite0-dev libxcb-cursor-dev libxcb-damage0-dev libxcb-xv0-dev \ - libxcb-dpms0-dev libxcb-dri2-0-dev libxcb-ewmh-dev libxcb-imdkit-dev libxcb-xvmc0-dev \ - libxcb-present-dev libxcb-record0-dev libxcb-res0-dev libxcb-xrm-dev libx11-xcb-dev libxcb-glx0-dev libxcb-icccm4 libxcb-icccm4-dev libxcb-xkb-dev libxkbcommon-x11-dev \ - libxcb-screensaver0-dev libxcb-util0-dev libxcb-xf86dri0-dev libxcb-xtest0-dev libavahi-client* libavahi-common* -apt -y install libunwind-dev libsndfile1-dev mesa-utils* mesa-common-dev libglu1-mesa-dev freeglut3-dev mesa-common-dev python2 libopenal-dev || true -apt -y install '^libxcb.*-dev' libx11-xcb-dev libglu1-mesa-dev libxrender-dev libxi-dev libxkbcommon-dev libxkbcommon-x11-dev || true - -wget https://raw.githubusercontent.com/abhiTronix/raspberry-pi-cross-compilers/master/utils/SSymlinker -sed -i 's/sudo//g' SSymlinker -chmod +x SSymlinker -./SSymlinker -s /usr/include/arm-linux-gnueabihf/asm -d /usr/include -./SSymlinker -s /usr/include/arm-linux-gnueabihf/gnu -d /usr/include -./SSymlinker -s /usr/include/arm-linux-gnueabihf/bits -d /usr/include -./SSymlinker -s /usr/include/arm-linux-gnueabihf/sys -d /usr/include -./SSymlinker -s /usr/lib/arm-linux-gnueabihf/crtn.o -d /usr/lib/crtn.o -./SSymlinker -s /usr/lib/arm-linux-gnueabihf/crt1.o -d /usr/lib/crt1.o -./SSymlinker -s /usr/lib/arm-linux-gnueabihf/crti.o -d /usr/lib/crti.o \ No newline at end of file diff --git a/ci/arm/inside_chroot_arm64.sh b/ci/arm/inside_chroot_arm64.sh new file mode 100644 index 0000000000..1121607c27 --- /dev/null +++ b/ci/arm/inside_chroot_arm64.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +export DEBIAN_FRONTEND=noninteractive +ln -snf /usr/share/zoneinfo/Europe/Bucharest /etc/localtime && echo "Europe/Bucharest" > /etc/timezone +echo "LC_ALL=en_US.UTF-8" | tee -a /etc/environment +echo "LANG=en_US.UTF-8" | tee -a /etc/locale.conf +locale-gen en_US.UTF-8 + +apt -y remove *qt* +apt -y autoremove + +rm -rfv $(find / | grep libiio) +rm -rfv $(find / | grep m2k) +rm -rfv $(find / | grep libad9361) +rm -rfv $(find / | grep libad9166) + +apt update && apt -y upgrade +apt -y dist-upgrade +dpkg --configure -a + +apt -y install '^libxcb.*-dev' autoconf automake bison build-essential cmake dh-python figlet flex freeglut3-dev g++ gawk gcc \ + gdb-multiarch gdbserver git libavahi-client* libavahi-common* libboost1.81-all-dev libdrm-dev libgbm-dev libglib2.0-dev libgl1-mesa-dev libgles2-mesa-dev libglu1-mesa-dev \ + libgmp-dev libinput-dev libopenal-dev libsndfile1-dev libspeechd-dev libts-dev libudev-dev libunwind-dev libxcb-icccm4 libxcb-xinerama0 \ + libx11-xcb-dev libxi-dev libxkbcommon-dev libxkbcommon-x11-dev libxrender-dev libxml2-dev libxml2-utils mesa-common-dev mesa-utils* \ + perl pkg-config unzip wget + +wget https://raw.githubusercontent.com/abhiTronix/raspberry-pi-cross-compilers/master/utils/SSymlinker +sed -i 's/sudo//g' SSymlinker +chmod +x SSymlinker +./SSymlinker -s /usr/include/aarch64-linux-gnu/asm -d /usr/include +./SSymlinker -s /usr/include/aarch64-linux-gnu/gnu -d /usr/include +./SSymlinker -s /usr/include/aarch64-linux-gnu/bits -d /usr/include +./SSymlinker -s /usr/include/aarch64-linux-gnu/sys -d /usr/include +./SSymlinker -s /usr/lib/aarch64-linux-gnu/crtn.o -d /usr/lib/crtn.o +./SSymlinker -s /usr/lib/aarch64-linux-gnu/crt1.o -d /usr/lib/crt1.o +./SSymlinker -s /usr/lib/aarch64-linux-gnu/crti.o -d /usr/lib/crti.o diff --git a/ci/arm/inside_chroot_armhf.sh b/ci/arm/inside_chroot_armhf.sh new file mode 100644 index 0000000000..95cb3d9924 --- /dev/null +++ b/ci/arm/inside_chroot_armhf.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +export DEBIAN_FRONTEND=noninteractive +ln -snf /usr/share/zoneinfo/Europe/Bucharest /etc/localtime && echo "Europe/Bucharest" > /etc/timezone +echo "LC_ALL=en_US.UTF-8" | tee -a /etc/environment +echo "LANG=en_US.UTF-8" | tee -a /etc/locale.conf +locale-gen en_US.UTF-8 + +sed -i 's/#deb-src/deb-src/' /etc/apt/sources.list + +apt -y purge openjdk* tex-common +apt -y remove gnuradio gnuradio-* libgnuradio-* libvolk* +apt -y remove *qt* +apt -y autoremove +apt update && apt -y upgrade +apt -y dist-upgrade +dpkg --configure -a + +rm -rfv $(find / | grep libiio) +rm -rfv $(find / | grep m2k) +rm -rfv $(find / | grep libad9361) +rm -rfv $(find / | grep libad9166) +rm -rfv $(find / | grep volk) +rm -rfv $(find / | grep gnuradio) + +apt -y build-dep qtbase5-dev +apt -y install '^libxcb.*-dev' autoconf automake bison build-essential cmake figlet flex freeglut3-dev g++ gawk gcc \ + gdb-multiarch gdbserver git libavahi-client* libavahi-common* libboost1.74-all-dev libdrm-dev libgbm-dev libglib2.0-dev libgl1-mesa-dev libgles2-mesa-dev \ + libglu1-mesa-dev libgmp-dev libinput-dev libopenal-dev libsndfile1-dev libspeechd-dev libts-dev libudev-dev \ + libunwind-dev libx11-xcb-dev libxi-dev libxkbcommon-dev libxkbcommon-x11-dev libxrender-dev libxml2-dev libxml2-utils \ + mesa-common-dev mesa-utils* perl pkg-config dh-python unzip wget + +wget https://raw.githubusercontent.com/abhiTronix/raspberry-pi-cross-compilers/master/utils/SSymlinker +sed -i 's/sudo//g' SSymlinker +chmod +x SSymlinker +./SSymlinker -s /usr/include/arm-linux-gnueabihf/asm -d /usr/include +./SSymlinker -s /usr/include/arm-linux-gnueabihf/gnu -d /usr/include +./SSymlinker -s /usr/include/arm-linux-gnueabihf/bits -d /usr/include +./SSymlinker -s /usr/include/arm-linux-gnueabihf/sys -d /usr/include +./SSymlinker -s /usr/lib/arm-linux-gnueabihf/crtn.o -d /usr/lib/crtn.o +./SSymlinker -s /usr/lib/arm-linux-gnueabihf/crt1.o -d /usr/lib/crt1.o +./SSymlinker -s /usr/lib/arm-linux-gnueabihf/crti.o -d /usr/lib/crti.o \ No newline at end of file diff --git a/ci/arm/local_build_scopy_for_kuiper.sh b/ci/arm/local_build_scopy_for_kuiper.sh index 6c7ff858d1..e309edca67 100755 --- a/ci/arm/local_build_scopy_for_kuiper.sh +++ b/ci/arm/local_build_scopy_for_kuiper.sh @@ -2,12 +2,15 @@ set -ex export PS4='+(${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }' -STAGING_AREA=$HOME"/staging" -STAGING_AREA_DEPS=$STAGING_AREA"/dependencies" JOBS=-j1 +SRC_DIR=$(git rev-parse --show-toplevel 2>/dev/null ) || echo "No source directory found" +SRC_SCRIPT=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +STAGING_AREA=$SRC_SCRIPT/staging +STAGING_AREA_DEPS=$STAGING_AREA/dependencies -USE_STAGING=OFF +USE_STAGING=OFF LIBIIO_VERSION=v0.26 LIBM2K_BRANCH=main @@ -19,8 +22,7 @@ GRM2K_BRANCH=master LIBSIGROKDECODE_BRANCH=master QWT_BRANCH=qwt-multiaxes-updated LIBTINYIIOD_BRANCH=master -IIOEMU_BRANCH=master -SCOPY_BRANCH=dev +IIOEMU_BRANCH=main if [ ! -z "$USE_STAGING" ] && [ "$USE_STAGING" == "ON" ] then @@ -60,11 +62,10 @@ build_with_cmake() { $CMAKE "$@" make $JOBS sudo make $JOBS install - sudo ldconfig } clone() { - echo "#######CLONE#######" + echo "####### CLONE #######" pushd $STAGING_AREA [ -d 'libiio' ] || git clone --recursive https://github.com/analogdevicesinc/libiio.git -b $LIBIIO_VERSION libiio [ -d 'libm2k' ] || git clone --recursive https://github.com/analogdevicesinc/libm2k.git -b $LIBM2K_BRANCH libm2k @@ -77,21 +78,20 @@ clone() { [ -d 'libsigrokdecode' ] || git clone --recursive https://github.com/sigrokproject/libsigrokdecode.git -b $LIBSIGROKDECODE_BRANCH libsigrokdecode [ -d 'libtinyiiod' ] || git clone --recursive https://github.com/analogdevicesinc/libtinyiiod.git -b $LIBTINYIIOD_BRANCH libtinyiiod [ -d 'iio-emu' ] || git clone --recursive https://github.com/analogdevicesinc/iio-emu -b $IIOEMU_BRANCH iio-emu - [ -d 'scopy' ] || git clone --recursive https://github.com/analogdevicesinc/scopy -b $SCOPY_BRANCH scopy popd } install_apt() { sudo apt-get update sudo apt-get -y upgrade - sudo apt-get -y install build-essential cmake vim bison flex swig swig4.0 python3 mlocate \ - libusb-1.0-* libavahi-client* libavahi-common* libxml2* libsndfile-dev libfuse2 libboost1.74-* \ - qtbase5-dev* qt5-qmake* qttools5-dev* qtdeclarative5-dev libqt5qml* libqt5svg5* + sudo apt-get -y install build-essential cmake vim bison flex swig swig4.0 python3 mlocate libfftw3-dev libgsl-dev \ + libusb-1.0-* libavahi-client* libavahi-common* libxml2* libsndfile-dev libfuse2 libboost1.74-* libglib2.0-dev \ + qtbase5-dev* qt5-qmake* qttools5-dev* qtdeclarative5-dev libqt5qml* libqt5svg5* libgmp3-dev libgmp-dev libthrift-dev libunwind-dev pip install mako --break-system-packages } build_libiio() { - echo "#######build_libiio#######" + echo "####### BUILD LIBIIO #######" pushd $STAGING_AREA/libiio build_with_cmake \ -DWITH_TESTS:BOOL=OFF \ @@ -108,21 +108,21 @@ build_libiio() { } build_libm2k() { - echo "#######build_libm2k#######" + echo "####### BUILD LIBM2K #######" pushd $STAGING_AREA/libm2k build_with_cmake -DENABLE_PYTHON=OFF -DENABLE_TOOLS=ON ../ popd } build_spdlog() { - echo "#######build_spdlog#######" + echo "####### BUILD SPDLOG #######" pushd $STAGING_AREA/spdlog build_with_cmake -DSPDLOG_BUILD_SHARED=ON ../ popd } build_volk() { - echo "#######build_volk#######" + echo "####### BUILD VOLK #######" pushd $STAGING_AREA/volk build_with_cmake \ -DCMAKE_BUILD_TYPE=Release \ @@ -131,7 +131,7 @@ build_volk() { } build_gnuradio() { - echo "#######build_gnuradio#######" + echo "####### BUILD GNURADIO #######" pushd $STAGING_AREA/gnuradio build_with_cmake \ -DPYTHON_EXECUTABLE=/usr/bin/python3 \ @@ -148,23 +148,24 @@ build_gnuradio() { } build_gr_scopy() { - echo "#######build_gr_scopy#######" + echo "####### BUILD GR_SCOPY #######" pushd $STAGING_AREA/gr-scopy build_with_cmake -DWITH_PYTHON=OFF ../ popd } build_gr_m2k() { - echo "#######build_gr_m2k#######" + echo "####### BUILD GR_M2K #######" pushd $STAGING_AREA/gr-m2k build_with_cmake -DWITH_PYTHON=OFF -DDIGITAL=OFF ../ popd } build_qwt() { - echo "#######build_qwt#######" + echo "####### BUILD QWT #######" pushd $STAGING_AREA/qwt git clean -xdf + sed -i 's|/usr/local/qwt-$$QWT_VERSION-ma|/usr/local|g' qwtconfig.pri if [ ! -z "$USE_STAGING" ] && [ "$USE_STAGING" == "ON" ] then qmake INCLUDEPATH=$STAGING_AREA_DEPS/include LIBS=-L$STAGING_AREA_DEPS/lib qwt.pro @@ -177,12 +178,11 @@ build_qwt() { sudo make install fi - sudo ldconfig popd } build_libsigrokdecode() { - echo "#######build_libsigrokdecode#######" + echo "####### BUILD LIBSIGROKDECODE #######" pushd $STAGING_AREA/libsigrokdecode git clean -xdf ./autogen.sh @@ -196,36 +196,38 @@ build_libsigrokdecode() { make $JOBS sudo make install - sudo ldconfig popd } build_libtinyiiod() { - echo "#######build_libtinyiiod#######" + echo "####### BUILD LIBTINYIIOD #######" pushd $STAGING_AREA/libtinyiiod build_with_cmake -DBUILD_EXAMPLES=OFF ../ popd } build_iio-emu() { - echo "#######build_iio-emu#######" + echo "####### BUILD IIO-EMU #######" pushd $STAGING_AREA/iio-emu build_with_cmake ../ popd } build_scopy() { - echo "#######build_scopy#######" - pushd $STAGING_AREA/scopy + echo "####### BUILD SCOPY #######" + pushd $SRC_DIR build_with_cmake ../ popd } -test_scopy() { - echo "#######TEST_SCOPY#######" - pushd $STAGING_AREA/scopy/build - ./scopy +build_scopy_appimage() +{ + pushd $SRC_DIR + export APPIMAGE=1 + build_with_cmake ../ popd + + $SRC_DIR/ci/arm/arm_build_process.sh create_appdir create_appimage } buid_deps() { @@ -242,11 +244,10 @@ buid_deps() { } -# instal_apt +# install_apt # clone # buid_deps # build_scopy -# test_scopy for arg in $@; do $arg diff --git a/ci/arm/qt_patch.patch b/ci/arm/qt_patch.patch deleted file mode 100644 index ec1e6bf431..0000000000 --- a/ci/arm/qt_patch.patch +++ /dev/null @@ -1,126 +0,0 @@ ---- new/qt-everywhere-src-5.15.2/qtbase/mkspecs/linux-arm-gnueabihf-g++/qmake.conf -+++ qt-everywhere-src-5.15.2/qtbase/mkspecs/linux-arm-gnueabihf-g++/qmake.conf -@@ -0,0 +1,26 @@ -+# -+# qmake configuration for building with arm-linux-gnueabihf-g++ -+# -+ -+MAKEFILE_GENERATOR = UNIX -+CONFIG += incremental -+QMAKE_INCREMENTAL_STYLE = sublib -+ -+include(../common/linux.conf) -+include(../common/gcc-base-unix.conf) -+include(../common/g++-unix.conf) -+ -+QMAKE_LIBS_EGL = -lEGL -+ -+# modifications to g++.conf -+QMAKE_CC = arm-linux-gnueabihf-gcc -+QMAKE_CXX = arm-linux-gnueabihf-g++ -+QMAKE_LINK = arm-linux-gnueabihf-g++ -+QMAKE_LINK_SHLIB = arm-linux-gnueabihf-g++ -+ -+# modifications to linux.conf -+QMAKE_AR = arm-linux-gnueabihf-ar cqs -+QMAKE_OBJCOPY = arm-linux-gnueabihf-objcopy -+QMAKE_NM = arm-linux-gnueabihf-nm -P -+QMAKE_STRIP = arm-linux-gnueabihf-strip -+load(qt_config) ---- new/qt-everywhere-src-5.15.2/qtbase/mkspecs/linux-arm-gnueabihf-g++/qplatformdefs.h -+++ qt-everywhere-src-5.15.2/qtbase/mkspecs/linux-arm-gnueabihf-g++/qplatformdefs.h -@@ -0,0 +1,40 @@ -+/**************************************************************************** -+** -+** Copyright (C) 2016 The Qt Company Ltd. -+** Contact: https://www.qt.io/licensing/ -+** -+** This file is part of the qmake spec of the Qt Toolkit. -+** -+** $QT_BEGIN_LICENSE:LGPL$ -+** Commercial License Usage -+** Licensees holding valid commercial Qt licenses may use this file in -+** accordance with the commercial license agreement provided with the -+** Software or, alternatively, in accordance with the terms contained in -+** a written agreement between you and The Qt Company. For licensing terms -+** and conditions see https://www.qt.io/terms-conditions. For further -+** information use the contact form at https://www.qt.io/contact-us. -+** -+** GNU Lesser General Public License Usage -+** Alternatively, this file may be used under the terms of the GNU Lesser -+** General Public License version 3 as published by the Free Software -+** Foundation and appearing in the file LICENSE.LGPL3 included in the -+** packaging of this file. Please review the following information to -+** ensure the GNU Lesser General Public License version 3 requirements -+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -+** -+** GNU General Public License Usage -+** Alternatively, this file may be used under the terms of the GNU -+** General Public License version 2.0 or (at your option) the GNU General -+** Public license version 3 or any later version approved by the KDE Free -+** Qt Foundation. The licenses are as published by the Free Software -+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -+** included in the packaging of this file. Please review the following -+** information to ensure the GNU General Public License requirements will -+** be met: https://www.gnu.org/licenses/gpl-2.0.html and -+** https://www.gnu.org/licenses/gpl-3.0.html. -+** -+** $QT_END_LICENSE$ -+** -+****************************************************************************/ -+ -+#include "../linux-g++/qplatformdefs.h" ---- new/qt-everywhere-src-5.15.2/qtbase/src/3rdparty/angle/include/EGL/eglplatform.h -+++ qt-everywhere-src-5.15.2/qtbase/src/3rdparty/angle/include/EGL/eglplatform.h -@@ -141,6 +141,7 @@ - */ - typedef khronos_int32_t EGLint; - -+typedef uint32_t DISPMANX_ELEMENT_HANDLE_T; - - /* C++ / C typecast macros for special EGL handle values */ - #if defined(__cplusplus) ---- new/qt-everywhere-src-5.15.2/qtbase/src/gui/configure.json -+++ qt-everywhere-src-5.15.2/qtbase/src/gui/configure.json -@@ -862,7 +862,10 @@ - "type": "compile", - "test": { - "include": [ "EGL/egl.h", "bcm_host.h" ], -- "main": "vc_dispmanx_display_open(0);" -+ "main": [ -+ "vc_dispmanx_display_open(0);", -+ "EGL_DISPMANX_WINDOW_T *eglWindow = new EGL_DISPMANX_WINDOW_T;" -+ ] - }, - "use": "egl bcm_host" - }, ---- new/qt-everywhere-src-5.15.2/qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/qeglfsbrcmintegration.cpp -+++ qt-everywhere-src-5.15.2/qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/qeglfsbrcmintegration.cpp -@@ -44,6 +44,12 @@ - - static DISPMANX_DISPLAY_HANDLE_T dispman_display = 0; - -+typedef struct { -+ DISPMANX_ELEMENT_HANDLE_T element; -+ int width; /* This is necessary because dispmanx elements are not queriable. */ -+ int height; -+} EGL_DISPMANX_WINDOW_T; -+ - static EGLNativeWindowType createDispmanxLayer(const QPoint &pos, const QSize &size, int z, DISPMANX_FLAGS_ALPHA_T flags) - { - VC_RECT_T dst_rect; -@@ -76,12 +82,12 @@ - eglWindow->width = size.width(); - eglWindow->height = size.height(); - -- return eglWindow; -+ return (EGLNativeWindowType)eglWindow; - } - - static void destroyDispmanxLayer(EGLNativeWindowType window) - { -- EGL_DISPMANX_WINDOW_T *eglWindow = static_cast(window); -+ EGL_DISPMANX_WINDOW_T *eglWindow = (EGL_DISPMANX_WINDOW_T*)(window); - DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start(0); - vc_dispmanx_element_remove(dispman_update, eglWindow->element); - vc_dispmanx_update_submit_sync(dispman_update); diff --git a/ci/arm/qt_patch_arm64.patch b/ci/arm/qt_patch_arm64.patch new file mode 100644 index 0000000000..b67970dcb6 --- /dev/null +++ b/ci/arm/qt_patch_arm64.patch @@ -0,0 +1,41 @@ +diff -Naur qt-everywhere-src/qtbase/mkspecs/devices/linux-rasp-pi4-aarch64/qmake.conf qt-everywhere-src-5.15.10/qtbase/mkspecs/devices/linux-rasp-pi4-aarch64/qmake.conf +--- qt-everywhere-src/qtbase/mkspecs/devices/linux-rasp-pi4-aarch64/qmake.conf 2024-10-16 12:06:03.801661834 +0300 ++++ qt-everywhere-src-5.15.10/qtbase/mkspecs/devices/linux-rasp-pi4-aarch64/qmake.conf 1970-01-01 02:00:00.000000000 +0200 +@@ -1,25 +0,0 @@ +-# +-# Generic qmake configuration for building with g++ on Raspberry Pi 4 (64-bit). +-# +-# Tested with Raspberry Pi OS 64-bit and aarch64 gcc compiler from Debian package repository +-# +-# A minimal configure line could look something like this: +-# ./configure -release -opengl es2 -device linux-rasp-pi4-aarch64 -device-option CROSS_COMPILE=aarch64-linux-gnu- -sysroot ~/rpi-sysroot -prefix /usr/local/qt6 -extprefix $HOME/qt-raspi +- +-DISTRO_OPTS += deb-multi-arch +- +-include(../common/linux_device_pre.conf) +- +-QMAKE_LIBS_EGL += -lEGL +-QMAKE_LIBS_OPENGL_ES2 += -lGLESv2 -lEGL +- +-QMAKE_CFLAGS += -march=armv8-a +-QMAKE_CXXFLAGS += $$QMAKE_CFLAGS +- +-EGLFS_DEVICE_INTEGRATION = eglfs_kms +- +-LINKER_FLAGS += -Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed +- +-include(../common/linux_device_post.conf) +- +-load(qt_config) +diff -Naur qt-everywhere-src/qtbase/mkspecs/devices/linux-rasp-pi4-aarch64/qplatformdefs.h qt-everywhere-src-5.15.10/qtbase/mkspecs/devices/linux-rasp-pi4-aarch64/qplatformdefs.h +--- qt-everywhere-src/qtbase/mkspecs/devices/linux-rasp-pi4-aarch64/qplatformdefs.h 2024-10-16 12:06:21.493092913 +0300 ++++ qt-everywhere-src-5.15.10/qtbase/mkspecs/devices/linux-rasp-pi4-aarch64/qplatformdefs.h 1970-01-01 02:00:00.000000000 +0200 +@@ -1,8 +0,0 @@ +-/**************************************************************************** +-** +-** Copyright (C) 2022 The Qt Company Ltd. +-** SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +-** +-****************************************************************************/ +- +-#include "../../linux-g++/qplatformdefs.h" diff --git a/ci/arm/qt_patch_armhf.patch b/ci/arm/qt_patch_armhf.patch new file mode 100644 index 0000000000..7a742efde9 --- /dev/null +++ b/ci/arm/qt_patch_armhf.patch @@ -0,0 +1,54 @@ +--- new/qt-everywhere-src-5.15.2/qtbase/src/3rdparty/angle/include/EGL/eglplatform.h ++++ qt-everywhere-src-5.15.2/qtbase/src/3rdparty/angle/include/EGL/eglplatform.h +@@ -141,6 +141,7 @@ + */ + typedef khronos_int32_t EGLint; + ++typedef uint32_t DISPMANX_ELEMENT_HANDLE_T; + + /* C++ / C typecast macros for special EGL handle values */ + #if defined(__cplusplus) +--- new/qt-everywhere-src-5.15.2/qtbase/src/gui/configure.json ++++ qt-everywhere-src-5.15.2/qtbase/src/gui/configure.json +@@ -862,7 +862,10 @@ + "type": "compile", + "test": { + "include": [ "EGL/egl.h", "bcm_host.h" ], +- "main": "vc_dispmanx_display_open(0);" ++ "main": [ ++ "vc_dispmanx_display_open(0);", ++ "EGL_DISPMANX_WINDOW_T *eglWindow = new EGL_DISPMANX_WINDOW_T;" ++ ] + }, + "use": "egl bcm_host" + }, +--- new/qt-everywhere-src-5.15.2/qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/qeglfsbrcmintegration.cpp ++++ qt-everywhere-src-5.15.2/qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/qeglfsbrcmintegration.cpp +@@ -44,6 +44,12 @@ + + static DISPMANX_DISPLAY_HANDLE_T dispman_display = 0; + ++typedef struct { ++ DISPMANX_ELEMENT_HANDLE_T element; ++ int width; /* This is necessary because dispmanx elements are not queriable. */ ++ int height; ++} EGL_DISPMANX_WINDOW_T; ++ + static EGLNativeWindowType createDispmanxLayer(const QPoint &pos, const QSize &size, int z, DISPMANX_FLAGS_ALPHA_T flags) + { + VC_RECT_T dst_rect; +@@ -76,12 +82,12 @@ + eglWindow->width = size.width(); + eglWindow->height = size.height(); + +- return eglWindow; ++ return (EGLNativeWindowType)eglWindow; + } + + static void destroyDispmanxLayer(EGLNativeWindowType window) + { +- EGL_DISPMANX_WINDOW_T *eglWindow = static_cast(window); ++ EGL_DISPMANX_WINDOW_T *eglWindow = (EGL_DISPMANX_WINDOW_T*)(window); + DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start(0); + vc_dispmanx_element_remove(dispman_update, eglWindow->element); + vc_dispmanx_update_submit_sync(dispman_update); diff --git a/ci/arm/runtime-aarch64 b/ci/arm/runtime-aarch64 new file mode 100644 index 0000000000000000000000000000000000000000..c60ccae0aee26174c6d4a05419e73ae90e5a17fc GIT binary patch literal 196992 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/dev/null ) || \ SRC_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && cd ../../ && pwd ) -source $SRC_DIR/ci/armhf/armhf_build_config.sh BINARY=$1 LOCATION=$2 LIBS_ARRAY=() BLACKLISTED=($(wget --quiet https://raw.githubusercontent.com/probonopd/AppImages/master/excludelist -O - | sort | uniq | cut -d '#' -f 1 | grep -v "^#.*" | grep "[^-\s]")) -export LD_LIBRARY_PATH="${APP_DIR}/usr/lib:${SYSROOT}/lib:${SYSROOT}/lib/arm-linux-gnueabihf:${SYSROOT}/usr/arm-linux-gnueabihf/lib:${SYSROOT}/usr/local/qt5.15/lib:${SYSROOT}/usr/local/lib:${SRC_DIR}/build" +export LD_LIBRARY_PATH="${APP_DIR}/usr/lib:${SRC_DIR}/build:$LD_LIBRARY_PATH" run_ldd(){ for library in $(ldd "$1" | cut -d '>' -f 2 | awk '{print $1}') do From 814e9e74b6774e4c7d865347ab76e30ae8829e61 Mon Sep 17 00:00:00 2001 From: Bindea Cristian Date: Mon, 18 Nov 2024 11:16:36 +0200 Subject: [PATCH 3/4] core/CMakeLists: change how Python links to Scopy on arm architectures Signed-off-by: Bindea Cristian --- ci/arm/arm_build_process.sh | 1 + core/CMakeLists.txt | 13 ++++++------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ci/arm/arm_build_process.sh b/ci/arm/arm_build_process.sh index 412a04f379..0d95a83437 100755 --- a/ci/arm/arm_build_process.sh +++ b/ci/arm/arm_build_process.sh @@ -306,6 +306,7 @@ build_scopy() { CURRENT_BUILD_CMAKE_OPTS="\ -DENABLE_PLUGIN_TEST=ON \ -DENABLE_TESTING=ON \ + -DPYTHON_EXECUTABLE=$SYSROOT/bin/python3 \ " build_with_cmake popd diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 01cf4742a3..1b581110e4 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -60,16 +60,15 @@ if(${WITH_PYTHON}) message(STATUS "Using default Python EXECUTABLE") endif() - if(CMAKE_SYSTEM_PROCESSOR MATCHES arm) - find_package(Python3 3.9 EXACT REQUIRED COMPONENTS Interpreter) - message(STATUS "Host Python Interpreter " ${Python3_EXECUTABLE}) - set(Python3_EXECUTABLE ${CMAKE_SYSROOT}/bin/python3.9) - message(STATUS "Target Python Interpreter " ${Python3_EXECUTABLE}) + if(CMAKE_SYSTEM_PROCESSOR MATCHES arm OR CMAKE_SYSTEM_PROCESSOR MATCHES aarch64) + find_package(Python3 REQUIRED COMPONENTS Development) else() find_package(Python3 REQUIRED COMPONENTS Interpreter Development) - message(STATUS "Python Interpreter " ${Python3_EXECUTABLE}) - message(STATUS "Python Libraries " ${Python3_LIBRARIES}) endif() + + message(STATUS "Python Interpreter " ${Python3_EXECUTABLE}) + message(STATUS "Python Libraries " ${Python3_LIBRARIES}) + set(PYTHON_VERSION python${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR} CACHE STRING "PYTHON_USED") set(PYTHON_VERSION ${PYTHON_VERSION} PARENT_SCOPE) if(NOT Python3_FOUND) From f8bf9dc9e1034d21ada799676f4dbb85f3200579 Mon Sep 17 00:00:00 2001 From: Bindea Cristian Date: Mon, 18 Nov 2024 11:16:52 +0200 Subject: [PATCH 4/4] ci/arm: update copy-deps script Signed-off-by: Bindea Cristian --- ci/arm/arm_build_process.sh | 8 +- ci/arm/copy-deps.sh | 147 +++++++++++++++++++++++++++--------- 2 files changed, 117 insertions(+), 38 deletions(-) diff --git a/ci/arm/arm_build_process.sh b/ci/arm/arm_build_process.sh index 0d95a83437..63efc978f5 100755 --- a/ci/arm/arm_build_process.sh +++ b/ci/arm/arm_build_process.sh @@ -359,10 +359,10 @@ create_appdir(){ mkdir -p $APP_DIR/usr/lib/scopy/plugins/resources cp $EMU_CONFIG $APP_DIR/usr/lib/scopy/plugins/resources - $COPY_DEPS ${TOOLCHAIN_HOST} $APP_DIR/usr/bin/scopy $APP_DIR/usr/lib - $COPY_DEPS ${TOOLCHAIN_HOST} $APP_DIR/usr/bin/iio-emu $APP_DIR/usr/lib - $COPY_DEPS ${TOOLCHAIN_HOST} $APP_DIR/usr/bin/scopy $APP_DIR/usr/lib - $COPY_DEPS ${TOOLCHAIN_HOST} "$APP_DIR/usr/lib/scopy/plugins/*.so" $APP_DIR/usr/lib + $COPY_DEPS --lib-dir ${SYSROOT}:${BUILD_FOLDER} --output-dir $APP_DIR/usr/lib $APP_DIR/usr/bin/scopy + $COPY_DEPS --lib-dir ${SYSROOT}:${BUILD_FOLDER} --output-dir $APP_DIR/usr/lib $APP_DIR/usr/bin/iio-emu + $COPY_DEPS --lib-dir ${SYSROOT}:${BUILD_FOLDER} --output-dir $APP_DIR/usr/lib $APP_DIR/usr/bin/scopy + $COPY_DEPS --lib-dir ${SYSROOT}:${BUILD_FOLDER} --output-dir $APP_DIR/usr/lib "$APP_DIR/usr/lib/scopy/plugins/*.so" cp -r $QT_LOCATION/plugins $APP_DIR/usr # search for the python version linked by cmake and copy inside the appimage the same version diff --git a/ci/arm/copy-deps.sh b/ci/arm/copy-deps.sh index 1d2ca90b58..79352cadd9 100755 --- a/ci/arm/copy-deps.sh +++ b/ci/arm/copy-deps.sh @@ -1,43 +1,122 @@ #!/bin/bash set -e -SRC_DIR=$(git rev-parse --show-toplevel 2>/dev/null ) || \ -SRC_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && cd ../../ && pwd ) -source $SRC_DIR/ci/arm/arm_build_config.sh $1 -BINARY=$2 -LOCATION=$3 +usage() +{ + echo "test" + +} +COPY="" + +while [ "$1" != "" ] +do + case "$1" in + "--help"| "-h") + usage + exit + ;; + "--lib-dir" | "-l") + SYSROOT="$2:$SYSROOT" + shift + ;; + "--output-dir" | "-o") + OUTPUT_DIR="$2" + COPY="true" + shift + ;; + *) + FILES="$FILES $1" + ;; + esac + shift +done + LIBS_ARRAY=() -BLACKLISTED=($(wget --quiet https://raw.githubusercontent.com/probonopd/AppImages/master/excludelist -O - | sort | uniq | cut -d '#' -f 1 | grep -v "^#.*" | grep "[^-\s]")) - -if [ ! -f "${SRC_DIR}"/ci/arm/ldd-mod ]; then - if [ ${TOOLCHAIN_HOST} == "aarch64-linux-gnu" ];then - sed 's|.*RTLDLIST=.*|RTLDLIST="/usr/aarch64-linux-gnu/lib/ld-2.31.so /usr/aarch64-linux-gnu/lib/ld-linux-aarch64.so.1"|' /usr/bin/ldd | tee "${SRC_DIR}"/ci/arm/ldd-mod - elif [ ${TOOLCHAIN_HOST} == "arm-linux-gnueabihf" ]; then - sed 's|.*RTLDLIST=.*|RTLDLIST="/usr/arm-linux-gnueabihf/lib/ld-2.31.so /usr/arm-linux-gnueabihf/lib/ld-linux-armhf.so.3"|' /usr/bin/ldd | tee "${SRC_DIR}"/ci/arm/ldd-mod - fi - chmod +x "${SRC_DIR}"/ci/arm/ldd-mod +# Separate SYSROOT into an array of SEARCH_PATHS +IFS=":" read -r -a SEARCH_PATHS <<< "$SYSROOT" + +# If COPY is not true, display all dependencies without excluding any from the blacklist +if [[ $COPY != "true" ]]; then + BLACKLISTED="" +else + BLACKLISTED=($(wget --quiet https://raw.githubusercontent.com/probonopd/AppImages/master/excludelist -O - | sort | uniq | cut -d '#' -f 1 | grep -v "^#.*" | grep "[^-\s]")) + BLACKLISTED+=(ld-linux-armhf.so) + BLACKLISTED+=(ld-linux-aarch64.so) + BLACKLISTED+=(ld-linux-armhf.so.3) + BLACKLISTED+=(ld-linux-aarch64.so.1) fi -export LD_LIBRARY_PATH="${APP_DIR}/usr/lib:${SYSROOT}/lib:${SYSROOT}/lib/${TOOLCHAIN_HOST}:${SYSROOT}/usr/${TOOLCHAIN_HOST}/lib:${SYSROOT}/usr/local/qt5.15/lib:${SYSROOT}/usr/local/lib:${SRC_DIR}/build" -run_ldd(){ - for library in $("${SRC_DIR}"/ci/arm/ldd-mod "$1" | cut -d '>' -f 2 | awk '{print $1}') - do - # check if the library exists at that path and if it was processed already or blacklisted - if ! [[ "${BLACKLISTED[*]}" =~ "${library##*/}" ]]; then - if [ -f "${library}" ] && ! [[ "${LIBS_ARRAY[*]}" =~ "${library}" ]]; then - LIBS_ARRAY+=("${library}") - echo "---Added new lib: ${library}" - if [ ! -f "${LOCATION}"/"${library##*/}" ]; then - cp "${library}" "${LOCATION}" - [ -L "${library}" ] && cp "$(realpath "${library}")" "${LOCATION}" - fi - run_ldd "${library}" - fi - fi - done +findlib() +{ + LIB=$1 + for path in "${SEARCH_PATHS[@]}" + do + LIB_PATH=$(find "$path" -name "${LIB%%.so*}.so*" -type f 2>/dev/null | sort | head -1) + [ "$LIB_PATH" != "" ] && break # Exit for at first succesful find + done + + [ "$LIB_PATH" = "" ] && LIB_PATH="not found" + echo "$LIB_PATH" } -for arg in $BINARY; do - run_ldd "${arg}" -done +copylib() +{ + library=$1 + destination=$2 + + lib_location=${library%/*} + lib_name=${library##*/} + lib_name_without_version=${lib_name%%.so*}.so + + echo "${lib_name_without_version}" + echo -n copied: + cp --verbose "${library}" "${destination}" + + #IFS=$'\n' read -r -a symlinks < <(find "$lib_location" -name "${lib_name_without_version}*" -type l 2>/dev/null) || echo "No symlinks to copy" + + symlinks=($(find "$lib_location" -name "${lib_name_without_version}*" -type l 2>/dev/null)) + for link in "${symlinks[@]}" + do + pushd ${destination} > /dev/null + [ -L "${link##*/}" ] && rm "${link##*/}" + echo -n linked: + ln --symbolic --verbose "${library##*/}" "${link##*/}" + popd > /dev/null + done +} + +process_lib(){ + DEPS=$(readelf -d "$1" 2> /dev/null | \ + grep NEEDED | \ + cut -d ":" -f 2 | \ + sed -e 's,\[,,g' -e 's,],,g' -e 's,[ ]*,,g'| \ + sort) + + for library in $DEPS + do + # Check if the library is blacklisted or was already processed + if [[ ! "${BLACKLISTED[*]}" =~ "${library}" && ! "${LIBS_ARRAY[*]}" =~ "${library}" ]]; then + + LIBS_ARRAY+=("${library}") + LIB_PATH=$(findlib "$library") # try to find the library in sysroot + + if [[ $COPY == "true" ]]; then + if [[ $LIB_PATH == "not found" ]]; then + echo "Error: ${library} not found" + exit 1 + fi + mkdir -p "$OUTPUT_DIR" + copylib "$LIB_PATH" "$OUTPUT_DIR" + fi + + # If COPY is not true, display only the library and its location if found + [ "$COPY" != "true" ] && echo "$library => $LIB_PATH" + process_lib "$LIB_PATH" + fi + done +} + +for arg in $FILES; do + process_lib "${arg}" +done \ No newline at end of file