---
milena/ChangeLog | 4 +
milena/doc/tutorial.tex | 159 +++++++++++++++++++++++++++++++++++++++-------
2 files changed, 138 insertions(+), 25 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 9f1baa5..f7b58fa 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,7 @@
+2012-06-18 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ * doc/tutorial.tex: Add section about multifile compilation.
+
2012-05-23 Guillaume Lazzara <z(a)lrde.epita.fr>
Fix a bug in a tutorial example.
diff --git a/milena/doc/tutorial.tex b/milena/doc/tutorial.tex
index 8fee888..e67a9da 100644
--- a/milena/doc/tutorial.tex
+++ b/milena/doc/tutorial.tex
@@ -952,34 +952,141 @@ result.
\doxysubsection{tuto3howtocompile}{Include path}
-If Milena has been installed in a custom directory, e.g. not /usr/include or
-/usr/local/include, the path to the library headers must be passed to the
-compiler.
+If Milena has been installed in a custom directory, e.g. not
+/usr/include or /usr/local/include, the path to the library headers
+must be passed to the compiler.
With g++ and MinGW, the option is \B{-I$<$path$>$}.
\begin{verbatim}
$ g++ -Ipath/to/mln my_program.cc
\end{verbatim}
-For other compilers, please look at the documentation and search for ``include
-path''.
-
+For other compilers, please look at the documentation and search for
+``include path''.
\doxysubsection{tuto3liblink}{Library linking}
-As it is usually expected when using a library, no library linking is needed for
-the library itself.
-Milena is a ``header only'' library and is compiled ``on demand'' with
your
-program.
+As it is usually expected when using a library, no library linking is
+needed for the library itself. Milena is a ``header only'' library
+and is compiled ``on demand'' with your program.
+
+If you use specific input/output you may need to link your program
+with the right graphic library. For more information, please refer to
+section \doxyref{inputoutput} in the Quick Reference Guide.
+
+
+\doxysubsection{tuto3multifile}{Multifile Compilation}
+
+In some cases, one might want to use Olena in a more complex program
+compiled through several independant files.
+
+Let's consider the program is composed of two files both including
+Milena headers:
+\begin{itemize}
+ \item main.cc
+ \item task.cc
+\end{itemize}
+
+Content of main.cc
+\begin{verbatim}
+#include <mln/core/image/image2d.hh>
+
+// Main.cc
-If you use specific input/output you may need to link your program with the
-right graphic library. For more information, please refer to section
-\doxyref{inputoutput} in the Quick Reference Guide.
+// Forward declaration.
+void f();
+
+int main()
+{
+ mln::image2d<int> ima;
+}
+\end{verbatim}
+
+Content of task.cc
+\begin{verbatim}
+#include <mln/core/image/image2d.hh>
+
+// task.cc
+
+void f()
+{
+ mln::image2d<int> ima;
+}
+
+\end{verbatim}
+
+The following call to the compiler will fail:
+\begin{verbatim}
+$ g++ -Ipath/to/mln main.cc task.cc
+/tmp/ccRaVKO2.o:(.data+0x0): multiple definition of `mln::trace::quiet'
+/tmp/ccAArtQl.o:(.data+0x0): first defined here
+/tmp/ccRaVKO2.o:(.bss+0x0): multiple definition of `mln::trace::tab'
+/tmp/ccAArtQl.o:(.bss+0x0): first defined here
+/tmp/ccRaVKO2.o:(.bss+0x4): multiple definition of `mln::trace::full_trace'
+/tmp/ccAArtQl.o:(.bss+0x4): first defined here
+/tmp/ccRaVKO2.o:(.bss+0x8): multiple definition of `mln::trace::internal::max_tab'
+[...]
+collect2: ld returned 1 exit status
+\end{verbatim}
+
+This issue is due to the ``header only'' architecture of the library
+and to global variables. global variable symbols are compiled for each
+files and it leads to symbols conflicts.
+
+The solution is to force the compiler to compile these symbols only
+once. Olena provided a mechanism to do this.
+
+In one of the files including olena headers, at the very top of
+the file (before any includes), add the following line:
+\begin{verbatim}
+#undef MLN_WO_GLOBAL_VARS
+\end{verbatim}
+
+For instance, we would have in main.cc:
+\begin{verbatim}
+#undef MLN_WO_GLOBAL_VARS
+#include <mln/core/image/image2d.hh>
+
+// Main.cc
+
+// Forward declaration.
+void f();
+
+int main()
+{
+ f();
+}
+
+\end{verbatim}
+
+The compile the sources again with the define:
+\begin{verbatim}
+$ g++ -DMLN_WO_GLOBAL_VARS -Ipath/to/mln main.cc task.cc
+\end{verbatim}
+
+The previous duplicate symbols will then be compiled thanks to main.cc
+which force the effective declaration of the global symbols. Because
+of the default define at compile time, any .cc files including headers
+from the library will just declare but not define global symbols.
+
+For that reason, sometimes one may also encounter the following error
+after defining MLN\_WO\_GLOBAL\_VARS.
+\begin{verbatim}
+g++ -DMLN_WO_GLOBAL_VARS -I$PWD/milena/ main.cc task.cc
+/tmp/cc4Ys1xX.o: In function `f()':
+task.cc:(.text+0x6): undefined reference to `mln::border::thickness'
+collect2: ld returned 1 exit status
+\end{verbatim}
+In our case, it would be because task.cc includes and uses global
+symbols which are not included in main.cc. Therefore, they are defined
+but never compiled. Here, the file main.cc should include the
+corresponding headers.
\doxysubsection{tuto3compildndebug}{Disable Debug}
-By default, Olena enables a lot of internal pre and post conditions. Usually,
-this is a useful feature and it should be enabled. It can heavily slow down a
-program though and these tests can be disabled by compiling using -DNDEBUG:
+By default, Olena enables a lot of internal pre and post
+conditions. Usually, this is a useful feature and it should be
+enabled. It can heavily slow down a program though and these tests can
+be disabled by compiling using -DNDEBUG:
\begin{verbatim}
$ g++ -DNDEBUG -Ipath/to/mln my_program.cc
@@ -987,20 +1094,22 @@ $ g++ -DNDEBUG -Ipath/to/mln my_program.cc
\doxysubsection{tuto3compoptimflags}{Compiler optimization flags}
-In this section you will find remarks about the compiler optimization flags and
-their impact on the compilation and execution time.
+In this section you will find remarks about the compiler optimization
+flags and their impact on the compilation and execution time.
\doxysubsubsection{tuto3compoptimgcc}{GCC}
\begin{itemize}
- \item \B{-O0}, combined with -DNDEBUG, it leads to the fastest compilation
- time. The execution is somewhat slow though since dispatch functions and one
- line members are not inlined by the compiler.
- \item \B{-O1}, best compromise between compilation time and execution time.
- \item \B{-O2}, \B{-O3}, combined with -DNDEBUG, it leads to the best execution
- time. However these optimizations dramatically slow down the compilation and
- requires much more memory at compile time.
+ \item \B{-O0}, combined with -DNDEBUG, it leads to the fastest
+ compilation time. The execution is somewhat slow though since
+ dispatch functions and one line members are not inlined by the
+ compiler.
+ \item \B{-O1}, best compromise between compilation time and
+ execution time.
+ \item \B{-O2}, \B{-O3}, combined with -DNDEBUG, it leads to the best
+ execution time. However these optimizations dramatically slow down
+ the compilation and requires much more memory at compile time.
\end{itemize}
\doxysubsubsection{tuto3compoptimother}{Other compilers}
--
1.7.2.5