probonopd / linuxdeployqt

Makes Linux applications self-contained by copying in the libraries and plugins that the application uses, and optionally generates an AppImage. Can be used for Qt and other applications
Other
2.22k stars 414 forks source link

ARM32 cross-compile problem #539

Closed haroldsamuels87 closed 2 years ago

haroldsamuels87 commented 2 years ago

Hi, I am cross-compiling a Qt program for arm32 on an amd64 machine (with docker) and I want it to be deployed with linuxdeployqt. I use ubuntu base image and apt-get to install necessary qt libraries. here is my Dockerfile:

FROM --platform=linux/arm/v7 ubuntu:jammy

RUN apt-get update 

RUN export DEBIAN_FRONTEND=noninteractiv && \
 apt -y install build-essential cmake git \
 gdb wget curl nano file patchelf \
 qtbase5-dev libqt5qml5 qtdeclarative5-dev \
 qml-module-qtquick2 qml-module-qtquick-window2 qml-module-qtquick-controls2 

 RUN cd /home && \
     git clone https://github.com/probonopd/linuxdeployqt.git && cd linuxdeployqt &&  \
     git checkout continuous && \
     export PATH=$(readlink -f /tmp/.mount_QtCreator-*-x86_64/*/gcc_64/bin/):$PATH && \
     cd /home/linuxdeployqt && \
     qmake && \
     make -j$(nproc) && sudo make install 

 RUN  wget -c \
  "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-armhf.AppImage" \
  -O /usr/local/bin/appimagetool && \
  chmod a+x /usr/local/bin/appimagetool

I used patchelf v0.14 because patchelf v0.9 was damaging the main executable, it gave me a warning with following message: creating a hole of ~50KB to work around a linux kernel bug. my program compiles successfully and if I copy it to the arm32 machine, it just works fine. now when I try to use linuxdeployqt with the folowing command :

linuxdeployqt <EXECUTABLE> -no-translations -unsupported-allow-new-glibc -appimage -qmldir=<PATH> -no-copy-copyright-files -no-strip

I see this error:

ERROR: Could not parse ldd output under 2 lines: ""
QProcess: Destroyed while process ("ldd") is still running.
QProcess: Destroyed while process ("objdump") is still running.

I inspected the code and I figured out that the QProcess is malfunctioning. if I use ldd on my program it shows dependencies correctly. I created a simple program to test QProcess and again it just did not work with any type of command. I searched the internet and couldn't find any solution to this problem so I decided to change the code and I came with this temporary solution. I created a function to open a process with popen instead of QProcess :

QByteArray q_process_alternative(const QString &command, const QStringList &arguments){
    QByteArray ret_val;
    FILE *fp;
    char line[200];         
    char command_str[5000];
    sprintf(command_str,"%s %s", command.toLocal8Bit().data(), arguments.join(" ").toLocal8Bit().data());
    printf("command_str->%s\n",command_str );
    fp = popen(command_str, "r");       
    while ( fgets( line, sizeof line, fp))
    {
        ret_val += QByteArray::fromRawData(line, strlen(line));
    }
    pclose(fp);
    return ret_val;
}

I know it's not an efficient alternative but I wanted an ad-hoc and quick solution and it worked with ldd but patchelf complains about missing filename. patchelf issues a command like this line:

patchelf $ORIGIN /path/to/libQtX.so.x

I could not find out what this $ORIGIN is and what it does. Can anybody please help me with that? To Summarize I have these questions:

  1. How to fix QProcess problem on an emulated docker container?(in my case host machine is amd64 and target is arm32 and I use qemu-arm-static)
  2. If it's not possible to fix QProcess problem, How can I write a QProcess alternative for shared.cpp and is this the correct way?
  3. what is $ORIGIN in shared.cpp, I couldn't find any documentation on that.

Thanks