\renewcommand{\FIGREP}{src/libraries/figures}

\section{Libraries}
\label{sec:libraries}
\intersec{izar}

\subsection{Compiling with libraries}
\label{sec:comp-with-libr}
\begin{frame}
  \frametitle{Libraries}
  \framesubtitle{}
  \begin{itemize}
    \item Libraries are a collection of pre-compiled pieces of code that can be
          reused in other programs
    \item One almost always uses libraries in our programs, \eg{}
    \cmd{iostream}, \cmd{vector} in C++, \cmd{stdio} in C
    \pause
    \item In general, a library consists of a header file, \cmd{cmath.h}, and a
    binary object, \cmd{libm.so}
    \item At compile time (pre-processing) you provide the headers
    \item At linking time you provide the object files
  \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Libraries}
  \framesubtitle{A simple example}

  \begin{itemize}
    \item Someone wrote an awesome math library called \cmd{mymath} providing
    the \cmd{squared} function
    \item Let's us it!
  \end{itemize}

  \cxxfile[title={libraryExample/main\_bad.c}]{examples/libraryExample/main_bad.c}
  \pause
  \begin{bashcode}
    $> gcc -Werror -Wall main_bad.c -o main
       main_bad.c: In function ‘main’:
       main_bad.c:4:39: error: implicit declaration of function ‘squared’
       4 |   printf("The square of 2.0 is %f\n", squared(2.0));
     \end{bashcode}%$
     \begin{itemize}
       \item Our program doesn't know about this \cmd{squared} function
     \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Libraries}
  \framesubtitle{A (better) simple example}

  \begin{itemize}
    \item Let's add the header file to declare the \cmd{squared} function
  \end{itemize}

  \cxxfile[title={libraryExample/main\_correct.c}]{examples/libraryExample/main_correct.c}
  \pause
  \begin{bashcode}
    $> gcc -Werror -Wall main_correct.c -o main
       main_correct.c:2:10: fatal error: mymath.h: No such file or directory
       2 | #include "mymath.h"
       |          ^~~~~~~~~~
       compilation terminated.
     \end{bashcode}%$
     \begin{itemize}
       \item We need to tell the compiler where to find this header file
     \end{itemize}
\end{frame}

\begin{frame}[fragile]
  \frametitle{Libraries}
  \framesubtitle{Include header files}
  \begin{itemize}
    \item When you have an \cmd{#include} or \cmd{use} (f90) in your code, the
    compiler must know where to look for them
    \item It has some default paths it will always look in, \eg{} system paths
    and current path, but you can supply your own with the \cmd{-I} option
  \end{itemize}

  \textbf{Example}:
  \begin{itemize}
    \item Let's assume the \cmd{mylibrary.h} header is located in
    \cmd{~/mycode/includes/mylibrary.h}
    \item The source code that uses it is located in
    \cmd{~/mycode/src/source.cpp}
    \item Here you have two options:
    \begin{enumerate}
      \item You put the library path in the source file, \ie{} \cmd{#include
        "../includes/mylibrary.h"}
      \item You simply use \cmd{#include "mylibrary.h"} and tell the compiler (pre-processor)
      where to look for it
      \begin{bashcode}
        gcc -I~/mycode/includes source.cpp
      \end{bashcode}
    \end{enumerate}
  \end{itemize}
\end{frame}

\begin{frame}[fragile,t]
  \frametitle{Libraries}
  \framesubtitle{A (almost there) simple example}

  \begin{itemize}
    \item Let's add the correct option to the compiler
  \end{itemize}

  \begin{bashcode}
    $> gcc -Imylibrary -Werror -Wall main_correct.c -o main
       /usr/bin/ld: /tmp/ccBYOiab.o: in function `main':
       main_correct.c:(.text+0x11): undefined reference to `squared'
       collect2: error: ld returned 1 exit status
     \end{bashcode}%$
     \begin{itemize}
       \item Now we are missing the actual definition of the function
       \item Two possibilities, the bad and the correct
     \end{itemize}
  \begin{bashcode}
    $> gcc -Imylibrary main_correct.c -o main mylibrary/libmymath.so  # the bad
     \end{bashcode}%$
     \begin{bashcode}
    $> gcc -Imylibrary main_correct.c -o main -Lmylibrary -lmymath    # the correct
     \end{bashcode}%$
   \end{frame}

\begin{frame}[fragile,t]
  \frametitle{Libraries}
  \framesubtitle{Linking options}

  \begin{itemize}
    \item To link a library to your executable you need to tell the linker
    \begin{itemize}
      \item Where is the library: \cmd{-L<PATH/TO/LIBRARY>}
      \item Which library you want to use: \cmd{-l<LIB_NAME>}
    \end{itemize}
    \item The linking options should be put at the end (after the files against
    which they will be linked)
    \begin{bashcode}
      $> gcc -Imylibrary main_correct.c -o main -Lmylibrary -lmymath    # OK
    \end{bashcode}%$
    \begin{bashcode}
      $> gcc -Lmylibrary -lmymath -Imylibrary main_correct.c -o main    # NOT OK
    \end{bashcode}%$
    \item In some cases, the order with which the library names appear matters.
    Read the linker documentation!
  \end{itemize}
  \vfill
  \pause
  \textbf{Summary:}
      \begin{bashcode}
      $> gcc -I<PATH/TO/HEADERS> code.c -L<PATH/TO/LIBRARY> -l<LIBRARY_NAME>
    \end{bashcode}%$
  \end{frame}

  \subsection{Static and shared libraries}
  \label{sec:stat-shar-libr}
\begin{frame}[fragile,b]
  \frametitle{Static and shared libraries}
  \framesubtitle{}

  \begin{minipage}{0.49\linewidth}
    \begin{itemize}
      \item Name is \cmd{libXYZ.a}
      \item Lib linked at compile time
      \item If the library changes, must recompile the program
      \item Executable is larger
    \end{itemize}
  \end{minipage}
  \hfill
  \begin{minipage}{0.49\linewidth}
    \begin{itemize}
      \item Name is \cmd{libXYZ.so}
      \item They are ``linked'' to the executable
      \item A table is created at compile time and libs are loaded at runtime
      \item Libs can be updated independently
      \item Smaller executable
    \end{itemize}
  \end{minipage}

  \addimage[width=10cm]{\FIGREP/library_static_shared}{3.0cm}{3.3cm}
  \end{frame}

\begin{frame}[t,fragile]
  \frametitle{Shared libraries}
  \framesubtitle{Loading the libraries}

  The following applies for shared libraries, but doesn't impact static
  libraries

  \begin{itemize}
    \item Shared libraries are not included in the executable, but only linked
    and loaded at runtime
    \item You can check them with \cmd{ldd}
    \begin{bashcode}
      $> ldd main
         linux-vdso.so.1 (0x00007ffc716df000)
         libmymath.so => not found
         libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f80e0657000)
         /lib64/ld-linux-x86-64.so.2 (0x00007f80e0846000)
    \end{bashcode}%$
    \item To tell the OS where is the library to load, we use the variable
    \cmd{LD_LIBRARY_PATH}
    \item For example, prepend your path
      \begin{bashcode}
        $> export LD_LIBRARY_PATH=/path/to/the/library:$LD_LIBRARY_PATH
      \end{bashcode}
  \end{itemize}
\end{frame}

\begin{frame}[exercise]
  \frametitle{Compilation}
  \framesubtitle{Exercise compilationWithLibrary}
  \begin{itemize}
    \item Go to the directory \cmd{compilationWithLibrary}
    \item Compile the code \cmd{main.F90} with shared library \cmd{libsaxpy.so}
    \item Execute the code
    \item Check the results according to the solution of exercise \cmd{simpleCompilation}
  \end{itemize}
\end{frame}

\begin{frame}[exercise]
  \frametitle{Compilation}
  \framesubtitle{BONUS: Exercise compilationWithMixLibrary}
  \begin{itemize}
    \item To mix static and shared libraries use: \cmd{-Wl,-Bstatic static_library -Wl,-Bdynamic shared_library}
    \item Go to the directory \cmd{compilationWithMixLibrary}
    \item Compile the code \cmd{main.c} with static library \cmd{libmax.a} and shared library \cmd{libsaxpy.so}
    \item Execute the code
    \item Check the results according to the solution of exercise \cmd{simpleCompilation}
  \end{itemize}
\end{frame}

\subsection{Important libraries in HPC}
\label{sec:import-libr-hpc}
\begin{frame}
  \frametitle{A few notable libraries}
  \framesubtitle{}

  Don't reinvent the wheel, use a library!
  \vfill
  \begin{itemize}
    \item Basic Linear Algebra Subprograms (BLAS)
    \begin{itemize}
      \item Provides routines to perform basic linear algebra operations (vector
      addition, dot product, etc.)
      \item OpenBLAS, Intel MKL, cuBLAS, rocBLAS, etc.
    \end{itemize}
    \item Linear Algebra Package (LAPACK)
    \begin{itemize}
      \item Provides routines for solving systems of linear equations
      \item OpenBLAS, Intel MKL, Netlib LAPACK and ScaLAPACK, etc.
    \end{itemize}
    \item Other solvers (direct and iterative)
    \begin{itemize}
      \item MUMPS, SuperLU, PETSc, PARDISO, etc.
    \end{itemize}
    \item Fourier transforms
    \begin{itemize}
      \item FFTW, cuFFT, intel MKL, etc.
    \end{itemize}
    \item And many others!
  \end{itemize}
\end{frame}

\begin{frame}[t,fragile]
  \frametitle{BONUS: Making your own library}
  \framesubtitle{}
  \begin{itemize}
    \item Creating static library \cmd{libmylib.a} from different object files \cmd{prog*.o}
    \begin{consoleoutput}
      $ gcc -c prog1.c prog2.c prog3.c ... progn.c
      $ ar -rv libmylib.a prog1.o prog2.o prog3.o ... progn.o
    \end{consoleoutput}
    \item Creating shared library \cmd{libmylib.so} from different object files \cmd{prog*.o}
    \begin{consoleoutput}
      $ gcc -fPIC -c prog1.c prog2.c prog3.c ... progn.c
      $ gcc -o libmylib.so -shared prog1.o prog2.o prog3.o ... progn.o
    \end{consoleoutput}
  \end{itemize}
\end{frame}

%%% Local Variables:
%%% mode: latex
%%% TeX-master: "../../SCM_slides"
%%% End:
