Files
cmake-examples/01-basic/C-static-library
2020-02-21 10:33:06 +08:00
..
2018-03-18 17:23:57 +00:00
2018-03-18 17:23:57 +00:00
2020-02-21 10:33:06 +08:00

= Static Library
:toc:
:toc-placement!:

toc::[]

# Introduction

Shows a hello world example which first creates and links a static library. This is a 
simplified example showing the library and binary in the same folder. Typically
these would be in sub-projects as described in section link:../../02-sub-projects[02-sub-projects]

The files in this tutorial are below:

```
$ tree
.
├── CMakeLists.txt
├── include
│   └── static
│       └── Hello.h
└── src
    ├── Hello.cpp
    └── main.cpp
```

  * link:CMakeLists.txt[] - Contains the CMake commands you wish to run
  * link:include/static/Hello.h[] - The header file to include
  * link:src/Hello.cpp[] - A source file to compile
  * link:src/main.cpp[] - The source file with main


# Concepts

## Adding a Static Library

The +add_library()+ function is used to create a library from some source files.
This is called as follows:

[source,cmake]
----
add_library(hello_library STATIC 
    src/Hello.cpp
)
----

This will be used to create a static library with the name libhello_library.a with
the sources in the +add_library+ call.

[NOTE]
====
As mentioned in the previous example, we pass the source files directly to the
+add_library+ call, as recommended for modern CMake.
====

## Populating Including Directories

In this example, we include directories in the library using the +target_include_directories()+ function with the scope set to +PUBLIC+.

[source,cmake]
----
target_include_directories(hello_library
    PUBLIC 
        ${PROJECT_SOURCE_DIR}/include
)
----

This will cause the included directory used in the following places:

* When compiling the library
* When compiling any additional target that links the library.

The meaning of scopes are:

* +PRIVATE+ - the directory is added to this target's include directories
* +INTERFACE+ - the directory is added to the include directories for any targets that link this library.
* +PUBLIC+ - As above, it is included in this library and also any targets that link this library.


[TIP]
====
For public headers it is often a good idea to have your include folder be "namespaced"
with sub-directories. 

The directory passed to +target_include_directories+ will be the root of your 
include directory tree and your C++ files should include the path from there to your header.

For this example you can see that we do it as follows:
[source,cpp]
----
#include "static/Hello.h"
----

Using this method means that there is less chance of header filename clashes when
you use multiple libraries in your project. 
====

## Linking a Library

When creating an executable that will use your library you must tell the compiler
about the library. This can be done using the +target_link_library()+ function.

[source,cmake]
----
add_executable(hello_binary 
    src/main.cpp
)

target_link_libraries( hello_binary
    PRIVATE  
        hello_library
)
----

This tells CMake to link the hello_library against the hello_binary executable
during link time. It will also propagate any include directories with +PUBLIC+ or +INTERFACE+ scope
 from the linked library target.

An example of this being called by the compiler is

```
/usr/bin/c++ CMakeFiles/hello_binary.dir/src/main.cpp.o -o hello_binary -rdynamic libhello_library.a
```


# Building the Example

[source,bash]
----
$ mkdir build

$ cd build

$ cmake ..
-- The C compiler identification is GNU 4.8.4
-- The CXX compiler identification is GNU 4.8.4
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/matrim/workspace/cmake-examples/01-basic/C-static-library/build

$ make
Scanning dependencies of target hello_library
[ 50%] Building CXX object CMakeFiles/hello_library.dir/src/Hello.cpp.o
Linking CXX static library libhello_library.a
[ 50%] Built target hello_library
Scanning dependencies of target hello_binary
[100%] Building CXX object CMakeFiles/hello_binary.dir/src/main.cpp.o
Linking CXX executable hello_binary
[100%] Built target hello_binary

$ ls
CMakeCache.txt  CMakeFiles  cmake_install.cmake  hello_binary  libhello_library.a  Makefile

$ ./hello_binary
Hello Static Library!
----