Qt 4.8 Cross Compile for Embedded Linux using Linaro Toolchain from Windows

PhilBot picture PhilBot · Jul 16, 2012 · Viewed 10.6k times · Source

I am trying to use the 2012.06 version of the Linaro Toolchain Windows Binary ( https://launchpad.net/linaro-toolchain-binaries/trunk/ ) to cross-compile the Qt 4.8 source to target an embedded Linux ARM Cortex-8 board. I was able to do this with the CodeSourcery toolchain mentioned in this post --> http://c2143.blogspot.com/?view=classic. But the target board software was built with the Linaro toolchain and so I am working towards that end.

I have patched the mkspec mentioned in the post above to look like this:

#
# qmake configuration for building with arm-none-linux-gnueabi-g++
#
include(../common/unix.conf)
include(../common/gcc-base-unix.conf)
include(../common/g++-unix.conf)
include(../common/qws.conf)

MAKEFILE_GENERATOR      = MINGW
CONFIG                 += no_import_libs no_generated_target_info
# 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++
QMAKE_LIB               = arm-linux-gnueabihf-ar
QMAKE_AR                = arm-linux-gnueabihf-ar cqs
QMAKE_OBJCOPY           = arm-linux-gnueabihf-objcopy
QMAKE_STRIP             = arm-linux-gnueabihf-strip
QMAKE_RUN_CC            = $(CC) -c $(CFLAGS) $(INCPATH) -o $obj $src
QMAKE_RUN_CC_IMP        = $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
QMAKE_RUN_CXX           = $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $obj $src
QMAKE_RUN_CXX_IMP       = $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
QMAKE_INCDIR            =
QMAKE_INCDIR_QT         = $$[QT_INSTALL_HEADERS]
QMAKE_LIBDIR_QT         = $$[QT_INSTALL_LIBS]
QMAKE_MOC               = $$[QT_INSTALL_BINS]\\moc.exe
QMAKE_UIC               = $$[QT_INSTALL_BINS]\\uic.exe
QMAKE_IDC               = $$[QT_INSTALL_BINS]\\idc.exe
QMAKE_COPY              = copy /y
QMAKE_COPY_DIR          = xcopy /s /q /y /i
QMAKE_MOVE              = move
QMAKE_DEL_FILE          = del
QMAKE_MKDIR             = mkdir
QMAKE_DEL_DIR           = rmdir
QMAKE_CHK_DIR_EXISTS    = if not exist
QMAKE_IDL               = midl
QMAKE_ZIP               = zip -r -9
CODESOURCERY_ARM_CFLAGS = -march=armv7-a -mtune=cortex-a8 -mthumb -mfpu=vfp -mfloat-abi=softfp -Wa,-mimplicit-it=thumb -marm -mthumb-interwork
#modifications to gcc-base.conf
QMAKE_CFLAGS           += $$CODESOURCERY_ARM_CFLAGS
QMAKE_CXXFLAGS         += $$CODESOURCERY_ARM_CFLAGS
QMAKE_LIBS             += -lrt -lpthread -ldl
QMAKE_LFLAGS           += $${QMAKE_LFLAGS_RPATH}$$[QT_INSTALL_LIBS]
!isEmpty(TARGET_QTDIR) {
    QMAKE_LFLAGS       += $${QMAKE_LFLAGS_RPATH}$${TARGET_QTDIR}/lib
}
!isEmpty(TARGET_SYSROOT) {
    QMAKE_LFLAGS       += $${QMAKE_LFLAGS_RPATH}$${TARGET_SYSROOT}/lib:$${TARGET_SYSROOT}/usr/lib
    QMAKE_LFLAGS       += -Wl,--dynamic-linker=$${TARGET_SYSROOT}/lib/ld-linux.so.3
}
load(qt_config)

When I run mingw32-make on the top level Makefile in order to produce the Qt libraries for the ARM board it compiles for a while but inevitably errors with:

collect2.exe: error: ld returned 1 exit status
mingw32-make[1]: *** [..\..\lib\libQtCore.so] Error 1
mingw32-make[1]: Leaving directory `C:/Users/user/Desktop/qt_creator_toolchain...
mingw32-make: *** [sub-corelib-make_default-ordered] Error 2

This error happens after many complaints like:

*.so uses VFP register arguments, *obj does not

I've researched that error and have tried to pass each of the following options to my mkespec and rebuild with the same error:

-mfloat-abi=softfp
-mfloat-abi=soft
-mfloat-abi=hard

I am clearly not understanding why the '-mfloat-abi=softfp' option works fine with the CodeSourcery Windows toolchain but not Linaro. The rest of the compiler flags are shown in the mkspec above.

Does anybody have any insight or thoughts on how to make this work? Thanks in advance.

UPDATE:

It turns out if I modify my C_FLAGS in the mkspec from this:

-march=armv7-a -mtune=cortex-a8 -mthumb -mfpu=vfp -mfloat-abi=softfp -Wa,-mimplicit-it=thumb -marm -mthumb-interwork

to this:

-march=armv7-a -mtune=cortex-a8 -mthumb -mfpu=neon -mfloat-abi=hard -Wa,-mimplicit-it=thumb -marm -mthumb-interwork

Then I can finally successfully compile Qt. How will this affect my performance / or ability to run a Qt App on the Board? Why can't I do softfp with Linaro but I can with CodeSourcery?

Answer

shawn xy bai picture shawn xy bai · Jul 18, 2012

- Hi, phil999,
Cortex-A Series Programmer’s Guide Version: 2.0
at http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0013a/index.html

From the document, it is known that
-mfpu=vfp specifies that the target has VFP hardware. (As does specifying the option -mfpu=neon.)
So, according to your C_FLAGS, option "-mfpu=vfp" equates with option"-mfpu=neon", the difference in Linaro may lie between option "-mfloat-abi=softfp" and option "-mfloat-abi=hard".

From the errors provided,

This error happens after many complaints like: *.so uses VFP register arguments, *obj does not


it seems that lib files are compiled with "-mfloat-abi=hard", which is recognized by "uses VFP register arguments".

'Cause if option "-mfloat-abi=softfp" is used for compiling lib files, floating-point arguments will be passed in R0-R3 and in stack space;
Option "-mfloat-abi=hard" must be spicified, once passing floating-point arguments in VFP or NEON floating-point registers.

So, in order to link with those lib files compiled with "-mfloat-abi=hard", you should also compile QT with "-mfloat-abi=hard", or, there will be some similar complaints as you encountered.

Besides, from the readme in gcc-linaro-arm-linux-gnueabihf-2012.06-20120625_win32\gcc-linaro-arm-linux-gnueabihf-2012.06-20120625_win32\share\doc\gcc-linaro-arm-linux-gnueabihf

Some points in readme are as follows

Target compatibility


The arm-linux-gnueabihf version targets the Linaro Evaluation Build 12.05 flavour of Ubuntu 12.04 "Precise Pangolin". The default configuration is:

  • Runs on all Cortex-A profile devices
  • Tuned for the Cortex-A9
  • Thumb-2
  • 'hard float' calling convention
  • Uses the VFPv3-D16 FPU
  • Multiarch and multilib enabled
  • EGLIBC 2.15
  • A GCC 4.7 series libgcc and libstdc++

To use softfp or hard

Two points:
1. Using float-abi with "softfp", it is backward compatibility with older softfp ABI codes.
2. with "-mfloat-abi=hard", it is more efficient, but is not backward compatibility with softfp abi codes.

More details will be found in "18.2 VFP support in GCC" and "15.1.1 VFP and NEON register usage" in Cortex-A Series Programmer’s Guide Version: 2.0 listed at the beginning.

Thanks.