December 27th 2014, APK Size Reduction
← December 15th 2014 QtTorch App | ● | January 21th 2015 UI Simplification →
Reducing the size of an Android APK, has both the benefit of a smaller foot print and a faster startup.
Usually a Qt app for Android consists of several modules (*.cpp) defined in the qmake project. Each module is compiled into an object file (*.o). Those are linked together into an executable. Finally this gets packaged with the Qt shared libraries to yield an APK.
The caveat on using the GCC as linker stage is that the GCC linker will include all object files (*.o) supplied on the command line into the executable, no matter if a particular module is used or not. So unused modules will blow up the executable.
The GCC linker, however, is of course able to abandon unused modules, but this requires an intermediate step. All the object files need to be placed in a static archive, from which the linker will pick only those modules that are actually referenced from another module. If they are not referenced, the GCC will not link the unused module.
However, another caveat with Qt is that it is not possible to use a static object file library within a single QMake project file (as opposed to CMake). We can try to split the creation of the static library into another project file, but yet another caveat of Qt is that it will only get the dependencies right if we put the modules into a separate directory. I won’t go into the details, because this would be lengthy, but the fact is that I’ve tried various approaches but none was getting static linkage right without using separate directories.
So with QMake a reasonable module layout of an app will always include a directory for a static library and a directory for the executable, which will look like that:
libXYZ/ module*.cpp libXYZ.pro app/ main.cpp app.pro toplevel.pro
In the toplevel project file toplevel.pro we include the two subdirs libXYZ and app and get the dependency of the app on the library right by specifying the depends section of the target like so:
TEMPLATE = subdirs SUBDIRS = libXYZ app app.depends = libXYZ
The project file libXYZ.pro to create the static library looks like that:
TARGET = XYZ TEMPLATE = lib CONFIG += staticlib HEADERS = *.h SOURCES = *.cpp QT += core widgets
And finally the project file app.pro for the executable that links with the static library looks like that:
TARGET = App TEMPLATE = app HEADERS = *.h SOURCES = *.cpp INCLUDEPATH += ../libXYZ LIBS += -L../libXYZ -lXYZ PRE_TARGETDEPS = ../libXYZ/libXYZ.a QT += core widgets
Note that the linked library must be added to PRE_TARGETDEPS, otherwise the app will not be relinked, if the library is rebuilt. Also note that the linked library will be found auto-magically even in case of an out-of-source build.
Now this enables us to link an executable against a static library, from which unused modules are dropped automatically. Mission accomplished!
← December 15th 2014 QtTorch App | ● | January 21th 2015 UI Simplification →