cf3a88d6c12d526e13262f6723a763f69324c21d
[hsd_doku_tool.git] / doc / thesis / chapters / projektumsetzung.tex
1 \chapter{Projektumsetzung}
2 \label{cha:Projektumsetzung}
3
4 In diesem Kapitel wird die Implementierung des Prototyps anhand des im letzten Kapitel aufgezeigten Konzeptes erläutert.
5 Als Entwicklungssystem wird ein Rechner mit der Linuxdistribution \textit{Debian 9} (64Bit) verwendet. Im Folgendem wird Bezug
6 auf die Quellen \cite{mvc}, \cite{observer}, \cite{johnson1998anwendungen}, \cite{CrossDevWorkflow}, \cite{LinuxCert}, \cite{wine} und \cite{fltkMan} genommen.
7
8 \section{Implementierung des Prototypen}
9
10 Im kommenden Abschnitt wird die Umsetzung der einzelnen Komponenten des Prototyps beschrieben. Da der Prototyp im Wesentlichen
11 aus den drei Komponenten des MVC Konzepts besteht, ist der folgende Abschnitt in die Implementierung dieser gegliedert.
12
13 \subsection{Implementierung des Models}
14 Das Model hält alle Daten und ist für das Laden und Speichern der XML-Vorlagedateien verantwortlich. Außerdem beinhaltet es die Programmlogik
15 zum Generieren der Dokumentationen.
16 Das Parsen der XML-Dateien übernimmt hierbei die Programmbibliothek \textit{tinyxml2}. Per Vorlage geladene oder neu erstellte Kapitel und Autoren
17 werden innerhalb des Models als Listen spezieller Autor- und Kapitelobjekte abgelegt.
18
19 \subsubsection{Author Objekte}
20 \begin{figure}[H] \centering \includegraphics[width=0.50\textwidth]{author} \caption{Hier wird der Aufbau der Autor Klasse dargestellt.}\label{fig:Author} \end{figure}
21 Wie man in Abb.~\ref{fig:Author} sehen kann, sind Autor Objekte sehr einfach gehalten und dienen nur dazu die einzelnen Attribute mithilfe von Zugriffsfunktionen
22 zu speichern.
23
24 \subsubsection{Kapitel Objekte}
25 Da es drei verschiedene Kapitelarten gibt, kann hier nicht derselbe Ansatz wie bei den Kapiteln gewählt werden. Der Grundaufbau eines Kapitels wird durch eine Interfaceklasse definiert. Auf Basis dieses Interface ist es möglich, die drei Kapiteltypen als eigene Klassen umzusetzen.
26 Das Model besitzt die Möglichkeit, diese verschiedenen Kapiteltypen mithilfe einer sogenannten Simple-Factory-Klasse zu erzeugen.
27 \begin{figure}[H] \centering \includegraphics[width=\textwidth]{simple_factory} \caption{Dises UML Diagramm zeigt die Funktionsweise der \textit{ChapterFactory}-Klasse.}\label{fig:ChaptFact} \end{figure}
28 Abb.~\ref{fig:ChaptFact} zeigt die Funktionsweise dieser Simple-Factory-Klasse. Die \textit{createChapter} Funktionen erlauben das erzeugen von verschiedenen
29 Kapitel Objekten. Über diese Klasse kann auch eine Liste der verfügbaren Kapiteltypen angefordert werden.
30
31 \subsubsection{FSHelper Klasse}
32 Funktionen, die plattformabhängige Operationen, wie zum Beispiel Dateisystemzugriffe, zur Verfügung stellen, werden in einer eigenen FSHelper
33 Klasse gekapselt. Die Funktionen sind jeweils für Linux und für Windows implementiert, und über Präprozessor Makros wird der passende
34 Code in die Funktionen kompiliert.
35
36 \subsubsection{Benachrichtigung der View}
37 \begin{figure}[H] \centering \includegraphics[width=\textwidth]{observer} \caption{Dieses UML Diagramm zeigt das wie das Model mit der View über das Observer Entwurfsmuster interagiert.}\label{fig:Observer} \end{figure}
38 Finden Änderungen im Model statt, muss laut MVC Konzept zumindest die View darüber informiert werden. Dies kann mithilfe des Observer Entwurfsmuster umgesetzt werden. Wie man in Abb.~\ref{fig:Observer} erkennen kann, leitet die View von einer abstrakten Object Klasse ab und muss die Funktion
39 \textit{updatedBySubject} implementieren. Das Model leitet von Subject ab, somit kann die View über die Funktion \textit{notifyObservers} über Änderungen benachrichtigt werden.
40
41
42
43 \subsection{Implementierung der View}
44
45 \begin{figure}[H] \centering \includegraphics[width=\textwidth]{fluid} \caption{Hier wird das Design der Grafischen Oberfläche mit \textit{fluid} dargestellt.}\label{fig:fluid} \end{figure}
46
47 Die View Klasse repräsentiert den Teil des Prototyps, mit dem der Benutzer interagiert. Das Benutzerinterface wird mit der plattformunabhängigen
48 Programmbibliothek \textit{FLTK} erstellt. Dieses bietet die Möglichkeit mithilfe des Programms
49 \textit{FLUID} grafische Oberflächen zu designen.
50 \newline
51 \par
52 Hierbei werden die einzelnen Grafikobjekte, wie in Abb.~\ref{fig:fluid} dargestellt, mithilfe von Drag \& Drop zusammengefügt. Aus diesem
53 Design lässt sich dann eine Basisklasse generieren, von der die wirkliche View Klasse abgeleitet werden kann. In der abgeleiteten Klasse kann dann die
54 Funktionalität über Callbackfunktionen, die von den einzelnen Grafikobjekten ausgelöst werden, implementiert werden. Über diese Funktionen
55 werden Anfragen über den Controller an das Model weitergeleitet.
56
57 \subsection{Implementierung des Controllers}
58
59 Der Controller gibt Anfragen der View an das Model weiter und gibt diesem die Anweisung die View über Änderungen zu benachrichtigen.
60 Er bietet außerdem eine Zwischenschicht, um bei strukturellen Änderungen im Model die Aufrufe der View zu konvertieren.
61
62 \section{Kompilieren und Linken}
63
64 Um so wenig Abhängigkeiten, wie möglich zu erhalten wird auf Linux und auf Windows versucht so viel
65 wie möglich statisch in die Programme zu linken. Damit dies möglich ist, müssen aber zuerst die externen Programmbibliotheken
66 kompiliert werden.
67
68 \subsection{Installieren der Abhängigkeiten}
69
70 Folgende Abhängigkeiten müssen auf dem Entwicklungssystem mithilfe des Paketmanagers installiert werden:
71 \begin{lstlisting}[language=bash]
72 $ sudo dpkg --add-architecture i386
73 $ sudo apt update
74 $ sudo mv /usr/lib/llvm-3.9/lib/libclang-3.9.so.1 /usr/lib/llvm-3.9/lib/libclang-3.9.so.1.bak
75 $ sudo apt install -y build-essential libfltk1.3-dev libasound-dev:i386 xserver-xorg-dev:i386 gcc-multilib g++-multilib mingw-w64 binutils-mingw-w64 p7zip-full doxygen:i386
76 \end{lstlisting}
77 Dies installiert benötigte Programmbibliotheken und die passenden Compiler.
78 Um auf Linux für Windows Crosskompilieren zu können, benötigt man den \textit{mingw-w64} Compiler. Dieser ist weitgehend mit dem GNU Compiler für Linux kompatibel.
79 Als Crosskompilieren versteht man das Bauen eines Programmes für ein fremdes Zielsystem.
80 \newline
81 \par
82 Damit die \textit{FLTK} Unittest beim Crosskompilieren für Windows nicht fehlschlagen, muss auch \textit{Wine} installiert werden. Dies geschieht
83 wie folgt über den Paketmanager:
84 \begin{lstlisting}[language=bash]
85 $ sudo apt install -y wine wine32 wine64 libwine libwine:i386 fonts-wine wine-binfmt
86 $ sudo update-binfmts --import /usr/share/binfmts/wine
87 \end{lstlisting}
88 \textit{Wine} kann als eine Windowskompatibilitätsschicht verstanden werden, die es ermöglicht Windows Programme auf Linux Systemen auszuführen.
89
90 \subsection{Linux}
91
92 \subsubsection{FLTK}
93
94 Mithilfe des im FLTK-Quellcode bereitgestellten Konfigurationsskripts muss die Prozessorarchitektur angegeben werden. Außerdem müssen alle nicht
95 benötigten Abhängigkeiten deaktiviert werden.
96 Mit dem Befehl \textit{make} wird dann der Buildprozess gestartet und die statische Programmbibliothek erzeugt.
97 \begin{lstlisting}[language=bash]
98 $ ./configure "CFLAGS=-m32" "CXXFLAGS=-m32" "LDFLAGS=-m32" --enable-localjpeg --enable-localzlib --enable-localpng --enable-x11=no --disable-xcursor --disable-xinerama --disable-xft --disable-xdbe --disable-xrender --disable-xfixes --disable-threads
99 $ make
100 \end{lstlisting}
101
102 \subsubsection{tinyxml2}
103
104 \textit{tinyxml2} wird mit dem GNU C++ Compiler \textit{gcc} kompiliert und danach mit dem Befehl \textit{ar} in eine statische Bibliothek umgewandelt.
105
106 \begin{lstlisting}[language=bash]
107 $ g++ -m32 -c -o tinyxml2.o tinyxml2.cpp
108 $ ar rvs libtinyxml2.a tinyxml2.o
109 \end{lstlisting}
110
111 \subsubsection{Prototyp}
112 \label{ssc:LinkingLinux}
113
114 Der Prototyp muss unter Linux mit folgenden Linker Parametern gelinkt werden:
115
116 \begin{lstlisting}
117 -static-libstdc++
118 -static-libgcc
119 ./libfltk.a
120 ./libtinyxml2.a
121 -ldl
122 -lm
123 -lX11
124 \end{lstlisting}
125
126 Leider ist es nicht möglich alle Programmbibliotheken statisch in ein Programm zu linken, da Linux Systeme komplett auf dynamische
127 Bibliotheken aufgebaut sind. Es ist vor allem nicht möglich, die Standard C Bibliothek des Betriebssystems statisch zu linken.
128 \newline
129 \par
130 Eine Plattformunabhängigkeit zwischen verschiedenen Linux Derivaten herzustellen erweist sich somit als ziemlich schwierig,
131 da nicht alle Systeme eine einheitliche Version der Standard C Bibliothek besitzen. Dieses Problem kann umgangen werden, indem alle
132 benötigten dynamischen Bibliotheken in der Programmumgebung mitgeliefert werden. Das Programm muss dann über ein Bash-Startskript
133 mit dem gleichen dynamischen Lader, mit dem auch das Programm gelinkt wurde, gestartet werden.
134 \newline
135 \par
136 Es müssen dann aber auch alle externen Programme mit demselben Lader gestartet werden.
137 Diese Funktion übernimmt die \textit{FSHelper} Klasse. Externe Programme können aber nicht wie bei Windows mit
138 mit dem POSIX konformen \textit{system} Befehl gestartet werden, da dies eine Shell mit dem dynamischen Lader des Betriebssystems
139 erzeugen würde. Es müssen daher externe Programme mithilfe von \textit{fork} und textit{exec} aufgerufen werden.
140
141 \subsection{Windows}
142
143 \subsubsection{FLTK}
144
145 Unter Windows muss zum Kompilieren der statischen \textit{FLTK} Programmbibliothek neben der Prozessorarchitektur auch noch
146 der zu verwendende \textit{mingw-w64} Compiler angegeben werden.
147
148 \begin{lstlisting}[language=bash]
149 $ ./configure LDFLAGS="-static-libgcc -static-libstdc++" --enable-cygwin --enable-threads --enable-localjpeg --enable-localzlib --enable-localpng --enable-x11 --disable-xcursor --disable-xinerama --disable-xft --disable-xdbe --disable-xrender --disable-xfixes --disable-threads --host=i686-w64-mingw32
150 $ make
151 \end{lstlisting}
152
153 \subsubsection{tinyxml2}
154
155 Die statische \textit{tinyxml2} Programmbibliothek wird analog wie bei Linux erstellt, nur dass der \textit{mingw-w64} Compiler verwendet wird.
156
157 \begin{lstlisting}[language=bash]
158 $ i686-w64-mingw32-g++ -c -o tinyxml2.o tinyxml2.cpp
159 $ i686-w64-mingw32-ar rvs libtinyxml2.a tinyxml2.o
160 \end{lstlisting}
161
162 \subsubsection{Prototyp}
163
164 Unter Windows muss der Prototyp mit diesen Parametern gelinkt werden:
165
166 \begin{lstlisting}
167 -mwindows
168 -static-libgcc
169 -static-libstdc++
170 ./libfltk.a
171 ./libtinyxml2.a
172 -lole32
173 -luuid
174 -lcomctl32
175 \end{lstlisting}
176
177 Für Windows können alle Komponenten in ein einziges ausführbares Programm gelinkt werden.
178
179 \section{Programmumgebung}
180
181 Damit das Dokumentationswerkzeug die externen Programme \textit{Doxygen} und \textit{Texlive} verwenden kann, müssen diese in eine
182 Programmumgebung gepackt werden. Diese Programmumgebung gliedert sich in folgende Verzeichnisse:
183
184 \begin{itemize}
185 \item \textbf{bin:} Dieses Verzeichnis beinhaltet das kompilierte Dokumentationswerkzeug und die \textit{Doxygen} Anwendung.
186 \item \textbf{lib:} Im Unterordner \textit{lib} werden etwaige Abhängigkeiten abgelegt. Dies ist vor allem für die Linuxumgebung relevant um
187                     Programmbibliotheken, die man nicht statisch linken kann mit in die Programmumgebung zu packen.
188 \item \textbf{etc:} In diesem Verzeichnis ist die \latex Designvorlage gespeichert.
189 \item \textbf{texlive\_windows/texlive\_linux:} Die Namensgebung dieses Ordners ist abhängig vom Betriebssystem. Hier wird die vollständige
190 \textit{Texlive} Installation abgelegt.
191 \end{itemize}
192 Der Inhalt dieser Verzeichnisse muss an das jeweilige Betriebssystem angepasst werden, da sonst die Programme nicht ausführbar wären.
193
194 \subsection{Programmumgebung Linux}
195 \textit{Texlive} wird mithilfe der Offiziellen Installationsroutine \cite{texlive} als portable Version in das Unterverzeichnis \textit{texlive\_linux}
196 installiert.
197 \newline
198 \par
199 \textit{Doxygen} und dessen Abhängigkeiten werden direkt aus den Paketquellen \cite{DebRpm} des Entwicklungssystems bezogen und nach \textit{bin} kopiert.
200 Um die Abhängigkeiten leicht kopieren zu können, kann folgendes Bash-Skript verwendet werden:
201
202 \begin{lstlisting}[language=bash,caption={Bash-Skript zum kopieren von Abhängigkeiten}]
203 #!/bin/bash
204
205 function useage()
206 {
207     cat << EOU
208 Useage: bash $0 <path to the binary> <path to copy the dependencies>
209 EOU
210 exit 1
211 }
212
213 #Validate the inputs
214 [[ $# < 2 ]] && useage
215
216 #Check if the paths are vaild
217 [[ ! -e $1 ]] && echo "Not a vaild input $1" && exit 1
218 [[ -d $2 ]] || echo "No such directory $2 creating..."&& mkdir -p "$2"
219
220 #Get the library dependencies
221 echo "Collecting the shared library dependencies for $1..."
222 deps=$(ldd $1 | awk 'BEGIN{ORS=" "}$1\
223 ~/^\//{print $1}$3~/^\//{print $3}'\
224  | sed 's/,$/\n/')
225 echo "Copying the dependencies to $2"
226
227 #Copy the deps
228 for dep in $deps
229 do
230     echo "Copying $dep to $2"
231     cp "$dep" "$2"
232 done
233
234 echo "Done!"
235 \end{lstlisting}
236
237 Dieses Skript ermittelt mithilfe des Programmes \textit{ldd} alle von einer Anwendung benötigten Programmbibliotheken und kopiert diese in das
238 angegebene Verzeichnis.
239
240 \subsubsection{Start Script}
241
242 Um das Dokumentationswerkzeug innerhalb dieser Programmumgebung ausführen zu können, wird folgendes Skript benötigt, das die Umgebung initialisiert:
243
244 \begin{lstlisting}[language=bash,caption={Bash Start Skript}]
245 DIR=$(pwd)
246 export PATH=$DIR/texlive_linux/2018/bin/i386-linux:$DIR/bin:$PATH
247 export LD_LIBRARY_PATH=$DIR/lib
248 $LD_LIBRARY_PATH/ld-linux.so.2 --library-path $LD_LIBRARY_PATH $DIR/bin/doc_tool
249 \end{lstlisting}
250
251 Dieses Bash-Skript erweitert den Systempfad um die Pfade der Programmumgebung und ermöglicht somit das Starten des Dokumentationsprogramms
252 mit Zugriff auf \textit{Doxygen} und \textit{Texlive}. Wie man erkennen kann, wird wie unter \ref{ssc:LinkingLinux} erwähnt das
253 Dokumentationswerkzeug indirekt über den dynamischen Lader \textit{ld-linux.so.2} aufgerufen.
254
255 \subsection{Programmumgebung Windows}
256
257 \textit{Texlive} für Windows wird auch mit der Offiziellen Installationsroutine auf dem Linux System erstellt. Damit dies funktioniert, muss
258 die Windows Installationsroutine auf dem Linux System mithilfe von \textit{Wine} ausgeführt werden. Es wird hier auch
259 die portable Version von \textit{Texlive} in das Unterverzeichnis \textit{texlive\_windows} installiert.
260 \newline
261 \par
262 Um \textit{Doxygen} in dem Unterverzeichnis \textit{bin} bereitzustellen, werden direkt die von der Offiziellen Doxygen Website zur Verfügung
263 gestellten Windows Programmdateien verwendet \cite{doxywin}.
264
265 \subsubsection{Start Skript}
266
267 Wie unter Linux muss auch hier die Programmumgebung mithilfe eines Startskriptes initialisiert werden.
268
269 \begin{lstlisting}[caption={Batch Start Skript}]
270 @echo off
271 set path=%CD%\texlive_windows\2018\bin\win32;%CD%\bin;%PATH%
272 start doc_tool
273 \end{lstlisting}
274
275 Auch hier erweitert das Skript den Systempfad um die Pfade der Programmumgebung um Zugriff auf \textit{Doxygen} und \textit{Texlive} zu ermöglichen.
276
277
278 \section{Pakete Erstellen}
279
280 Um das Dokumentationsprogramm mit all seinen Abhängigkeiten leicht weitergeben und auf verschiedenen Systemen einrichten zu können,
281 ist es nötig, die gesamte Programmumgebung in ein komprimiertes Paket zusammenzufassen.
282
283 \subsection{Linux}
284 Unter Linux ist \textit{.tar.gz} eines der gängigsten Kompressionsformate. Daher kann davon ausgegangen werden, dass alle Linuxsysteme
285 ein Entpacken solcher Archive unterstützten. Um ein \textit{.tar.gz} Archiv in ein selbstextrahierendes Archiv umzuwandeln, kann man
286 in den Anfang der Archivdatei ein Shellskript einfügen. Dieses Shellskript muss dann das komprimierte Paket, das sich
287 in derselben Datei befindet, entpacken.
288 \newline
289 \par
290 Es wurde ein Hilfsprogramm geschrieben, das \textit{.tar.gz} Pakete mithilfe der gerade aufgezeigten Methode
291 in ein selbstextrahierendes Archiv umwandeln kann:
292 \begin{lstlisting}[language=bash]
293 #!/bin/sh
294 #Script that creates self extracting executable script from tar.gz file.
295 if [ $# -eq 0 ] || [ ! -f $1 ]; then
296         echo "This script creates self extractable executable"
297         echo Usage: $0 [/path/to/*.tar.gz]
298         exit;
299 fi
300 if [ $# -gt 0 ]; then
301         TAR_FILE=$1
302 fi
303 EXIT_COMMAND=exit
304 if [ $# -gt 1 ]; then
305         EXIT_COMMAND="exec $2"
306 fi
307 FILECOUNT=$(tar -tzf $TAR_FILE | wc -l)
308 SELF_EXTRACTABLE="$TAR_FILE.run"
309
310 cat > ${SELF_EXTRACTABLE} << EOL
311 #!/bin/bash
312 if [ -f '/usr/bin/xmessage' ] || [ -f '/usr/bin/gxmessage' ]; then
313     XMESSAGE=\$(which gxmessage) || XMESSAGE=xmessage
314     PWD=\$(pwd)
315     ans=\$(\$XMESSAGE -nearmouse -title 'Extract?' -buttons yes,no Extract to: [ \$PWD ] ? -print)
316 else
317     ans=yes
318 fi
319 if [ "\$ans" == "yes" ]; then
320     TOSKIP=\$(awk '/^#----- ARCHIVE STARTS HERE -----#/ {print NR + 1; exit 0; }' \$0)
321     COUNT=$FILECOUNT
322     echo "Installing Doc Tool: "&
323     PID=\$!
324     LINE="                                                  "
325     LINENUM=0
326
327     # Extract
328     tail -n+\$TOSKIP \$0  | tar -xzvp 2>&1 |
329     while read line; do
330         x=\$((x+1))
331
332         # calculate percentage
333         PERCENTAGE_NUM=\$(((x*100)/COUNT))
334         PERCENTAGE=\$(printf '%03d' \$PERCENTAGE_NUM)
335
336         # create gauge line
337         if [ "\$PERCENTAGE_NUM" -ge "\$LINENUM" ]; then
338                 LINE=\${LINE/ />}
339
340                 if [ "\$PERCENTAGE_NUM" -ge "100" ]; then
341                         LINE=\${LINE// />}
342                 fi
343         fi
344
345         # display gauge line
346         if [ -z \${XMESSAGE+x} ]; then
347               echo -en "[\$LINE] \$x / \$COUNT extracted (\$PERCENTAGE%)\r"
348                 if [ "\$PERCENTAGE_NUM" -ge "\$LINENUM" ]; then
349                       LINENUM=\$((PERCENTAGE_NUM+2))
350                 fi
351         else
352                if [ "\$PERCENTAGE_NUM" -ge "\$LINENUM" ]; then
353                       LINENUM=\$((PERCENTAGE_NUM+2))
354                       if ps -p \$PID > /dev/null
355                       then
356                             kill \$PID 2> /dev/null
357                        fi
358                       \$XMESSAGE -center -title 'Progress' "[\$LINE] \$x / \$COUNT extracted! (\$PERCENTAGE%)" &
359                        PID=\$!
360                fi
361         fi
362     done
363
364     # check if untar was successful
365     if [ "\${PIPESTATUS[1]}" != "0" ]; then
366         if [ -z \${XMESSAGE+x} ]; then
367             echo 'Failed to extract package!'
368         else
369              \$XMESSAGE -nearmouse -title 'Error!' 'Failed to extract package!'
370         fi
371         exit 1
372     fi
373
374     # display success message
375     if [ -z \${XMESSAGE+x} ]; then
376         echo ''
377         echo 'Finished extracting!'
378     else
379         \$XMESSAGE -nearmouse -title 'Success' 'Finished extracting!'
380     fi
381    exit
382 else
383    exit
384 fi
385 #----- ARCHIVE STARTS HERE -----#
386 EOL
387
388 cat $TAR_FILE >> $SELF_EXTRACTABLE
389 chmod a+x $SELF_EXTRACTABLE
390 \end{lstlisting}
391
392 \subsection{Windows}
393 Das gängigste Kompressionsformat unter Windows ist \textit{zip}. Daher wird auch dieses
394 als zum Packen der gesamten Programmumgebung gewählt. Mithilfe des Programmes \textit{7zip} kann unter Linux ein selbstextrahierendes Programm erzeugt werden, das eine Fortschrittsanzeige
395 besitzt und sich unter Windows ausführen lässt.
396
397 \section{Resultat}
398
399 \begin{figure}[H] \centering \includegraphics[width=0.8\textwidth]{doc_tool} \caption{Diese Abbildung zeigt die resultierende Benutzeroberfläche}\label{fig:doc_tool} \end{figure}
400 Abb.~\ref{fig:doc_tool} Zeigt die Benutzeroberfläche des in diesem Kapitel entwickelten Prototypen. Die Grafische Oberfläche besitzt alle in \ref{sc:aufbauGui}
401 gezeiten Merkmale. Es das Programm wurde unter Berücksichtigung der unter \autoref{cha:Anforderungen} definierten Anforderungen erstellt.