This full static mirror of the Run Up to Date Linux Everywhere Project is kept online by Free Software popularizer, researcher and trainer Marco Fioretti. To know how you can support this archive, and Marco's work in general, please click here

How to build a minimal Qt library

//(this article is courtesy of Luciano Montanaro, mikelima at the
server: virgilio.it)//

Here are some thoughts and experiences on how to configure a minimal qt library that still supports kde3.2 (or most of it). I’m basing my experiments on the qt-copy version of the qt libraries, which can be found in KDE CVS tree. Currently they are at version 3.3. I’m using a SuSE 9.0 distribuition, with gcc 3.3.1 and glibc 2.3.2. The Qt library can be optimized, on a first level, by using the right configuration options. There are a number of modules that can be excluded, if some advanced features are not needed. The ./configure --help command is useful to see what options we have available. Here are some interesting options
for the curious:

-version-script

Use a version script when linking the Qt library. Internal symbols will be marked as local. Requires a recent GNU binutils package. WARNING: Experimental, may be removed in future versions. This option is potentially very useful, but as it is marked experimental, I don’t currently recommend using it. In an embedded environment, however it can indeed save quite a bit of memory. It needs recent binutils to work, and it enables a version-script to hide library-private symbols, thus reducing memory occupation and link time.

-platform target

The operating system and compiler you are building on (linux-g++). This option can be used to change the operating system and compiler to build to. The build system for the qt library is a quite rigid, and to change compilation options you must modify some file under the mkspecs directory. The cleanest way is to duplicate for example the
“linux-g++” in a “tinylinux-g++” directory and to change the options there. Options worth testing for gcc (or g++) are -Os instead of -O2, to optimize for size, -funit-at-a-time and -fomit-frame-pointer.

-disable-<module>

Disable <module> where module is one of: styles tools kernel widgets dialogs iconview workspace network canvas table xml opengl sql. This option can be used to disable the inclusion of parts of the qt library. I think the opengl support could be disabled without problems, and probably we could do without the sql and table modules as well.

-no-ipv6

Do not compile IPv6 support. This could probably be used too… ipv6 is nowhere near ubiquitous. I doubt it would save much, anyway.

-dlopen-opengl

Qt uses dlopen(3) to resolve OpenGL functions (instead of linking with OpenGL libraries directly). This could be an alternative to completely disabling openGL support. OpenGL can still be used, but it is not linked at startup. However, given our target, I doubt that OpenGL would be supported in any useful way.

-release

Disable debugging and enable optimization. This is important to reduce code size, as you’ll see below.

Here are the result of some experiment I did.

Compiling with: stripped Library size:

KDE recommend options 7967300
With -release 7243592
As previous, plus -Os|6453064
As previous, plus -funit-at-a-time 6126760
As previous, plus -fomit-frame-pointer 6108808
As previous, option -disable-opengl 6065356

Other things to research

If only KDE applications are of interest, then most of the Qt dialogs are not needed. Disabling the file and print dialogs could cut off a sizable chunk of code. The QWorkspace widget should not be needed by KDE, however the Qt tools (the designer, at least) use it. I’m not sure if the memory gains are worth the effort, anyway. Qt 4 is said to be more modular, so some of the less used parts of Qt could will not be loaded anyway. Here is the script I used to compile the final version of the Qt library.

  ---- cut here --------
  #! /bin/bash
  export QTDIR=$PWD
  export YACC='byacc -d'
  make -f Makefile.cvs
  ./configure -system-zlib -qt-gif -system-libpng -system-libjpeg \
    -plugin-imgfmt-mng -thread -no-stl -no-exceptions -release -fast \
    -prefix ~/test-qtlibs-small -platform tinylinux-g++ \
    -disable-opengl -disable-workspace
  make sub-tools
  ---- cut here --------

…and here is the modified qmake.defs I used. To use it together with the above script, cp -a mkspecs/linux-g++ mkspecs/tinylinux-g++,then copy it to mkspecs/tinylinux-g++/qmake.defs

  ---- cut here --------
  #
  #
  #
  # qmake configuration for linux-g++
  #

  MAKEFILE_GENERATOR      = UNIX
  TEMPLATE                = app
  CONFIG                  += qt warn_on release incremental link_prl
  QMAKE_INCREMENTAL_STYLE = sublib

  QMAKE_CC                = gcc
  QMAKE_LEX               = flex
  QMAKE_LEXFLAGS          =
  QMAKE_YACC              = yacc
  QMAKE_YACCFLAGS         = -d
  QMAKE_YACCFLAGS_MANGLE  = -p $base -b $base
  QMAKE_YACC_HEADER       = $base.tab.h
  QMAKE_YACC_SOURCE       = $base.tab.c
  QMAKE_CFLAGS            = -pipe
  QMAKE_CFLAGS_DEPS       = -M
  QMAKE_CFLAGS_WARN_ON    = -Wall -W
  QMAKE_CFLAGS_WARN_OFF   = -w
  QMAKE_CFLAGS_RELEASE    = -Os -funit-at-a-time -fomit-frame-pointer
  QMAKE_CFLAGS_DEBUG      = -g
  QMAKE_CFLAGS_SHLIB      = -fPIC
  QMAKE_CFLAGS_YACC       = -Wno-unused -Wno-parentheses
  QMAKE_CFLAGS_THREAD     = -D_REENTRANT

  QMAKE_CXX               = g++
  QMAKE_CXXFLAGS          = $$QMAKE_CFLAGS
  QMAKE_CXXFLAGS_DEPS     = $$QMAKE_CFLAGS_DEPS
  QMAKE_CXXFLAGS_WARN_ON  = $$QMAKE_CFLAGS_WARN_ON
  QMAKE_CXXFLAGS_WARN_OFF = $$QMAKE_CFLAGS_WARN_OFF
  QMAKE_CXXFLAGS_RELEASE  = $$QMAKE_CFLAGS_RELEASE
  QMAKE_CXXFLAGS_DEBUG    = $$QMAKE_CFLAGS_DEBUG
  QMAKE_CXXFLAGS_SHLIB    = $$QMAKE_CFLAGS_SHLIB
  QMAKE_CXXFLAGS_YACC     = $$QMAKE_CFLAGS_YACC
  QMAKE_CXXFLAGS_THREAD   = $$QMAKE_CFLAGS_THREAD

  QMAKE_INCDIR            =
  QMAKE_LIBDIR            =
  QMAKE_INCDIR_X11        = /usr/X11R6/include
  QMAKE_LIBDIR_X11        = /usr/X11R6/lib
  QMAKE_INCDIR_QT         = $(QTDIR)/include
  QMAKE_LIBDIR_QT         = $(QTDIR)/lib
  QMAKE_INCDIR_OPENGL     = /usr/X11R6/include
  QMAKE_LIBDIR_OPENGL     = /usr/X11R6/lib

  QMAKE_LINK              = g++
  QMAKE_LINK_SHLIB        = g++
  QMAKE_LFLAGS            =
  QMAKE_LFLAGS_RELEASE    =
  QMAKE_LFLAGS_DEBUG      =
  QMAKE_LFLAGS_SHLIB      = -shared
  QMAKE_LFLAGS_PLUGIN     = $$QMAKE_LFLAGS_SHLIB
  QMAKE_LFLAGS_SONAME     = -Wl,-soname,
  QMAKE_LFLAGS_THREAD     =
  QMAKE_RPATH             = -Wl,-rpath,

  QMAKE_LIBS              =
  QMAKE_LIBS_DYNLOAD      = -ldl
  QMAKE_LIBS_X11          = -lXext -lX11 -lm
  QMAKE_LIBS_X11SM        = -lSM -lICE
  QMAKE_LIBS_NIS          = -lnsl
  QMAKE_LIBS_QT           = -lqt
  QMAKE_LIBS_QT_THREAD    = -lqt-mt
  QMAKE_LIBS_OPENGL       = -lGLU -lGL -lXmu
  QMAKE_LIBS_OPENGL_QT    = -lGL -lXmu
  QMAKE_LIBS_THREAD       = -lpthread

  QMAKE_MOC               = $(QTDIR)/bin/moc
  QMAKE_UIC               = $(QTDIR)/bin/uic

  QMAKE_AR                = ar cqs
  QMAKE_RANLIB            =

  QMAKE_TAR               = tar -cf
  QMAKE_GZIP              = gzip -9f

  QMAKE_COPY              = cp -f
  QMAKE_COPY_FILE         = $(COPY)
  QMAKE_COPY_DIR          = $(COPY) -r
  QMAKE_MOVE              = mv -f
  QMAKE_DEL_FILE          = rm -f
  QMAKE_DEL_DIR           = rmdir
  QMAKE_STRIP             = strip
  QMAKE_STRIPFLAGS_LIB    += --strip-unneeded
  QMAKE_CHK_DIR_EXISTS    = test -d
  QMAKE_MKDIR             = mkdir -p
  ----- cut here --------

Other tips

The size of Qt drops by quite a bit also bycompiling it with -Os {-fomit-frame-pointer -funit-at-a-time} and disabling the OpenGL classes. I have tested a bit more and if you don’t need xinerama support and antialiased text, you can add the options {-no-xinerama -no-xrender -no-xft}. With these, libqt-mt.so shrinks to 5925200 bytes. A copy of konqueror linked to this library with {LD_PRELOAD=~/kde/qt-copy-local/lib/libqt-mt.so.3.1.1} on an otherwise “normal” SuSE install, uses, according to top 21MB, versus 23 when using the standard library. Building against this library could improve still a bit, since libXft and libXrender are still linked to konqueror.

RULE = Run Up to Date Linux Everywhere
This entry was posted in Software. Bookmark the permalink.