/**
\page using_cmake Using CMake

\tableofcontents

CMake lets you express the structure of your software in a
portable way, that can then let you or others compile it
with lots of different tools.  So, for example,
you don't have to maintain Makefiles and Visual Studio projects,
you can have a common "source" that can generate either.

It is possible to use YARP without CMake.  But it isn't
as much fun.  So we give a basic tutorial on it here.

We gave instructions on installing CMake and getting started
with a basic project here:

  \li <a href="http://wiki.icub.org/wiki/CMake#Install_CMake">install_cmake</a>

Now we're going to go into CMake usage in a little more
depth.  But let's start simple, with a basic "hello world"
example.



\section using_cmake_basic Hello World Example

Let's use CMake to compile the usual "hello world" program.

Create a directory "cmake_tutorial" to work in.
Save the following as "main.cpp" within
that directory:

\code
    #include <stdio.h>
    int main() {
      printf("hello world.\n");
      return 0;
    }
\endcode

Then save the following as "CMakeLists.txt" within the
same directory:

\verbatim
    cmake_minimum_required(VERSION 3.12)
    project(MyProject)
    add_executable(hello)
    target_sources(hello PRIVATE main.cpp)
\endverbatim

The first line gives a CMake version number.  CMake is evolving with
time, so it is useful to warn a user if they have a version of CMake
too old to work on your project.  More importantly, by giving a
version number CMake can support your project indefinitely into
the future as its language changes.

The second line gives a name for our project.  If we compile
using Makefiles, this won't do anything, but if we compile with
something like Visual Studio, the project name will be used for
our workspace/solution.

The third line says we want to generate a program called "hello"
(with whatever extension is common on the operating system used,
".exe" for Windows, nothing for Linux) and that to generate it
we use the source file "main.cpp".

Now all we need to do is run CMake and we are ready to compile.
In what follows, we describe running CMake on the command line,
since it is easier to present.  For instructions on using the
CMake GUI on Windows, see:

  \li <a href="http://wiki.icub.org/wiki/CMake#Install_CMake">install_cmake</a>

From the command-line, you can see all the options cmake takes
by running it without any arguments.

we usually run cmake with a single
argument that specifies the directory the source code is
in.  We could also specify what kind of tool we will want to
build with (Unix Makefiles, CodeBlocks, Eclipse, KDevelop3, ...).
By default, CMake will produce Unix Makefiles on systems where
that make sense.
If we want to compile in the same directory as our
source code, that directory is ".", and here's what we
see when we run cmake:

\verbatim
$ cmake .
-- The C compiler identification is GNU
-- The CXX compiler identification is GNU
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler info
-- Detecting C compiler info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler info
-- Detecting CXX compiler info - done
-- Configuring done
-- Generating done
-- Build files have been written to: ...
\endverbatim

We can then compile; on Windows we would click on the workspace/solution
file that CMake has just created, or in Linux we do "make":

\verbatim
$ make
Scanning dependencies of target hello
[100%] Building CXX object CMakeFiles/hello.dir/main.cpp.o
Linking CXX executable hello
[100%] Built target hello
\endverbatim

Our program is now ready to run:

\verbatim
$ ./hello
hello world.
\endverbatim

Success!  But what was the point of all this?  The point is that
with our source code in C/C++, and our project description in
CMake, our code can be compiled easily by users of a vast range
of operating systems and tools.  This makes collaborating with
others a whole lot easier.


\section using_cmake_outofsource Out-of-source Builds

CMake generates a lot of helper files for compilation.
In our "hello world" example, here are the files
and directories we see after CMake has run:

\verbatim
$ ls
CMakeCache.txt  CMakeFiles  cmake_install.cmake  CMakeLists.txt
main.cpp        Makefile
\endverbatim

Normally, we don't actually want all this junk mixed in
with our source code. It is very common
with CMake to do "out-of-source" builds, where compiling happens
in a different directory to the source.  So let's try doing
this for our "hello world" example.  First, let's clean up:

\verbatim
$ rm -rf CMakeCache.txt CMakeFiles cmake_install.cmake Makefile
$ ls
CMakeLists.txt  main.cpp
\endverbatim

On Windows, just click on all files other than the two
we wrote (CMakeLists.txt and main.cpp) and delete them.
Now, let's build our program, but this time in a subdirectory
called "build" (or whatever you like):

\verbatim
$ mkdir build
$ cd build
$ cmake ..
$ make
$ ./hello
\endverbatim

(On Windows, make a subdirectory "build", then run CMake with the
source directory set to where "main.cpp" is and the binary directory
set to the "build" directory - then go through the compilation
procedure again).

Now if we want to clean up, we can just remove the build directory.

The benefit of this method is that we can compile our code in lots of
different ways side by side.  This can be useful if you share a file
system across several computers running different operating systems or
compilers, or if your program takes a set of different compile options
that you need to test.


\section using_cmake_library Building a library

We've seen an example of how to build a program.  Now let's
make a library as well.  The library will be called "namer"
and it will have a single function "getWorld" that returns
the name of the nearest planet.

We choose to put this library in a subdirectory called
"namer" - it doesn't really matter where we put it,
this is just an example.

Here is a header file "namer/world.h":
\code
    #include <string>
    std::string getWorld();
\endcode

And here is the corresponding implementation "namer/world.cpp":
\code
    #include <namer/world.h>
    std::string getWorld() { return "Earth"; }
\endcode

And we update our "main.cpp" program to make use of the "getWorld"
function:
\code
    #include <stdio.h>
    #include <namer/world.h>
    int main() {
      printf("Hello %s\n", getWorld().c_str());
      return 0;
    }
\endcode

Note the new include directive, for "world.h" (we could have said
"namer/world.h" instead, it is up to us how we want to organize things).

Now we update the "CMakeLists.txt" to tell it about the library
and to make sure the header file can be found by both the library
and by "main.cpp":
\verbatim
    cmake_minimum_required(VERSION 3.12)
    project(MyProject)
    add_library(namer)
    target_sources(namer PRIVATE namer/world.cpp
                                 namer/world.h)
    target_include_directories(namer PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
                                            $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)

    add_executable(hello)
    target_sources(hello PRIVATE main.cpp)
    target_link_libraries(hello PRIVATE namer)
\endverbatim

The `target_include_directories` command makes
sure `namer/world.h` can be found when included in source code.
We supply the path relative to `CMAKE_CURRENT_SOURCE_DIR`, which is a
variable pointing to our source directory.

The `add_library` command tells CMake that we want to make
a library called `namer` (`namer.lib` on Windows, `libnamer.a` or `libnamer.a`
on Linux, ...) using the supplied source code.  Note that
header files should be included in this list (although it
will work without them).  There are extra commands you can
use to organize code into different groups for presentation
in IDEs like visual studio, but we'll skip over that.

The `target_link_libraries` says that program `hello` needs
library `namer`.

And that's all!  CMake will figure out all the details needed for your
operating system and compiler to compile the library and link it
to your program.


\section using_cmake_split Building a library and program separately

We've just seen how to build a library and a program all together
in one project.  In real life, libraries and programs often are
written by different people working on different projects.
Let's simulate that by breaking up our library and program into
two separate projects.

Add the following CMake file for the library in "namer/CMakeLists.txt":
\verbatim
    cmake_minimum_required(VERSION 3.12)
    project(Namer)
    add_library(namer)
    target_sources(namer PRIVATE world.cpp world.h)
    target_include_directories(namer PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
                                            $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
\endverbatim
This is very similar to what we had before, except with our program
pruned out.

Make a subdirectory "hello" and move "main.cpp" into it.  Then add
"hello/CMakeLists.txt":

\verbatim
    cmake_minimum_required(VERSION 3.12)
    project(hello)
    find_package(Namer REQUIRED)
    add_executable(hello)
    target_sources(hello PRIVATE main.cpp)
    target_include_directories(hello PRIVATE "${Namer_INCLUDE_DIRS}")
    target_link_libraries(hello PRIVATE ${Namer_LIBRARIES})
\endverbatim

This is also similar to what we had before, except we now use the
"find_package" command.  This command is used to find external
material that your project needs.

If you try configuring and compiling the library, it will work
fine.  But the executable will not work yet.
You will get an error like this (depends on CMake version):

\verbatim
find_package could not find module FindNamer.cmake or a configuration
file for package Namer.  Adjust CMAKE_MODULE_PATH to find
FindNamer.cmake or set Namer_DIR to the directory containing a CMake
configuration file for Namer.  The file will have one of the following
names:
  NamerConfig.cmake
  namer-config.cmake
\endverbatim

Basically, we haven't specified how to find the package Namer yet.
CMake tried some ways it knows but none of them worked.

One way we can help CMake find the Namer package (which will be our
namer library) is by writing a helper script called FindNamer.cmake.
This is just another file written in the CMake language that
pokes around in all the places our library might be hiding.
Here is an example (put this in "hello/FindNamer.cmake"):

\verbatim
  find_path(Namer_INCLUDE_DIRS world.h /usr/include "$ENV{NAMER_ROOT}")

  find_library(Namer_LIBRARIES namer /usr/lib "$ENV{NAMER_ROOT}")

  set(Namer_FOUND TRUE)

  if (NOT Namer_INCLUDE_DIRS)
    set(Namer_FOUND FALSE)
  endif (NOT Namer_INCLUDE_DIRS)

  if (NOT Namer_LIBRARIES)
    set(Namer_FOUND FALSE)
  endif (NOT Namer_LIBRARIES)
\endverbatim

The important parts here are the "find_path" and "find_library"
commands, which look for the header file world.h and the namer
library.  I wrote them to check the Unix standard locations first,
then a directory specified by an environment variable.

Now modify "hello/CMakeLists.txt" so that it can find this script:
\verbatim
    cmake_minimum_required(VERSION 3.12)
    set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}")
    find_package(Namer REQUIRED)
    include_directories("${Namer_INCLUDE_DIRS}")
    add_executable(hello)
    target_sources(hello PRIVATE main.cpp)
    target_link_libraries(hello PRIVATE ${Namer_LIBRARIES})
\endverbatim

If we try again, configuration will still
 fail since the search path we gave for "find_path" and "find_library"
doesn't actually include the needed files.  We could copy them, or
have added a hard-coded directory to find_path and find_library
pointing to where the files are on our hard drive - but better, in the
CMake GUI on windows or by running "ccmake ." on Linux, we can just
fill in the directories there.

*/
