Cross Compiling with Qt

In case anyone is interested or just getting started, I have put together a write up of how to get Qt configured and built for cross compiling on the Jetson on Ubuntu 16.04. I have also put together some scripts to automate the entire process which really saves a lot of time. The document describing the entire process for both the manual configuration and automated configuration is located here, https://www.innovative-dsp.com/ftp/jetson/Configure%20Cross%20Compiling%20for%20Nvidia%20Jetson%20TX2%20on%20Ubuntu%2064%20bit.pdf.

The scripts are in the same location here, https://www.innovative-dsp.com/ftp/jetson/.

Please let me know if anything is unclear and I will amend the documentation and or scripts for clarity. Complements of Innovative Integration!

Hi,
I tried Configuring Cross Compiling for Nvidia Jetson TX2 on Ubuntu 64 bit as per your link above https://www.innovative-dsp.com/ftp/jetson/Configure%20Cross%20Compiling%20for%20Nvidia%20Jetson%20TX2%20on%20Ubuntu%2064%20bit.pdf

However, I ran into the following issues. Could you let know how you resolved these issues?

  1. Jetpack 3.0 can be installed only Ubuntu 14.04 and so my host is a Ubuntu 14.04.

While executing the command below in Section 1 for the host, I got the message “Unable to locate package gcc-5-arm-linux-gnueabi”
, “Unable to locate package g+±5-arm-linux-gnueabi”
Could You let know how you resolved this issue?

[b]#Install the GCC ARM toolset Linaro **VERSION 5
Run the following command,

sudo apt-get install -y gcc-5-arm-linux-gnueabi g+±5-arm-linux-gnueabi [/b]

2)In Section 2 - Compile Qt, while trying to install Qt by the command ‘sudo make install’, the following undefined reference errors were observed.

Any pointers as to the cause of the error and how you resolved it?

_tx2/rootfs/usr/lib/aarch64-linux-gnu -L/usr/lib/aarch64-linux-gnu -L/opt/qt-everywhere-opensource-src-5.9.0/qtserialbus/lib -lQt5SerialBus -L/opt/qt-everywhere-opensource-src-5.9.0/qtbase/lib -lQt5Core -lpthread
/opt/qt-everywhere-opensource-src-5.9.0/qtserialbus/lib/libQt5SerialBus.so: undefined reference to QTcpServer::newConnection()@Qt_5' /opt/qt-everywhere-opensource-src-5.9.0/qtserialbus/lib/libQt5SerialBus.so: undefined reference to QTcpServer::QTcpServer(QObject*)@Qt_5
/home/Downloads/64_TX2/Linux_for_Tegra_tx2/rootfs/usr/lib/aarch64-linux-gnu/libQt5Network.so.5: undefined reference to qt_safe_select(int, fd_set*, fd_set*, fd_set*, timespec const*)' /opt/qt-everywhere-opensource-src-5.9.0/qtserialbus/lib/libQt5SerialBus.so: undefined reference to QTcpServer::acceptError(QAbstractSocket::SocketError)@Qt_5
/opt/qt-everywhere-opensource-src-5.9.0/qtserialbus/lib/libQt5SerialBus.so: undefined reference to `QTcpServer::close()@Qt_5

/opt/qt-everywhere-opensource-src-5.9.0/qtserialbus/lib/libQt5SerialBus.so: undefined reference to QHostAddress::~QHostAddress()@Qt_5' /home/Downloads/64_TX2/Linux_for_Tegra_tx2/rootfs/usr/lib/aarch64-linux-gnu/libQt5Network.so.5: undefined reference to qIsEffectiveTLD(QString const&)’
/opt/qt-everywhere-opensource-src-5.9.0/qtserialbus/lib/libQt5SerialBus.so: undefined reference to QAbstractSocket::connected()@Qt_5' /opt/qt-everywhere-opensource-src-5.9.0/qtserialbus/lib/libQt5SerialBus.so: undefined reference to QAbstractSocket::peerName() const@Qt_5’
/opt/qt-everywhere-opensource-src-5.9.0/qtserialbus/lib/libQt5SerialBus.so: undefined reference to QAbstractSocket::state() const@Qt_5' /opt/qt-everywhere-opensource-src-5.9.0/qtserialbus/lib/libQt5SerialBus.so: undefined reference to QAbstractSocket::staticMetaObject@Qt_5’
/opt/qt-everywhere-opensource-src-5.9.0/qtserialbus/lib/libQt5SerialBus.so: undefined reference to QAbstractSocket::error(QAbstractSocket::SocketError)@Qt_5' /opt/qt-everywhere-opensource-src-5.9.0/qtserialbus/lib/libQt5SerialBus.so: undefined reference to QTcpServer::isListening() const@Qt_5’
/opt/qt-everywhere-opensource-src-5.9.0/qtserialbus/lib/libQt5SerialBus.so: undefined reference to QAbstractSocket::peerAddress() const@Qt_5' /opt/qt-everywhere-opensource-src-5.9.0/qtserialbus/lib/libQt5SerialBus.so: undefined reference to QAbstractSocket::disconnected()@Qt_5
/opt/qt-everywhere-opensource-src-5.9.0/qtserialbus/lib/libQt5SerialBus.so: undefined reference to QTcpServer::errorString() const@Qt_5' /opt/qt-everywhere-opensource-src-5.9.0/qtserialbus/lib/libQt5SerialBus.so: undefined reference to QTcpSocket::QTcpSocket(QObject*)@Qt_5
/opt/qt-everywhere-opensource-src-5.9.0/qtserialbus/lib/libQt5SerialBus.so: undefined reference to QHostAddress::QHostAddress(QString const&)@Qt_5' /opt/qt-everywhere-opensource-src-5.9.0/qtserialbus/lib/libQt5SerialBus.so: undefined reference to QAbstractSocket::peerPort() const@Qt_5’
/opt/qt-everywhere-opensource-src-5.9.0/qtserialbus/lib/libQt5SerialBus.so: undefined reference to QTcpServer::staticMetaObject@Qt_5' /opt/qt-everywhere-opensource-src-5.9.0/qtserialbus/lib/libQt5SerialBus.so: undefined reference to QTcpServer::listen(QHostAddress const&, unsigned short)@Qt_5
/opt/qt-everywhere-opensource-src-5.9.0/qtserialbus/lib/libQt5SerialBus.so: undefined reference to operator<<(QDebug, QHostAddress const&)@Qt_5' collect2: error: ld returned 1 exit status make[4]: *** [../../../bin/canbusutil] Error 1 make[4]: Leaving directory /opt/qt-everywhere-opensource-src-5.9.0/qtserialbus/src/tools/canbusutil’
make[3]: *** [sub-canbusutil-install_subtargets] Error 2
make[3]: Leaving directory /opt/qt-everywhere-opensource-src-5.9.0/qtserialbus/src/tools' make[2]: *** [sub-tools-install_subtargets] Error 2 make[2]: Leaving directory /opt/qt-everywhere-opensource-src-5.9.0/qtserialbus/src’
make[1]: *** [sub-src-install_subtargets] Error 2
make[1]: Leaving directory `/opt/qt-everywhere-opensource-src-5.9.0/qtserialbus’
make: *** [module-qtserialbus-install_subtargets] Error 2
vm@vm-VirtualBox:/opt/qt-everywhere-opensource-src-5.9.0$

  1. After successful creation and deployment of a Qt app exe to the target Jetson TX2 device, should an attempt to execute in the target Jetson TX2 board be successful?

After the Section 2 - sudo make install on the host, when doing the resync operation under #Copy Qt5 to the Jetson Device, does the host and the device get synced with the environment required for executing Qt app exe on the target board? Does rsync’ng along the ‘qt5’ folder from the host to the target device suffice for this case? Please advise.

Thanks
M

FYI, arm-linux-gnueabi implies an older ARMv7 32-bit system. For a JTX2 you want arm64/aarch64. The CPU architecture is ARMv8, which normally implies the native 64-bit operating mode, but you may find some tool chains which name ARMv8 as 32-bit compatibility to the armhf…if this is the case they will name other packages as arm64 or aarch64. gnueabi would be incorrect for almost all JTX2 compiles (there are some exceptions for 32-bit compatibility mode). FYI, 32-bit ARMv8 compatibility mode is mostly ARMv7 with NEON extension and hard float calling convention…which in turn is what armhf implies.

Perhaps the software which was downloaded is expecting older 32-bit ARM.

I used the jetsonhacks tutorial for qt-creator:http://www.jetsonhacks.com/2017/01/31/install-qt-creator-nvidia-jetson-tx1/
It was not cross-compiling, though.

Here’s an excerpt from the tutorial which sticks out for this case:

Here’s the where the first issue comes into play. When GCC is added to the compiler list, it does not set the processor architecture flag correctly. As shown in the video, remedy this issue by modifying the ABI section of the GCC compiler dialog. Change the setting to:

    custom – arm – linux – generic – elf – 64 bit

Having armhf in the compiler search tends to point at this ABI change (or lack thereof) mistaking the system for 32-bit armhf. I’m not sure where that setting is being used, but it could be what gets around the armhf issue. There is a reference in that tutorial which refers to a tk1, so this might need some armhf/arm64 translation.

The gcc-5-arm-linux-gnueabi package may not be a part of the repo list for Ubuntu 14.04. It worked fine on 16.04 so you might have to do a search to find a third party repo that has this package and add it to your repo list.

I will try this process again from scratch to see if I can replicate those compile errors and see what it takes to fix them.

I use Fedora on my host, so I always manually install Linaro for cross compiles. On a TX2 it might be a matter of adding the armhf as a foreign architecture before the tools show up (normally only arm64/aarch64 64-bit tools are listed from the relevant repositories). Unless the Jetson knows you want to see armhf, and unless you have a repository enabled with this, there is no way for the standard apt-get tools to find the armhf version.

The point here is that someone was getting an error for missing armhf (32-bit), but you don’t want to build 32-bit, so it is more likely that ABI note which is the issue (having a 64-bit ABI means it most likely will look instead for arm64/aarch64…then you’d get a native 64-bit architecture build and not a 32-bit compatibility build).

The compile errors are caused by a conflict between the version of Qt installed by default on the Jetson module and the one you are trying to build and those .so files are copied to the rootfs during this procedure. To fix that, you must remove the older Qt .so files. Navigate to $HOME/64_TX2/Linux_for_Tegra_tx2/rootfs/usr/lib/aarch64-linux-gnu and delete all files named libQt*.*. This same problem will haunt you when running the executable on the Jetson device so you have to manually specify that it use the new Qt that you just built by setting the LD_LIBRARY_PATH to /usr/local/qt5/lib with command,
export LD_LIBRARY_PATH=/usr/local/qt5/lib. I will amend the script and documentation to incorporate these fixes.

Hi, I also do Cross Compile with Qt for Jetson TX2. I use Qt5.10. But I have an error when to do “make”:

"aarch64-linux-gnu/bin/ld: /home/cat/Jetpack33/64_TX2/Linux_for_Tegra/rootfs/usr/lib/aarch64-linux-gnu/libz.a(compress.o): relocation R_AARCH64_ADR_PREL_PG_HI21 against external symbol `__stack_chk_guard@@GLIBC_2.17’ can not be used when making a shared object; recompile with -fPIC

/home/cat/Jetpack33/64_TX2/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/…/lib/gcc/aarch64-linux-gnu/7.3.1/…/…/…/…/aarch64-linux-gnu/bin/ld: /home/cat/Jetpack33/64_TX2/Linux_for_Tegra/rootfs/usr/lib/aarch64-linux-gnu/libz.a(compress.o)(.text+0x10): unresolvable R_AARCH64_ADR_PREL_PG_HI21 relocation against symbol `__stack_chk_guard@@GLIBC_2.17

/home/cat/Jetpack33/64_TX2/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/…/lib/gcc/aarch64-linux-gnu/7.3.1/…/…/…/…/aarch64-linux-gnu/bin/ld: final link failed: Bad value"

  1. To recompile with -fPIC, I find down someone to solve it: replace -fPIE to -fPIC in Makefile.inc, but I couldn’t find down where Makefile is?

The makefile in directory: rootfs/opt/qt-everywhere-src-5.10.1 doesn’t have -fPIE.

  1. I also saw in qmake.conf file in qtbase/mkspecs/devices/linux-jetson-tx1-g++/ they said that:

If getting cryptic linker errors from static libs like libm.a, check that the

symlinks libm.so, libz.so, etc. under rootfs/usr/lib/aarch64-linux-gnu are not

broken. If they are, due to using absolute paths, change them so that they are

relative to rootfs.

and the libz.so in my directory is “link broken”. But I don’t know how to solve it?

Please give me some advice. Thank you.

I’m a long way from being able to solve this, but a library of name suffix “.a” is static, not dynamic. The -fPIC implies you need a dynamic library and not static (ending with “.so”…but of course it is the actual library build which is static or dynamic, so changing the file name won’t fix anything).

Possibly it is telling you that you need a dynamic library for libz (libz.so) instead of a static library (not libz.a).

If a project has a configuration tool (such as a “./configure” script or any other pre-build configuration setup tool), then often you will find an option to use a static versus dynamic version of a library. I can’t help for this case, but perhaps you have such an option setup available.

Hi linuxdev, thank you for your reply.

  1. I use ./configure command line. So how to set with a dynamic library?

  2. Do you know where is makefile.inc file? I want to try with -fPIC, the error says: “can not be used when making a shared object; recompile with -fPIC

  3. The “libz.o” file in /rootfs/usr/lib/aarch64-linux-gnu/ is: link (broken), others are link to unknown. I checked the libz.o on Jetson TX2 is “link to Unknown”, I also run rsync command again. But it is still “link (broken)” on host pc (means in rootfs). Could you help me to solve it?

Thank you sir.

Each “./configure” is unique to the software. Usually “./configure --help | less” is a good way to see all options.

The makefile.inc is also custom and might be part of the configure step (meaning the “right thing” would happen if the “./configure” step is correct for your system). I couldn’t give you any specific details.

I will guess that you will want to configure, find an error, fix the one error, configure again, and so on until configure itself works. Fixes will likely mean either telling configure to include or exclude a feature in combination with adding new packages (including the dev version of packages).

FYI, I have many repositories enabled, and if you don’t see something you are searching for then there is a chance you just need to enable the relevant repository.

Take for example libz. If I search the system for the dynamic version (not the “.a”), then via “ldconfig -p” I see “/lib/aarch64-linux-gnu/libz.so.1”. I can know the package which installed this via “dpkg -S /lib/aarch64-linux-gnu/libz.so.1”: “zlib1g” (it is actually “zlib1g.arm64” since it is on arm64, but the base package is “zlib1g”).

To see what packages might be related I run “apt search zlib1g”. I see several, but the one you’ll need to build software against this is the “dev” version:

zlib1g-dev

I happen to already have this installed (via “sudo apt-get install zlib1g-dev”). To list if you have this package already:

dpkg -l | egrep zlib1g

Interestingly I find that “/usr/lib/aarch64-linux-gnu/libz.a” is also provided by the same “zlib1g-dev” package. So you might already have this. The implication is that your configure needs to be told to not use libz.a and instead use libz.so (but I can’t tell you the specific configure step…see “./configure --help”).

I always start with “./configure --prefix=/usr/local”. From this I add or remove options which fail in configure if I cannot install a dependency through “sudo apt-get …”. Then when build occurs there is a similar iterative approach to fixing errors one at a time.

Sorry, I don’t have any exact solution.

Is the pdf still available? To me the link is broken.

here is a new link http://s000.tinyupload.com/index.php?file_id=20681921323297665665

The newer link is broken too. Can you please share a working link?

The new link is broken, could you please share a new one? thanks