Thursday, July 6, 2017

Building Qt 4.8.7

Many already have probably heard about Qt by now so I will be terse in saying how cool it is and yet maybe too overwhelming, except for big and complex applications. What matters most in this post is how to using on a Solaris 11.3 (GA / Release) desktop. There are no pre-built binaries, except to some well known Solaris (honorable) sites which attempt to address the gaps in software availability to Solaris. The problem with those sites is that they somewhat lag behind or require to much stuff to setup their distribuition infrastructure. In face of that, I always prefer to build the software myself under a controlled environment I know better and is 100% free of security issues.

I will build it with GNU tools and compilers, targeting both 32 and 64 bits. The reason for not using Developer Studio at first is because software out there is more frequently distributed with the GNU build automation tools in mind so that the probability of a successful build is higher at first. Most of the GNU tools furnished with Solaris 11.3 (GA / Release) seems fairly updated, except for GNU build automation the themselves, which I recommend updating beforehand. Furthermore, the GCC packaged with Solaris is version 4.8.2, which means that it only fully supports C89 and C++03, so all bets are off for anything newer than that. Fortunately, this legacy version 4.8.7 of Qt don't require anything else than that. I know that C++03 is already history, but nevertheless it is there in case you need it. By the way, C is also history and yet it is still wildely prevalent in so many areas.

I learned the hard-way that the following Solaris 11.3 packages must be installed in order to maximize features and gracefully build Qt:

  • unicode
  • developer/icu
  • library/icu
  • image/graphviz
  • x11/library/xtrans

I thought that building Qt shouldn't be difficult (and in the end I confirm that) but that's not so unless you have all the necessary information at your fingertips, which, at least in case of Solaris, isn't that so. Despite the available information on its website the task wasn't easy at first and I had to pass to a series of trials and errors until I get there. As I believe noone should deserve that, as usual, I share my knowlege with the rest of the world on the belief that the contribution would make more people happier and think about doing the same more often.

In building Qt you'll have the ability to enable some features deemed as plugins but some of them must preexist installed on the Solaris system, either pre-packaged or manually built similarly to this task. Some of these features already package in Solaris will work with no issues, others won't because they are outdated or because of the way they were built and/or made available in the system. One example is SQLite version 3. The package available to Solaris is the 32-bits version 3.8.8.1 with certain features disabled or not available. For Qt that seems to be not much of a problem, but for Firefox it certainly is. Thus, as SQLite is so prevalent, this is a pre-requisite that's better to address right-away to avoid subsequent limitations or unexpected shortcomings, that is, update / install SQLite (by manually building both the 32 and 64 bits enabling all its features) right-away! The build work-flow is similar to the one on this post!

At the time of this writing, first, download the source-code tarball for version 4.8.7. You should look for the 230 Mb file named qt-everywhere-opensource-src-4.8.7.tar.gz (using git is not a good choice, as the Solaris version is outdated and in the end you'll only get more trouble, unless you have already taken care of manually updating it). Now follow my recommedation on GNU - Build preparation in order to prepare a sane environment for the task. Next to this previous step, fine-tune the generated setenv executable script in the root of the corresponding version subtree to consider an updated SQLite (as well as any other pre-requisite software) installation, for instance:

...
# Insert below, other PATH and PKG_CONFIG_PATH settings.
# Follow my PATH building suggestion.

 
PKG=/opt/sqlite-3.19.3/gnu$BITS
if [[ -d "$PKG" ]] ; 

then

  CFG=$PKG/bin
  ! [[ "$PATH" =~
"$PKG" ]] && \
    export PATH=$CFG:$PATH

  CFG=$PKG/lib/pkgconfig

  PCP=${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}
  ! [[ "$PCP" =~ "$PKG" ]] && \
    export PKG_CONFIG_PATH=$CFG$PCP

 
fi

...

In fact, the above will be part of a more complete environment setup (the setenv script) which I reference on some of the previous links. The relevant ajustments to the script are:

#
# Other PATH and PKG_CONFIG_PATH settings.
# Put in reverse order of dependency.
#

extend-env /opt/sqlite-3.19.3
extend-env /opt/tcl-8.5.19
extend-env /opt/automake-1.15
extend-env /opt/autoconf-2.69
extend-env /opt/m4-1.4.18
extend-env /opt/libtool-2.4.6

  
From the ZFS perspective, the "sane" environment is:

$ DS=...
$ zfs list -o name -t all -r $DS/software/Qt |sed 's,$DS,...,'
NAME
.../software/Qt
.../software/Qt/qt-4.8.7
.../software/Qt/qt-4.8.7@source
.../software/Qt/qt-4.8.7-gnu32
.../software/Qt/qt-4.8.7-gnu32@start
.../software/Qt/qt-4.8.7-gnu32@config
.../software/Qt/qt-4.8.7-gnu32@build
.../software/Qt/qt-4.8.7-gnu64
.../software/Qt/qt-4.8.7-gnu64@start
.../software/Qt/qt-4.8.7-gnu64@config
.../software/Qt/qt-4.8.7-gnu64@build


The qt-4.8.7 is the ZFS dataset to where the tarball was extracted.
Right after extraction the @source ZFS snapshot is taken.
The qt-4.8.7 dataset is made readonly, hum..., just in case.
The qt-4.8.7-gnu32 and qt-4.8.7-gnu64 are ZFS clones of @source.
Before the @start snapshots, certain "adjustments" are required.

First, the files qmake.conf and qplatformdefs.h .
They are at mkspecs/build-type/ subdirectories of the clones' mountpoints.
You may note in mkspecs/ a symbolic link called default, but ignore it.
As I'm building for GNU, build-type will be solaris-g++ and solaris-g++64.
The adjustments are:
In .../qt-4.8.7-gnu32/mkspecs/solaris-g++/qmake.conf:
(core2 is a particular optimization, not a requirement)

22: QMAKE_CFLAGS   = -march=core2 -std=gnu89
34: QMAKE_CXXFLAGS = -march=core2 -std=gnu++03

45: QMAKE_INCDIR   = /usr/include
46: QMAKE_LIBDIR   = /usr/lib


In .../qt-4.8.7-gnu32/mkspecs/solaris-g++/qplatformdefs.h:

124: // typedef unsigned int useconds_t;
125: // extern "C" int usleep(useconds_t);
126: // extern "C" int gethostname(char *, int);


In .../qt-4.8.7-gnu64/mkspecs/solaris-g++-64/qmake.conf:

QMAKE_CFLAGS   = -m64 -march=core2 -std=gnu89 ...keep rest...
QMAKE_CXXFLAGS = -m64 -march=core2 -std=gnu++03 ...keep rest...
QMAKE_INCDIR   = /usr/include

QMAKE_LIBDIR   = /usr/lib/64
Second, config.tests/x11/xinput/xinput.cpp.
The adjustment is:
 42 // #ifdef Q_OS_SOLARIS
 43 // #error "Not supported."
 44 // #else
 ...
 59 // #endif

Now take the @start snapshots and configure each build-type.

NOTE
The next configure commands' arguments are non-negotiable:
(otherwise the build will result unsuccessful)

-prefix (must be present, but its value can vary)
-no-webkit (must be present; Solaris lacks pthread_getattr_np())
-qt-libpng (must be present; Solaris headers and libs are misplaced)
-R (must be present; for each extra-system feature)

Be aware of the -qtnamespace setting. If you set it (but its value cannot be Qt) it will probably cause further impacts on any source-code, source-code generators and other libraries that may not count on such namespace value. Hence, it seems better to leave it off.

Furthermore, certain arguments that are not listed, must not be! For instance, -xvideo must not be listed due to a bug in configure. Similarly, declaratives and scripts arguments must not be listed. In general, for the build to succeed it's preferably not to rely on system options, that is, prefer the -qt-... alternatives. Finally, make sure you exclude portions of the machine instructions-set not supported by the particular hardware, such as: -no-3dnow, -no-sse4.1 and so on...

For GNU32:
$ ./configure -prefix /opt/qt-4.8.7/gnu32 -opensource -qt-sql-sqlite -xmlpatterns -no-webkit -multimedia -audio-backend -phonon -phonon-backend -svg -no-sse4.1 -no-sse4.2 -no-avx -no-neon -no-3dnow -qt-zlib -qt-libtiff -qt-libmng -qt-libpng -qt-libjpeg -openssl -make libs -make tools -make examples -make demos -make docs -R/opt/sqlite-3.19.3/gnu32/lib -nis -cups -iconv -pch -dbus -gtkstyle -no-nas-sound -opengl -sm -xshape -xsync -xinerama -xcursor -xfixes -xrandr -xrender -mitshm -fontconfig -xinput -xkb -glib -platform solaris-g++

For GNU64:
$ ./configure -prefix /opt/qt-4.8.7/gnu64 -opensource -qt-sql-sqlite -xmlpatterns -no-webkit -multimedia -audio-backend -phonon -phonon-backend -svg -no-sse4.1 -no-sse4.2 -no-avx -no-neon -no-3dnow -qt-zlib -qt-libtiff -qt-libmng -qt-libpng -qt-libjpeg -openssl -make libs -make tools -make examples -make demos -make docs -R/opt/sqlite-3.19.3/gnu64/lib -nis -cups -iconv -pch -dbus -gtkstyle -no-nas-sound -opengl -sm -xshape -xsync -xinerama -xcursor -xfixes -xrandr -xrender -mitshm -fontconfig -xinput -xkb -glib -platform solaris-g++-64

An initial licensing terms is presented:
(accept it by entering yes)

This is the  Open Source Edition.

You are licensed to use this software under the terms of
the Lesser GNU General Public License (LGPL) versions 2.1.
You are also licensed to use this software under the terms of
the GNU General Public License (GPL) versions 3.

Type '3' to view the GNU General Public License version 3.
Type 'L' to view the Lesser GNU General Public License version 2.1.
Type 'yes' to accept this license offer.
Type 'no' to decline this license offer.

Do you accept the terms of either license?


Each build target will output with a corresponding header:
 
This target is using ... (solaris-g++).
Build type:    solaris-g++
Architecture:  i386
 or
This target is using ... (solaris-g++-64).
Build type:    solaris-g++-64

Architecture:  x86_64

But both will continue their output as follows:
Debug .................. no
Qt 3 compatibility ..... yes
QtDBus module .......... yes (run-time)
QtConcurrent code ...... yes
QtGui module ........... yes
QtScript module ........ yes
QtScriptTools module ... yes
QtXmlPatterns module ... yes
Phonon module .......... yes
Multimedia module ...... yes
SVG module ............. yes
WebKit module .......... no
JavaScriptCore JIT ..... To be decided by JavaScriptCore
Declarative module ..... yes
Declarative debugging ...yes
Support for S60 ........ no
Symbian DEF files ...... no
STL support ............ yes
PCH support ............ yes
MMX/3DNOW/SSE/SSE2/SSE3. yes/no/yes/yes/yes
SSSE3/SSE4.1/SSE4.2..... yes/no/no
AVX..................... no
Graphics System ........ default
IPv6 support ........... yes
IPv6 ifname support .... yes
getaddrinfo support .... yes
getifaddrs support ..... yes
Accessibility .......... yes
NIS support ............ yes
CUPS support ........... yes
Iconv support .......... sun
Glib support ........... yes
GStreamer support ...... yes
PulseAudio support ..... yes
Large File support ..... yes
GIF support ............ plugin
TIFF support ........... plugin (qt)
JPEG support ........... plugin (qt)
PNG support ............ yes (qt)
MNG support ............ plugin (qt)
zlib support ........... yes
Session management ..... yes
OpenGL support ......... yes (Desktop OpenGL)
OpenVG support ......... no
NAS sound support ...... no
XShape support ......... yes
XVideo support ......... yes
XSync support .......... yes
Xinerama support ....... yes
Xcursor support ........ yes
Xfixes support ......... yes
Xrandr support ......... yes
Xrender support ........ yes
Xi support ............. yes
MIT-SHM support ........ yes
FontConfig support ..... yes
XKB Support ............ yes
immodule support ....... yes
GTK theme support ...... yes
SQLite support ......... qt (qt)
OpenSSL support ........ yes (run-time)
Alsa support ........... no
ICD support ............ no
libICU support ......... yes
Use system proxies ..... no

After a while (around 15 min on my slow machine) one sees:
(it's safe to completely ignore most of the configure instructions;
ZFS is an exceeding file-system dispensing reconfigure and confclean)

Qt is now configured for building. Just run 'gmake'.
Once everything is built, you must run 'gmake install'.
Qt will be installed into /opt/qt-4.8.7/...
To reconfigure, run 'gmake confclean' and 'configure'.

Now take the @config snapshots and build each build-type:
(this takes time on my slow machine; enough for a good nap, at least!)

$ gmake

Now take the @build snapshots and install each build-type:
(assuming that the right ZFS datasets were already mapped under /opt)

$ sudo gmake install

Now take the @release snapshots of each build-type installed.
The final results on the building machine are as follows:

$ DS=rpool/VARSHARE/qt-4.8.7
$ zfs list -o name -t all -r $DS
NAME
rpool/VARSHARE/qt-4.8.7
rpool/VARSHARE/qt-4.8.7/gnu32
rpool/VARSHARE/qt-4.8.7/gnu32@release
rpool/VARSHARE/qt-4.8.7/gnu64
rpool/VARSHARE/qt-4.8.7/gnu64@release


Now, if you plan to distribute the binaries, you have to package or create a tarball for each build-type. In general, if nothing more than the sub-structure under /opt is enough (which is the case), then the simplicity of a tarball is much more appealing.

Once the binaries are in place (integrated into /opt), it's just a matter of adjusting the PATH environment variable as usual:

$ export PATH=/opt/qt-4.8.7/gnu64/bin:$PATH

$ cd /opt/qt-4.8.7/gnu64/bin
$ ls -1
assistant
designer
lconvert
linguist
lrelease
lupdate
moc
pixeltool
qcollectiongenerator
qdbus
qdbuscpp2xml
qdbusviewer
qdbusxml2cpp
qdoc3
qhelpconverter
qhelpgenerator
qmake
qmlplugindump
qmlviewer
qt3to4
qtconfig
qtdemo
qttracereplay
rcc
uic
uic3
xmlpatterns
xmlpatternsvalidator

 

$ cd /opt/qt-4.8.7/gnu64/lib
$ ls -1 *.so.?.?.?
libphonon.so.4.4.0
libQt3Support.so.4.8.7
libQtCLucene.so.4.8.7
libQtCore.so.4.8.7
libQtDBus.so.4.8.7
libQtDeclarative.so.4.8.7
libQtDesigner.so.4.8.7
libQtDesignerComponents.so.4.8.7
libQtGui.so.4.8.7
libQtHelp.so.4.8.7
libQtMultimedia.so.4.8.7
libQtNetwork.so.4.8.7
libQtOpenGL.so.4.8.7
libQtScript.so.4.8.7
libQtScriptTools.so.4.8.7
libQtSql.so.4.8.7
libQtSvg.so.4.8.7
libQtTest.so.4.8.7
libQtXml.so.4.8.7
libQtXmlPatterns.so.4.8.7


You should make sure that the GUI Style is GTK+.

$ qtconfig


Et voilĂ !

$ qtdemo

   
Now it's possible to follow the baby steps of:
How to Develop Qt Applications in the Oracle Developer Studio IDE

NOTE
Fortunately, you can also use NetBeans 8.2 hassle-free.
Version 8.1 doesn't integrate well, perhaps requiring some tricks...