[bootlin/training-materials updates] master: labs/sysdev-thirdparty-qemu: updated lab for QEMU (affbfbf2)

Michael Opdenacker michael.opdenacker at bootlin.com
Wed Jan 18 17:11:16 CET 2023


Repository : https://github.com/bootlin/training-materials
On branch  : master
Link       : https://github.com/bootlin/training-materials/commit/affbfbf2538d12698955bb0883e4ad65b232c330

>---------------------------------------------------------------

commit affbfbf2538d12698955bb0883e4ad65b232c330
Author: Michael Opdenacker <michael.opdenacker at bootlin.com>
Date:   Wed Jan 18 17:11:16 2023 +0100

    labs/sysdev-thirdparty-qemu: updated lab for QEMU
    
    Signed-off-by: Michael Opdenacker <michael.opdenacker at bootlin.com>


>---------------------------------------------------------------

affbfbf2538d12698955bb0883e4ad65b232c330
 labs/sysdev-thirdparty-qemu/dependencies.dia       | 432 +++++++++++++
 .../sysdev-thirdparty-qemu.tex                     | 707 +++++++++++++++++++++
 2 files changed, 1139 insertions(+)

diff --git a/labs/sysdev-thirdparty-qemu/dependencies.dia b/labs/sysdev-thirdparty-qemu/dependencies.dia
new file mode 100644
index 00000000..10e06f3d
--- /dev/null
+++ b/labs/sysdev-thirdparty-qemu/dependencies.dia
@@ -0,0 +1,432 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<dia:diagram xmlns:dia="http://www.lysator.liu.se/~alla/dia/">
+  <dia:diagramdata>
+    <dia:attribute name="background">
+      <dia:color val="#ffffffff"/>
+    </dia:attribute>
+    <dia:attribute name="pagebreak">
+      <dia:color val="#000099ff"/>
+    </dia:attribute>
+    <dia:attribute name="paper">
+      <dia:composite type="paper">
+        <dia:attribute name="name">
+          <dia:string>#Letter#</dia:string>
+        </dia:attribute>
+        <dia:attribute name="tmargin">
+          <dia:real val="2.5399999618530273"/>
+        </dia:attribute>
+        <dia:attribute name="bmargin">
+          <dia:real val="2.5399999618530273"/>
+        </dia:attribute>
+        <dia:attribute name="lmargin">
+          <dia:real val="2.5399999618530273"/>
+        </dia:attribute>
+        <dia:attribute name="rmargin">
+          <dia:real val="2.5399999618530273"/>
+        </dia:attribute>
+        <dia:attribute name="is_portrait">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="scaling">
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="fitto">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+      </dia:composite>
+    </dia:attribute>
+    <dia:attribute name="grid">
+      <dia:composite type="grid">
+        <dia:attribute name="dynamic">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="width_x">
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="width_y">
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="visible_x">
+          <dia:int val="1"/>
+        </dia:attribute>
+        <dia:attribute name="visible_y">
+          <dia:int val="1"/>
+        </dia:attribute>
+        <dia:composite type="color"/>
+      </dia:composite>
+    </dia:attribute>
+    <dia:attribute name="color">
+      <dia:color val="#d8e5e5ff"/>
+    </dia:attribute>
+    <dia:attribute name="guides">
+      <dia:composite type="guide">
+        <dia:attribute name="position">
+          <dia:real val="0"/>
+        </dia:attribute>
+        <dia:attribute name="orientation">
+          <dia:int val="0"/>
+        </dia:attribute>
+      </dia:composite>
+    </dia:attribute>
+    <dia:attribute name="guide_color">
+      <dia:color val="#00ff00ff"/>
+    </dia:attribute>
+    <dia:attribute name="display">
+      <dia:composite type="display">
+        <dia:attribute name="antialiased">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="snap-to-grid">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="snap-to-guides">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="snap-to-object">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="show-grid">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="show-guides">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="show-connection-points">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+      </dia:composite>
+    </dia:attribute>
+  </dia:diagramdata>
+  <dia:layer name="Hintergrund" visible="true" connectable="false"/>
+  <dia:layer name="Arrière-plan" visible="true" connectable="true" active="true">
+    <dia:object type="Standard - Text" version="1" id="O0">
+      <dia:attribute name="obj_pos">
+        <dia:point val="6.50312,10.025"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="6.50312,9.285;6.50312,10.225"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>##</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="Latin Modern Sans" style="0" name="Courier"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.80000000000000004"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="6.50312,10.025"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000ff"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="0"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="valign">
+        <dia:enum val="3"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - Text" version="1" id="O1">
+      <dia:attribute name="obj_pos">
+        <dia:point val="12.4031,9.975"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="12.4031,9.235;12.4031,10.175"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>##</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="Latin Modern Sans" style="0" name="Courier"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.80000000000000004"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="12.4031,9.975"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000ff"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="0"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="valign">
+        <dia:enum val="3"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - Text" version="1" id="O2">
+      <dia:attribute name="obj_pos">
+        <dia:point val="6.50312,16.025"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="6.50312,15.285;6.50312,16.225"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>##</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="Latin Modern Sans" style="0" name="Courier"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="0.80000000000000004"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="6.50312,16.025"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000ff"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="0"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="valign">
+        <dia:enum val="3"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - Box" version="0" id="O3">
+      <dia:attribute name="obj_pos">
+        <dia:point val="5,15"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="4.95,14.95;19.05,19.1"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="5,15"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="14"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="4.0500000000000007"/>
+      </dia:attribute>
+      <dia:attribute name="border_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:attribute name="border_color">
+        <dia:color val="#5cacffff"/>
+      </dia:attribute>
+      <dia:attribute name="inner_color">
+        <dia:color val="#add8e6ff"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - Text" version="1" id="O4">
+      <dia:attribute name="obj_pos">
+        <dia:point val="12,17.025"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="10.3575,16.1975;13.6425,17.8525"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#alsa-lib#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="Latin Modern Sans" style="0" name="Courier"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="1.411111056804657"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="12,17.5025"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000ff"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="valign">
+        <dia:enum val="2"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O3" connection="8"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - Box" version="0" id="O5">
+      <dia:attribute name="obj_pos">
+        <dia:point val="5,8"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="4.95,7.95;19.05,12.1"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="5,8"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="14"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="4.0500000000000007"/>
+      </dia:attribute>
+      <dia:attribute name="border_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:attribute name="border_color">
+        <dia:color val="#5cacffff"/>
+      </dia:attribute>
+      <dia:attribute name="inner_color">
+        <dia:color val="#add8e6ff"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - Text" version="1" id="O6">
+      <dia:attribute name="obj_pos">
+        <dia:point val="12,10.025"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="9.9375,9.1975;14.0625,10.8525"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#alsa-utils#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="Latin Modern Sans" style="0" name="Courier"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="1.411111056804657"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="12,10.5025"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000ff"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="valign">
+        <dia:enum val="2"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O5" connection="8"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - ZigZagLine" version="1" id="O7">
+      <dia:attribute name="obj_pos">
+        <dia:point val="12,12.05"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="11.6382,12;12.3618,15.05"/>
+      </dia:attribute>
+      <dia:attribute name="orth_points">
+        <dia:point val="12,12.05"/>
+        <dia:point val="12,13.5"/>
+        <dia:point val="12,13.5"/>
+        <dia:point val="12,15"/>
+      </dia:attribute>
+      <dia:attribute name="orth_orient">
+        <dia:enum val="1"/>
+        <dia:enum val="0"/>
+        <dia:enum val="1"/>
+      </dia:attribute>
+      <dia:attribute name="autorouting">
+        <dia:boolean val="false"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow">
+        <dia:enum val="22"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_length">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_width">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O5" connection="6"/>
+        <dia:connection handle="1" to="O3" connection="1"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - Box" version="0" id="O8">
+      <dia:attribute name="obj_pos">
+        <dia:point val="23.1,15"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="23.05,14.95;37.15,19.1"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="23.1,15"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="14"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="4.0500000000000007"/>
+      </dia:attribute>
+      <dia:attribute name="border_width">
+        <dia:real val="0.10000000149011612"/>
+      </dia:attribute>
+      <dia:attribute name="border_color">
+        <dia:color val="#5cacffff"/>
+      </dia:attribute>
+      <dia:attribute name="inner_color">
+        <dia:color val="#add8e6ff"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - Text" version="1" id="O9">
+      <dia:attribute name="obj_pos">
+        <dia:point val="30.1,17.025"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="28.7513,16.1975;31.4488,17.8525"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#ipcalc#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="Latin Modern Sans" style="0" name="Courier"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="1.411111056804657"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="30.1,17.5025"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000ff"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="valign">
+        <dia:enum val="2"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O8" connection="8"/>
+      </dia:connections>
+    </dia:object>
+  </dia:layer>
+</dia:diagram>
diff --git a/labs/sysdev-thirdparty-qemu/sysdev-thirdparty-qemu.tex b/labs/sysdev-thirdparty-qemu/sysdev-thirdparty-qemu.tex
new file mode 100644
index 00000000..8da85015
--- /dev/null
+++ b/labs/sysdev-thirdparty-qemu/sysdev-thirdparty-qemu.tex
@@ -0,0 +1,707 @@
+\subchapter{Third party libraries and applications}{Objective: Learn
+  how to leverage existing libraries and applications: how to
+  configure, compile and install them}
+
+To illustrate how to use existing libraries and applications, we will
+extend the small root filesystem built in the {\em A tiny embedded
+system} lab to add the {\em ALSA} libraries and tools to run
+basic sound support tests. {\em ALSA} stands for {\em Advanced Linux
+Sound Architecture}, and is the Linux audio subsystem.
+
+We'll see that manually re-using existing libraries is quite tedious,
+so that more automated procedures are necessary to make it
+easier. However, learning how to perform these operations manually
+will significantly help you when you face issues with more
+automated tools.
+
+\section{Figuring out library dependencies}
+
+We're going to integrate the {\em alsa-utils}
+and {\em ipcalc} executables. In our case, the dependency chain
+for {\em alsa-utils} is quite simple, it only depends on the
+{\em alsa-lib} library. {\em ipcalc} is standalone
+and doesn't have any dependency.
+
+\includegraphics[width=\textwidth]{labs/sysdev-thirdparty-qemu/dependencies.pdf}
+
+Of course, all these libraries rely on the C library, which is not
+mentioned here, because it is already part of the root filesystem
+built in the {\em A tiny embedded system} lab. You might wonder how to
+figure out this dependency tree by yourself. Basically, there are
+several ways, that can be combined:
+
+\begin{itemize}
+\item Read the library documentation, which often mentions the
+  dependencies;
+\item Read the help message of the \code{configure script} (by running
+  \code{./configure --help}).
+\item By running the \code{configure} script, compiling and looking
+  at the errors.
+\end{itemize}
+
+To configure, compile and install all the components of our system,
+we're going to start from the bottom of the tree with {\em alsa-lib},
+then continue with {\em alsa-utils}.
+
+\section{Preparation}
+
+For our cross-compilation work, we will need two separate spaces:
+\begin{itemize}
+\item A \emph{staging} space in which we will directly install all the
+  packages: non-stripped versions of the libraries, headers,
+  documentation and other files needed for the compilation. This
+  \emph{staging} space can be quite big, but will not be used on our
+  target, only for compiling libraries or applications;
+\item A \emph{target} space, in which we will only copy the required
+  files from the \emph{staging} space: binaries and libraries, after
+  stripping, configuration files needed at runtime, etc. This target
+  space will take a lot less space than the \emph{staging} space, and
+  it will contain only the files that are really needed to make the
+  system work on the target.
+\end{itemize}
+
+To sum up, the {\em staging} space will contain everything that's
+needed for compilation, while the {\em target} space will contain only
+what's needed for execution.
+
+Create the \code{$HOME/__SESSION_NAME__-labs/thirdparty} directory,
+and inside, create two directories: \code{staging} and \code{target}.
+
+For the target, we need a basic system with BusyBox and
+initialization scripts. We will re-use the system built in the {\em A
+  tiny embedded system} lab, so copy this system in the target
+directory:
+
+\bashcmd{$ cp -a $HOME/__SESSION_NAME__-labs/tinysystem/nfsroot/* target/}
+
+Note that for this lab, a lot of typing will be required. To save time
+typing, we advise you to copy and paste commands from the electronic
+version of these instructions.
+
+\section{Testing}
+
+Make sure the \code{target/} directory is exported by your NFS server
+to your board by modifying \code{/etc/exports} and restarting your NFS
+server.
+
+Make your board boot from this new directory through NFS.
+
+\section{alsa-lib}
+
+{\em alsa-lib} is a library supposed to handle the interaction with
+the ALSA subsystem. It is available at \url{https://alsa-project.org}.
+Download version 1.2.7.1, and extract it
+in \code{$HOME/__SESSION_NAME__-labs/thirdparty/}.
+
+{\bf Tip}: if the website for any of the source packages that we
+need to download in the next sections is down, a great mirror
+that you can use is \url{http://sources.buildroot.net/}.
+
+Back to {\em alsa-lib} sources, look at the \code{configure} script
+and see that it has been generated by \code{autoconf} (the header
+contains a sentence like {\em Generated by GNU Autoconf 2.69}). Most of
+the time, \code{autoconf} comes with \code{automake}, that generates
+Makefiles from \code{Makefile.am} files. So {\em alsa-lib} uses a rather
+common build system. Let's try to configure and build it:
+
+\begin{bashinput}
+$ ./configure
+$ make
+\end{bashinput}
+
+If you look at the generated binaries, you'll see that they are
+x86 ones because we compiled the sources with gcc, the default compiler.
+This is obviously not what we want, so let's clean-up the generated objects
+and tell the \code{configure} script to use the ARM cross-compiler:
+
+\begin{bashinput}
+$ make clean
+$ CC=arm-linux-gcc ./configure
+\end{bashinput}
+
+Of course, the \code{arm-linux-gcc} cross-compiler must be in your
+\code{PATH} prior to running the configure script. The \code{CC} environment
+variable is the classical name for specifying the compiler to
+use.
+
+Quickly, you should get an error saying:
+
+%\footnotesize
+\begin{terminaloutput}
+checking whether we are cross compiling... configure: error: in `/home/mike/__SESSION_NAME__-labs/thirdparty/alsa-lib-1.2.7.1':
+configure: error: cannot run C compiled programs.
+If you meant to cross compile, use `--host'.
+See `config.log' for more details
+\end{terminaloutput}
+\normalsize
+
+If you look at the \code{config.log} file, you can see that the
+\code{configure} script compiles a binary with the cross-compiler
+and then tries to run it on the development workstation. This is a
+rather usual thing to do for a \code{configure} script, and that's
+why it tests so early that it's actually doable, and bails out if not.
+
+Obviously, it cannot work in our case, and the scripts exits. The job
+of the \code{configure} script is to test the configuration of the system. To
+do so, it tries to compile and run a few sample applications to test
+if this library is available, if this compiler option is supported,
+etc. But in our case, running the test examples is definitely not
+possible.
+
+We need to tell the \code{configure} script that we are cross-compiling, and
+this can be done using the \code{--build} and \code{--host} options,
+as described in the help of the \code{configure} script:
+
+\begin{verbatim}
+System types:
+  --build=BUILD	configure for building on BUILD [guessed]
+  --host=HOST	cross-compile to build programs to run on HOST [BUILD]
+\end{verbatim}
+
+The \code{--build} option allows to specify on which system the
+package is built, while the \code{--host} option allows to specify on
+which system the package will run. By default, the value of the
+\code{--build} option is guessed and the value of \code{--host} is the
+same as the value of the \code{--build} option. The value is guessed
+using the \code{./config.guess} script, which on your system should
+return \code{x86_64-pc-linux-gnu}. See
+\url{https://www.gnu.org/software/autoconf/manual/html_node/Specifying-Names.html}
+for more details on these options.
+
+So, let's override the value of the \code{--host} option:
+
+\bashcmd{$ CC=arm-linux-gcc ./configure --host=arm-linux}
+
+The \code{configure} script should end properly now, and create a
+Makefile.
+
+However, there is one subtle last issue to handle: because the C
+library used in our toolchain (uClibc-ng) does not support {\em symbol
+versioning}, we need to tell {\em alsa-lib} about this by passing
+\code{--without-versioned}. Without this option, {\em alsa-lib} will
+build fine, but it will not work properly at runtime\footnote{See
+\url{https://mailman.alsa-project.org/pipermail/alsa-devel/2009-February/014999.html}
+for all the details}. So you should configure {\em alsa-lib} as
+follows:
+
+\bashcmd{$ CC=arm-linux-gcc ./configure --host=arm-linux --without-versioned}
+
+Run the \code{make} command, which should run just fine.
+
+Look at the result of compiling in \code{src/.libs}: a set of object files
+and a set of \code{libasound.so*} files.
+
+The \code{libasound.so*} files are a dynamic version of the
+library. The shared library itself is \code{libasound.so.2.0.0}, it has
+been generated by the following command line:
+
+\begin{bashinput}
+$ arm-linux-gcc -shared conf.o confmisc.o input.o output.o async.o error.o dlmisc.o socket.o shmarea.o userfile.o names.o -lm -ldl -lpthread -lrt -Wl,-soname -Wl,libasound.so.2 -o libasound.so.2.0.0
+\end{bashinput}
+
+And creates the symbolic links \code{libasound.so} and
+\code{libasound.so.2}.
+
+\begin{bashinput}
+$ ln -s libasound.so.2.0.0 libasound.so.2
+$ ln -s libasound.so.2.0.0 libasound.so
+\end{bashinput}
+
+These symlinks are needed for two different reasons:
+
+\begin{itemize}
+\item \code{libasound.so} is used at compile time when you want to
+  compile an application that is dynamically linked against the
+  library. To do so, you pass the \code{-lLIBNAME} option to the
+  compiler, which will look for a file named
+  \code{lib<LIBNAME>.so}. In our case, the compilation option is
+  \code{-lasound} and the name of the library file is
+  \code{libasound.so}. So, the \code{libasound.so} symlink is needed
+  at compile time;
+\item \code{libasound.so.2} is needed because it is the {\em SONAME}
+  of the library. {\em SONAME} stands for {\em Shared Object Name}. It
+  is the name of the library as it will be stored in applications
+  linked against this library. It means that at runtime, the dynamic
+  loader will look for exactly this name when looking for the shared
+  library. So this symbolic link is needed at runtime.
+\end{itemize}
+
+To know what's the {\em SONAME} of a library, you can use:
+\bashcmd{$ arm-linux-readelf -d libasound.so.2.0.0}
+
+and look at the \code{(SONAME)} line. You'll also see that this
+library needs the C library, because of the \code{(NEEDED)} line on
+\code{libc.so.0}.
+
+The mechanism of \code{SONAME} allows to change the library without
+recompiling the applications linked with this library. Let's say that
+a security problem is found in the {\em alsa-lib} release that provides
+{\em libasound 2.0.0}, and fixed in the next {\em alsa-lib} release, which will
+now provide {\em libasound 2.0.1}.
+
+You can just recompile the library, install it on your target system,
+change the \code{libasound.so.2} link so that it points to
+\code{libasound.so.2.0.1} and restart your applications. And it will
+work, because your applications don't look specifically for
+\code{libasound.so.2.0.0} but for the {\em SONAME}
+\code{libasound.so.2}.
+
+However, it also means that as a library developer, if you break the
+ABI of the library, you must change the {\em SONAME}: change from
+\code{libasound.so.2} to \code{libasound.so.3}.
+
+Finally, the last step is to tell the \code{configure} script where the
+library is going to be installed. Most \code{configure} scripts consider that
+the installation prefix is \code{/usr/local/} (so that the library is
+installed in \code{/usr/local/lib}, the headers in
+\code{/usr/local/include}, etc.). But in our system, we simply want
+the libraries to be installed in the \code{/usr} prefix, so let's tell
+the \code{configure} script about this:
+
+\begin{bashinput}
+$ CC=arm-linux-gcc ./configure --host=arm-linux  --without-versioned --prefix=/usr
+$ make
+\end{bashinput}
+
+For this library, this option may not change anything to the resulting
+binaries, but for safety, it is always recommended to make sure that
+the prefix matches where your library will be running on the target
+system.
+
+Do not confuse the {\em prefix} (where the application or library will
+be running on the target system) from the location where the
+application or library will be installed on your host while building
+the root filesystem.
+
+For example, {\em libasound} will be installed in
+\code{$HOME/__SESSION_NAME__-labs/thirdparty/target/usr/lib/} because this is
+the directory where we are building the root filesystem, but once our
+target system will be running, it will see {\em libasound} in
+\code{/usr/lib}.
+
+The prefix corresponds to the path in the target system and {\bf
+  never} on the host. So, one should {\bf never} pass a prefix like
+\code{$HOME/__SESSION_NAME__-labs/thirdparty/target/usr}, otherwise at
+runtime, the application or library may look for files inside this
+directory on the target system, which obviously doesn't exist! By
+default, most build systems will install the application or library in
+the given prefix (\code{/usr} or \code{/usr/local}), but with most
+build systems (including {\em autotools}), the installation prefix can
+be overridden, and be different from the configuration prefix.
+
+We now only have the installation process left to do.
+
+First, let's make the installation in the {\em staging} space:
+\bashcmd{$ make DESTDIR=$HOME/__SESSION_NAME__-labs/thirdparty/staging install}
+
+Now look at what has been installed by {\em alsa-lib}:
+\begin{itemize}
+\item Some configuration files in \code{/usr/share/alsa}
+\item The headers in \code{/usr/include}
+\item The shared library and its libtool (\code{.la}) file in \code{/usr/lib}
+\item A pkgconfig file in \code{/usr/lib/pkgconfig}. We'll come back
+  to these later
+\end{itemize}
+
+Finally, let's install the library in the {\em target} space:
+
+\begin{enumerate}
+\item Create the \code{target/usr/lib} directory, it will contain the
+  stripped version of the library
+\item Copy the dynamic version of the library. Only
+  \code{libasound.so.2} and \code{libasound.so.2.0.0} are needed,
+  since \code{libasound.so.2} is the {\em SONAME} of the library and
+  \code{libasound.so.2.0.0} is the real binary:
+  \begin{itemize}
+  \item \bashcmd{$ cp -a staging/usr/lib/libasound.so.2* target/usr/lib}
+  \end{itemize}
+\item Measure the size of the \code{target/usr/lib/libasound.so.2.0.0}
+  library before stripping.
+\item Strip the library:
+  \begin{itemize}
+  \item \bashcmd{$ arm-linux-strip target/usr/lib/libasound.so.2.0.0}
+  \end{itemize}
+\item Measure the size of the \code{target/usr/lib/libasound.so.2.0.0}
+  library library again after stripping. How many unnecessary bytes
+  were saved?
+\end{enumerate}
+
+Then, we need to install the {\em alsa-lib} configuration files:
+
+\begin{bashinput}
+$ mkdir -p target/usr/share
+$ cp -a staging/usr/share/alsa target/usr/share
+\end{bashinput}
+
+Now, we need to adjust one small detail in one of the configuration
+files. Indeed, \code{/usr/share/alsa/alsa.conf} assumes a Unix group
+called \code{audio} exists, which is not the case on our very small
+system. So edit this file, and replace \code{defaults.pcm.ipc_gid
+audio} by \code{defaults.pcm.ipc_gid 0} instead.
+
+And we're done with {\em alsa-lib}!
+
+\section{Alsa-utils}
+
+Download {\em alsa-utils} from the ALSA offical webpage. We tested the lab
+with version 1.2.6.
+
+Once uncompressed, we quickly discover that the {\em alsa-utils} build
+system is based on the {\em autotools}, so we will work once again
+with a regular \code{configure} script.
+
+As we've seen previously, we will have to provide the prefix and host
+options and the CC variable:
+
+\bashcmd{$ CC=arm-linux-gcc ./configure --host=arm-linux --prefix=/usr}
+
+Now, we should quiclky get an error in the execution of the
+\code{configure} script:
+
+\begin{verbatim}
+checking for libasound headers version >= 1.2.5 (1.2.5)... not present.
+configure: error: Sufficiently new version of libasound not found.
+\end{verbatim}
+
+Again, we can check in \code{config.log} what the \code{configure}
+script is trying to do:
+
+%\footnotesize
+\begin{terminaloutput}
+configure:15855: checking for libasound headers version >= 1.2.5 (1.2.5)
+configure:15902: arm-linux-gcc -c -g -O2  conftest.c >&5
+conftest.c:24:10: fatal error: alsa/asoundlib.h: No such file or directory
+\end{terminaloutput}
+\normalsize
+
+Of course, since {\em alsa-utils} uses {\em alsa-lib}, it includes
+its header file! So we need to tell the C compiler where the headers
+can be found: there are not in the default directory
+\code{/usr/include/}, but in the \code{/usr/include} directory of our
+{\em staging} space. The help text of the \code{configure} script says:
+
+\begin{verbatim}
+  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+\end{verbatim}
+
+Let's use it:
+
+\begin{bashinput}
+$ CPPFLAGS=-I$HOME/__SESSION_NAME__-labs/thirdparty/staging/usr/include \%\linebreak
+CC=arm-linux-gcc %\% \linebreak
+./configure --host=arm-linux --prefix=/usr
+\end{bashinput}
+
+Now, it should stop a bit later, this time with the error:
+\begin{verbatim}
+checking for libasound headers version >= 1.0.27... found.
+checking for snd_ctl_open in -lasound... no
+configure: error: No linkable libasound was found.
+\end{verbatim}
+
+The \code{configure} script tries to compile an application against {\em
+  libasound} (as can be seen from the \code{-lasound} option): {\em
+  alsa-utils} uses {\em alsa-lib}, so the \code{configure} script
+wants to make sure this library is already installed. Unfortunately,
+the \code{ld} linker doesn't find it. So, let's tell the
+linker where to look for libraries using the \code{-L} option followed
+by the directory where our libraries are (in
+\code{staging/usr/lib}). This \code{-L} option can be passed to the
+linker by using the \code{LDFLAGS} at configure time, as told by the
+help text of the \code{configure} script:
+
+\begin{verbatim}
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+\end{verbatim}
+
+Let's use this \code{LDFLAGS} variable:
+
+\begin{bashinput}
+$ LDFLAGS=-L$HOME/__SESSION_NAME__-labs/thirdparty/staging/usr/lib \ 
+     CPPFLAGS=-I$HOME/__SESSION_NAME__-labs/thirdparty/staging/usr/include \ 
+     CC=arm-linux-gcc \
+     ./configure --host=arm-linux --prefix=/usr
+\end{bashinput}
+
+Once again, it should fail a bit further down the tests, this time
+complaining about a missing {\em curses helper header}. {\em curses}
+or {\em ncurses} is a graphical framework to design UIs in the
+terminal. This is only used by {\em alsamixer}, one of the tools
+provided by {\em alsa-utils}, that we are not going to use.
+Hence, we can just disable the build of {\em alsamixer}.
+
+Of course, if we wanted it, we would have had to build {\em ncurses} first,
+just like we built {\em alsa-lib}.
+
+\begin{bashinput}
+$ LDFLAGS=-L$HOME/__SESSION_NAME__-labs/thirdparty/staging/usr/lib \
+     CPPFLAGS=-I$HOME/__SESSION_NAME__-labs/thirdparty/staging/usr/include \
+     CC=arm-linux-gcc \
+     ./configure --host=arm-linux --prefix=/usr \
+     --disable-alsamixer
+\end{bashinput}
+
+Then, run the compilation with \code{make}. Hopefully, it works!
+
+Let's now begin the installation process.  Before really installing in
+the staging directory, let's install in a dummy directory, to see
+what's going to be installed (this dummy directory will not be used
+afterwards, it is only to verify what will be installed before
+polluting the staging space):
+
+\bashcmd{$ make DESTDIR=/tmp/alsa-utils/ install}
+
+The \code{DESTDIR} variable can be used with all Makefiles based on
+\code{automake}. It allows to override the installation directory:
+instead of being installed in the configuration prefix directory, the
+files will be installed in \code{DESTDIR/configuration-prefix}.
+
+Now, let's see what has been installed in \code{/tmp/alsa-utils/} (run
+\code{tree /tmp/alsa-utils}):
+
+\begin{verbatim}
+/tmp/alsa-utils/
+|-- lib
+|   |-- systemd
+|   |   `-- system
+|   |       |-- alsa-restore.service
+|   |       |-- alsa-state.service
+|   |       `-- sound.target.wants
+|   |           |-- alsa-restore.service -> ../alsa-restore.service
+|   |           `-- alsa-state.service -> ../alsa-state.service
+|   `-- udev
+|       `-- rules.d
+|           `-- 90-alsa-restore.rules
+|-- usr
+|   |-- bin
+|   |   |-- aconnect
+|   |   |-- alsabat
+|   |   |-- alsaloop
+|   |   |-- alsatplg
+|   |   |-- alsaucm
+|   |   |-- amidi
+|   |   |-- amixer
+|   |   |-- aplay
+|   |   |-- aplaymidi
+|   |   |-- arecord -> aplay
+|   |   |-- arecordmidi
+|   |   |-- aseqdump
+|   |   |-- aseqnet
+|   |   |-- axfer
+|   |   |-- iecset
+|   |   `-- speaker-test
+|   |-- sbin
+|   |   |-- alsabat-test.sh
+|   |   |-- alsaconf
+|   |   |-- alsactl
+|   |   `-- alsa-info.sh
+|   `-- share
+|       |-- alsa
+|       |   |-- init
+|       |   |   |-- 00main
+|       |   |   |-- ca0106
+|       |   |   |-- default
+|       |   |   |-- hda
+|       |   |   |-- help
+|       |   |   |-- info
+|       |   |   `-- test
+|       |   `-- speaker-test
+|       |       `-- sample_map.csv
+|       |-- man
+|       |   |-- fr
+|       |   |   `-- man8
+|       |   |       `-- alsaconf.8
+|       |   |-- man1
+|       |   |   |-- aconnect.1
+|       |   |   |-- alsabat.1
+|       |   |   |-- alsactl.1
+|       |   |   |-- alsa-info.sh.1
+|       |   |   |-- alsaloop.1
+|       |   |   |-- amidi.1
+|       |   |   |-- amixer.1
+|       |   |   |-- aplay.1
+|       |   |   |-- aplaymidi.1
+|       |   |   |-- arecord.1 -> aplay.1
+|       |   |   |-- arecordmidi.1
+|       |   |   |-- aseqdump.1
+|       |   |   |-- aseqnet.1
+|       |   |   |-- axfer.1
+|       |   |   |-- axfer-list.1
+|       |   |   |-- axfer-transfer.1
+|       |   |   |-- iecset.1
+|       |   |   `-- speaker-test.1
+|       |   |-- man7
+|       |   `-- man8
+|       |       `-- alsaconf.8
+|       `-- sounds
+|           `-- alsa
+|               |-- Front_Center.wav
+|               |-- Front_Left.wav
+|               |-- Front_Right.wav
+|               |-- Noise.wav
+|               |-- Rear_Center.wav
+|               |-- Rear_Left.wav
+|               |-- Rear_Right.wav
+|               |-- Side_Left.wav
+|               `-- Side_Right.wav
+`-- var
+    `-- lib
+        `-- alsa
+
+24 directories, 62 files
+\end{verbatim}
+
+So, we have:
+\begin{itemize}
+\item The {\em systemd} service definitions in \code{lib/systemd}
+\item The {\em udev} rules in \code{lib/udev}
+\item The {\em alsa-utils} binaries in \code{/usr/bin} and \code{/usr/sbin}
+\item Some sound samples in \code{/usr/share/sounds}
+\item The various translations in \code{/usr/share/locale}
+\item The manual pages in \code{/usr/share/man/}, explaining how to
+  use the various tools
+\item Some configuration samples in \code{/usr/share/alsa}.
+\end{itemize}
+
+Now, let's make the installation in the {\em staging} space:
+
+\bashcmd{$ make DESTDIR=$HOME/__SESSION_NAME__-labs/thirdparty/staging/ install}
+
+Then, let's manually install only the necessary files in the {\em target}
+space. We are only interested in \code{speaker-test}:
+
+\begin{bashinput}
+$ cd ..
+$ cp -a staging/usr/bin/speaker-test target/usr/bin/
+$ arm-linux-strip target/usr/bin/speaker-test
+\end{bashinput}
+
+And we're finally done with {\em alsa-utils}!
+
+Now test that all is working fine by running the \code{speaker-test} util on
+your board, with the headset provided by your instructor plugged
+in. You may need to add the missing libraries from the toolchain
+install directory.
+
+Now you can use:
+
+\begin{itemize}
+
+\item \code{speaker-test} with no arguments to generate {\em pink noise}
+
+\item \code{speaker-test -t sine} to generate a {\em sine wave},
+optionally with \code{-f <freq>} for a specific frequency
+
+\end{itemize}
+
+{\bf Known issue:} {\em according to our tests, you are likely to hear no
+sound on your Ubuntu 22.04 host when you run \code{speaker-test}. There should be no
+issue with what you built if \code{speaker-test} executes without an
+error, and if that's the case, you should consider this a success.
+Sound was working with the QEMU version on Ubuntu 20.04 and works
+again on Ubuntu 22.10. So, there is probably an issue somewhere in the QEMU
+integration in Ubuntu.}
+
+There you are: you built and ran your first program depending
+on a library different from the C library.
+
+\section{ipcalc}
+
+After practicing with autotools based packages, let's build {\em ipcalc}, which
+is using {\em Meson} as build system. We won't really need this utility
+in our system, but at least it has no dependencies and therefore
+offers an easy way to build our first {\em Meson} based package.
+
+So, first install the \code{meson} package.
+
+In the main lab directory, then let's check out the sources through
+\code{git}:
+
+\begin{bashinput}
+$ git clone https://gitlab.com/ipcalc/ipcalc.git
+$ cd ipcalc/
+$ git checkout 1.0.1
+\end{bashinput}
+
+To cross-compile with {\em Meson}, we need to create a {\em cross file}.
+Let's create the \code{../cross-file.txt} file with the below contents:
+
+\begin{verbatim}
+[binaries]
+c = 'arm-linux-gcc'
+
+[host_machine]
+system = 'linux'
+cpu_family = 'arm'
+cpu = 'cortex-a9'
+endian = 'little'
+\end{verbatim}
+
+We also need to create a special directory for building:
+
+\begin{bashinput}
+$ mkdir cross-build
+$ cd cross-build
+\end{bashinput}
+
+We can now have \code{meson} create the Ninja build files for us:
+
+\begin{bashinput}
+$ meson --cross-file ../../cross-file.txt --prefix /usr ..
+\end{bashinput}
+
+We are now ready to build {\em ipcalc}:
+
+\begin{bashinput}
+$ ninja
+\end{bashinput}
+
+And now install \code{ipcalc} to the build space:
+
+\begin{bashinput}
+$ DESTDIR=$HOME/__SESSION_NAME__-labs/thirdparty/staging ninja install
+\end{bashinput}
+
+Check that the \code{staging/usr/bin/ipcalc} file is indeed an ARM
+executable.
+
+The last thing to do is to copy it to the target space and strip it:
+
+\begin{bashinput}
+$ cd ../..
+$ cp staging/usr/bin/ipcalc target/usr/bin/
+$ arm-linux-strip target/usr/bin/ipcalc
+\end{bashinput}
+
+Note that we could have asked \code{ninja install} to strip the
+executable for us when installing it into the staging directory.
+To do, this, we would have added a \code{strip} entry in the cross file,
+and passed \code{--strip} to {\em Meson}. However, it's better to keep
+files unstripped in the staging space, in case we need to debug them.
+
+You can now test that \code{ipcalc} works on the target:
+
+\begin{bashinput}
+# ipcalc 192.168.0.100
+Address:	192.168.0.100
+Address space:	Private Use
+\end{bashinput}
+
+\section{Final touch}
+
+To finish this lab completely, and to be consistent with what we've done before,
+let's strip the C library and its loader too.
+
+First, check the initial size of the binaries:
+\bashcmd{$ ls -l target/lib}
+
+Then strip the binaries in \code{/lib}:
+\begin{bashinput}
+$ chmod +w target/lib/*.so.*
+$ arm-linux-strip target/lib/*.so.*
+\end{bashinput}
+
+And check the final size:
+\bashcmd{$ ls -l target/lib/}




More information about the training-materials-updates mailing list