December 11, 2011

Revisiting LTIB and Qt on i.MX51 and i.MX53

In a previous post, we walked through the process of building Qt using the LTIB tool, but we were a bit cavalier about the steps involved.

Since that time, we’ve been shipping demo software based on LTIB and Qt with our Nitrogen53 and Nitrogenboards, and the lack of documentation shows.

In order to remedy that and allow our customers to replicate our results, this post will walk through the steps to build an Ubuntu-based VirtualBox image that contains LTIB and Qt. A set of future blog posts will detail the steps we’ve used to translate that build into our standard Qt demo package.

Since developer machines come and go, the VM image is a good way to control our build process and minimize the number of unknowns when deploying systems.

Step 1: Build the VM

We built the VirtualBox image by starting with the Ubuntu Minimal CD to try and keep things small. Our purpose is setting up a build machine, so we started with the “OpenSSH Server” profile, which allows us to fork the VM off into a second workspace and primarily access the device over SSH.

We chose the 32-bit PC (x86) distribution and used 10.04 “Lucid Lynx”.

We created a single user: boundary, password boundary.

Step 2: Configure with pre-requisites

In order to simplify things, we captured the full set of Ubuntu packages included on the build machine and placed on our web-site at
https://boundarydevices.com/ltib-installed-packages. You can copy these by piping them into apt-get install like so:

boundary@ubuntu:~$ wget https://boundarydevices.com/ltib-installed-packages
--2011-12-10 18:10:08--  https://boundarydevices.com/ltib-installed-packages
Resolving boundarydevices.com... 69.89.31.84
Connecting to boundarydevices.com|69.89.31.84|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 6093 (6.0K) 
Saving to: `ltib-installed-packages'

100%[======================================>] 6,093       --.-K/s   in 0.04s

2011-12-10 18:10:08 (144 KB/s) - `ltib-installed-packages' saved [6093/6093]

boundary@ubuntu:~$ cat ltib-installed-packages | xargs sudo apt-get install
[sudo] password for boundary:
Reading package lists... Done
Building dependency tree
Reading state information... Done
adduser is already the newest version.
apparmor is already the newest version.
...

Step 3: Install LTIB

In this distribution, we started with the package L2.6.35_11.09.01_ER_source_bundle.tar.gz from Freescale, and the L2.6.35_11.09.01_ER_source.tar.gz tar-ball within it.

After extracting, we installed LTIB in the normal way into /home/boundary/ltib:

boundary@ltib-qt-4:~$ sudo mkdir -p /opt/freescale/
boundary@ltib-qt-4:~$ sudo chown boundary.boundary /opt/freescale
boundary@ltib-qt-4:~$ cd L2.6.35_11.09.01_ER_source/
boundary@ltib-qt-4:~/L2.6.35_11.09.01_ER_source$ ls
EULA     ltib.tar.gz           pkgs                tftp.zip
install  package_manifest.txt  redboot_201003.zip
boundary@ltib-qt-4:~/L2.6.35_11.09.01_ER_source$ ./install

You are about to install the LTIB (GNU/Linux Target Image Builder)

Before installing LTIB, you must read and accept the EULA
(End User License Agreement) which will be presented next.

Do you want to continue ? Y|n
Y

              FREESCALE SEMICONDUCTOR SOFTWARE LICENSE AGREEMENT

IMPORTANT. Read the following Freescale Semiconductor Software License Agreement
("Agreement") completely. By selecting the "I Accept" button at the end of this
page, you indicate that you accept the terms of this Agreement. You may then
download the file.

...

I have read and accept the EULA (yes|no):
yes

The LTIB files are extracted from a tar file which includes the
prefix ltib.  After installation you will find LTIB in:
/home/boundary/L2.6.35_11.09.01_ER_source/ltib

Where do you want to install LTIB ? (/home/boundary/L2.6.35_11.09.01_ER_source)
/home/boundary
Making target directory /home/boundary/ltib
Installing LTIB to /home/boundary/ltib
ltib/
ltib/hash
ltib/doc/
...

Following the LTIB directions, we also added this line to /etc/sudoers:

boundary ALL= NOPASSWD: /usr/bin/rpm, /opt/freescale/ltib/usr/bin/rpm

And edited ltib as described here.

    no_sudo_check => 0,  # fc9 work-around

Step 4: Run LTIB

In the earlier posts on bringing up LTIB, I described running ltib -m config to configure the toolchain and packages for LTIB. In other words, I described an interactive process.

For production use, it’s better to simply save and restore the configuration file produced by the U/I.

The LTIB configuration used in this VirtualBox build is available here. In order to restore it, use the ltib --selecttype option as shown below.

boundary@ubuntu:~$ wget https://boundarydevices.com/ltib_11.03.config
--2011-12-10 19:44:54--  https://boundarydevices.com/ltib_11.03.config
Resolving boundarydevices.com... 69.89.31.84
Connecting to boundarydevices.com|69.89.31.84|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1675 (1.6K) 
Saving to: `ltib_11.03.config.3'

100%[======================================>] 1,675       --.-K/s   in 0s

2011-12-10 19:44:54 (173 GB/s) - `ltib_11.03.config.3' saved [1675/1675]

boundary@ubuntu:~$ cd ltib && ./ltib --selectype

LTIB configuration screenshot

After running selectype, LTIB will run for a while. Go get a cup of coffee and check in with it periodically.

Note that SSH is up and running now, and if you configure the VM with a bridged network adapter, you can run ifconfig eth0 in the virtual machine to find its’ IP address and use SSH to access it. Because you can run this in a console window on your development machine, Cut and Paste and screen scraping becomes much easier. Once things are configured and I know the IP address of the VM, I typically stash the VM console window on an unused Workspace on my Ubuntu development machine.

If everything proceeds as planned, your LTIB build will complete with this happy banner:

Started: Sun Dec 11 11:42:07 2011
Ended:   Sun Dec 11 11:42:21 2011
Elapsed: 14 seconds

Build Succeeded

The output of the build is placed in /home/boundary/ltib/rootfs. The size is fairly
large, but can be trimmed down later (a topic that deserves more than one blog post of its own).

boundary@ltib-qt:~$ du -hs /home/boundary/ltib/rootfs
663M	/home/boundary/ltib/rootfs

Step 5: Set up symlink for Qt

If you’ve looked at the other post on building Qt, or if you’ve taken a look at the qmake.conf file, you should notice that the include and linker specs are specified using the path /tftpboot/ltib. This is done primarily to avoid having references to home directories and to allow multiple instances of LTIB to be placed on a development machine.

To set this up, you should simply create a /tftpboot directory and a symlink from /tftpboot/ltib to the LTIB root filesystem. In this post, that directory is /home/boundary/ltib/rootfs.

boundary@ltib-qt:~$ sudo mkdir /tftpboot
boundary@ltib-qt:~$ sudo ln -sf /home/boundary/ltib/rootfs /tftpboot/ltib

Step 6: Configure Qt

Now that LTIB is installed, you can move on to configuring Qt.

To make things easy and reproducible, we placed some configuration files in this zip file. It consists of a configuration shell script (do_config_qt-4.7.1) and the LTIB configuration directory mkspecs/linux-mxc-g++/.

You can grab it and the Qt sources themselves using wget.

boundary@ltib-qt:~$ wget http://get.qt.nokia.com/qt/source/qt-everywhere-opensource-src-4.7.1.tar.gz
--2011-12-11 11:51:59--  http://get.qt.nokia.com/qt/source/qt-everywhere-opensource-src-4.7.1.tar.gz
Resolving get.qt.nokia.com... 208.111.145.207, 69.28.182.56
Connecting to get.qt.nokia.com|208.111.145.207|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 211768512 (202M) [application/octet-stream]
Saving to: `qt-everywhere-opensource-src-4.7.1.tar.gz'

 2% [                                       ] 4,239,502    416K/s  eta 8m 45s

boundary@ltib-qt:~$ tar zxvf qt-everywhere-opensource-src-4.7.1.tar.gz
qt-everywhere-opensource-src-4.7.1/
qt-everywhere-opensource-src-4.7.1/qmake/
qt-everywhere-opensource-src-4.7.1/qmake/property.cpp
qt-everywhere-opensource-src-4.7.1/qmake/meta.h
qt-everywhere-opensource-src-4.7.1/qmake/Makefile.win32-g++
...
boundary@ltib-qt:~$ cd qt-everywhere-opensource-src-4.7.1
boundary@ltib-qt:~/qt-everywhere-opensource-src-4.7.1$ wget https://boundarydevices.com/qt-config-mx5x.zip
--2011-12-11 12:01:46--  https://boundarydevices.com/qt-config-mx5x.zip
Resolving boundarydevices.com... 69.89.31.84
Connecting to boundarydevices.com|69.89.31.84|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3324 (3.2K) [application/zip]
Saving to: `qt-config-mx5x.zip'

100%[======================================>] 3,324       --.-K/s   in 0.001s

2011-12-11 12:01:47 (3.45 MB/s) - `qt-config-mx5x.zip' saved [3324/3324]

boundary@ltib-qt:~/qt-everywhere-opensource-src-4.7.1$ unzip qt-config-mx5x.zip
Archive:  qt-config-mx5x.zip
  inflating: do_config_qt-4.7.1
   creating: mkspecs/linux-mxc-g++/
  inflating: mkspecs/linux-mxc-g++/qplatformdefs.h
  inflating: mkspecs/linux-mxc-g++/qmake.conf

If you take a look at the file do_config_qt-4.7.1, you’ll see that it sets a few environment variables, so you’ll want to run it with the source or dot operator:

boundary@ltib-qt:~/qt-everywhere-opensource-src-4.7.1$ . ./do_config_qt-4.7.1
Determining system architecture... (Linux:2.6.32-36-generic:i686)
    32-bit Intel 80x86 (i386)
    'arm' is supported
    'i386' is supported
System architecture: 'arm'
Host architecture: 'i386'

You have asked to use pkg-config and are cross-compiling.
Please make sure you have a correctly set-up pkg-config
environment!

... lots of spew here...

Qt is now configured for building. Just run 'make'.
Once everything is built, you must run 'make install'.
Qt will be installed into /usr/local/Trolltech/Qt-4.7.1/

Step 7: Build and install Qt

Compared with the steps above, this step is really easy:

boundary@ltib-qt:~/qt-everywhere-opensource-src-4.7.1$ make
cd src/tools/bootstrap/ && make -f Makefile
make[1]: Entering directory `/home/boundary/qt-everywhere-opensource-src-4.7.1/src/tools/bootstrap'
...
make[3]: Leaving directory `/home/boundary/qt-everywhere-opensource-src-4.7.1/demos/spectrum/app'
make[2]: Leaving directory `/home/boundary/qt-everywhere-opensource-src-4.7.1/demos/spectrum'
make[1]: Leaving directory `/home/boundary/qt-everywhere-opensource-src-4.7.1/demos'
boundary@ltib-qt:~/qt-everywhere-opensource-src-4.7.1$ sudo make INSTALL_ROOT=~/ltib/rootfs/ install
[sudo] password for boundary:
cd src/tools/bootstrap/ && make -f Makefile install
make[1]: Entering directory `/home/boundary/qt-everywhere-opensource-src-4.7.1/src/tools/bootstrap'
...
cp -f -r /home/boundary/qt-everywhere-opensource-src-4.7.1/mkspecs/wincewm60standard-msvc2008 /home/boundary/ltib/rootfs//usr/local/Trolltech/Qt-4.7.1//mkspecs/
cp -f -r /home/boundary/qt-everywhere-opensource-src-4.7.1/mkspecs/wincewm65professional-msvc2005 /home/boundary/ltib/rootfs//usr/local/Trolltech/Qt-4.7.1//mkspecs/
cp -f -r /home/boundary/qt-everywhere-opensource-src-4.7.1/mkspecs/wincewm65professional-msvc2008 /home/boundary/ltib/rootfs//usr/local/Trolltech/Qt-4.7.1//mkspecs/
boundary@ltib-qt:~/qt-everywhere-opensource-src-4.7.1$

As shown above, this configuration installed Qt libraries into /home/boundary/ltib/rootfs, and
specifically, into the usr/local/ tree within it.

If you’ve followed this post to this point, congratulations! You now have a usable build of
Linux and Qt. I’ll follow up in future posts with how you can create a production-ready distribution
based on this core.

Wrapping it up

This VirtualBox image is available here.

You can use it in a number of different ways:

  1. You can install the nfs-kernel-server package, export it and boot a Nitrogen53 directly to the VM image.
  2. You can grab the /opt/freescale and /home/boundary/ltib directories and use them to compile and link your applications.
  3. You can use it as a quick-start to cross-compilation without going through all of these steps yourself if you’re evaluating a Nitrogen or Nitrogen53 board.
  4. You can use it for comparison with your own build.

The last of these is really the intent of this post.