Update to minimum CMake 3.5

And modernise some examples.
This commit is contained in:
Thom Troy
2018-03-18 17:23:57 +00:00
parent 54e75664c1
commit b81da6f68b
52 changed files with 303 additions and 212 deletions

View File

@@ -1,10 +1,10 @@
# Set the minimum version of CMake that can be used
# To find the cmake version run
# $ cmake --version
cmake_minimum_required(VERSION 3.0)
cmake_minimum_required(VERSION 3.5)
# Set the project name
project (hello_cmake)
# Add an executable
add_executable(hello_cmake main.cpp)
add_executable(hello_cmake main.cpp)

View File

@@ -35,7 +35,7 @@ of CMake that is supported.
[source,cmake]
----
cmake_minimum_required(VERSION 3.0)
cmake_minimum_required(VERSION 3.5)
----

View File

@@ -1,7 +1,7 @@
# Set the minimum version of CMake that can be used
# To find the cmake version run
# $ cmake --version
cmake_minimum_required(VERSION 3.0)
cmake_minimum_required(VERSION 3.5)
# Set the project name
project (hello_headers)
@@ -12,12 +12,12 @@ set(SOURCES
src/main.cpp
)
# Add an executable with the above sources
add_executable(hello_headers ${SOURCES})
# Set the direcoties that should be included in the build command for this target
# when running g++ these will be included as -I/directory/path/
target_include_directories(hello_headers
PRIVATE ${PROJECT_SOURCE_DIR}/include
PRIVATE
${PROJECT_SOURCE_DIR}/include
)

View File

@@ -83,6 +83,27 @@ file(GLOB SOURCES "src/*.cpp")
----
====
[NOTE]
====
An alternative to setting specific file names in the +SOURCES+ variable is
to use a GLOB command to find files using wildcard pattern matching.
[source,cmake]
----
file(GLOB SOURCES "src/*.cpp")
----
====
[TIP]
====
For modern CMake it is normally recommend to not use a variable for sources and to
directly declare the sources in the add_xxx function.
This is particularly important for glob commands which may not always show you the
correct results if you add a new source file.
====
## Including Directories
When you have different include folders, you can make your compiler aware of them using the
@@ -91,8 +112,9 @@ When you have different include folders, you can make your compiler aware of the
[source,cmake]
----
target_include_directories(target
PRIVATE ${PROJECT_SOURCE_DIR}/include
)
PRIVATE
${PROJECT_SOURCE_DIR}/include
)
----
The +PRIVATE+ identifier specifies the scope of the include. This is important for libraries and is exlpained in the next example. More details on the function is available link:https://cmake.org/cmake/help/v3.0/command/target_include_directories.html[here]

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.0)
cmake_minimum_required(VERSION 3.5)
project(hello_library)
@@ -6,16 +6,14 @@ project(hello_library)
# Create a library
############################################################
# Source files to be used in the library
set(library_SOURCES
#Generate the static library from the library sources
add_library(hello_library STATIC
src/Hello.cpp
)
#Generate the static library from the library sources
add_library(hello_library STATIC ${library_SOURCES})
target_include_directories(hello_library
PUBLIC ${PROJECT_SOURCE_DIR}/include
PUBLIC
${PROJECT_SOURCE_DIR}/include
)
@@ -23,15 +21,13 @@ target_include_directories(hello_library
# Create an executable
############################################################
# Source fles for the binary
set(binary_SOURCES
# Add an executable with the above sources
add_executable(hello_binary
src/main.cpp
)
# Add an executable with the above sources
add_executable(hello_binary ${binary_SOURCES})
# link the new hello_library target with the hello_binary target
target_link_libraries( hello_binary
PRIVATE hello_library
PRIVATE
hello_library
)

View File

@@ -6,7 +6,9 @@ toc::[]
# Introduction
Shows a hello world example which first creates and links a static library
Shows a hello world example which first creates and links a static library. This is a
simplified example showing the libray and binary in the same folder. Typically
these would be in sub-projects as described in section 02-sub-projects
The files in this tutorial are below:
@@ -15,14 +17,15 @@ $ tree
.
├── CMakeLists.txt
├── include
│   └── Hello.h
│   └── static
│   └── Hello.h
└── src
├── Hello.cpp
└── main.cpp
```
* link:CMakeLists.txt[] - Contains the CMake commands you wish to run
* link:include/Hello.h[] - The header file to include
* 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
@@ -36,15 +39,19 @@ This is called as follows:
[source,cmake]
----
set(library_SOURCES
add_library(hello_library STATIC
src/Hello.cpp
)
add_library(hello_library STATIC ${library_SOURCES})
----
This will be used to create a static library with the name libhello_library.a with
the sources from the +library_SOURCES+ variable.
the sources in the +add_library+ call.
[NOTE]
====
As mentioned in the prevoius example, we pass the source files directly to the
+add_library+ call, as recommended for modern CMake.
====
## Populating Including Directories
@@ -53,7 +60,8 @@ In this example, we include directories in the library using the +target_include
[source,cmake]
----
target_include_directories(hello_library
PUBLIC ${PROJECT_SOURCE_DIR}/include
PUBLIC
${PROJECT_SOURCE_DIR}/include
)
----
@@ -69,6 +77,24 @@ The meaning of scopes are:
* +PUBLIC+ - As above, it is included int his 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 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
@@ -76,10 +102,13 @@ about the library. This can be done using the +target_link_library()+ function.
[source,cmake]
----
add_executable(hello_binary ${binary_SOURCES})
add_executable(hello_binary
src/main.cpp
)
target_link_libraries( hello_binary
PRIVATE hello_library
PRIVATE
hello_library
)
----

View File

@@ -1,8 +1,8 @@
#include <iostream>
#include "Hello.h"
#include "static/Hello.h"
void Hello::print()
{
std::cout << "Hello Static Library!" << std::endl;
}
}

View File

@@ -1,8 +1,8 @@
#include "Hello.h"
#include "static/Hello.h"
int main(int argc, char *argv[])
{
Hello hi;
hi.print();
return 0;
}
}

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.0)
cmake_minimum_required(VERSION 3.5)
project(hello_library)
@@ -6,32 +6,28 @@ project(hello_library)
# Create a library
############################################################
# Source files to be used in the library
set(library_SOURCES
#Generate the shared library from the library sources
add_library(hello_library SHARED
src/Hello.cpp
)
#Generate the shared library from the library sources
add_library(hello_library SHARED ${library_SOURCES})
add_library(hello::library ALIAS hello_library)
target_include_directories(hello_library
PUBLIC ${PROJECT_SOURCE_DIR}/include
PUBLIC
${PROJECT_SOURCE_DIR}/include
)
############################################################
# Create an executable
############################################################
# Source fles for the binary
set(binary_SOURCES
# Add an executable with the above sources
add_executable(hello_binary
src/main.cpp
)
# Add an executable with the above sources
add_executable(hello_binary ${binary_SOURCES})
# link the new hello_library target with the hello_binary target
target_link_libraries( hello_binary
PRIVATE hello::library
PRIVATE
hello::library
)

View File

@@ -17,14 +17,15 @@ $ tree
.
├── CMakeLists.txt
├── include
│   └── Hello.h
│   └── shared
│   └── Hello.h
└── src
├── Hello.cpp
└── main.cpp
```
* link:CMakeLists.txt[] - Contains the CMake commands you wish to run
* link:include/Hello.h[] - The header file to include
* link:include/shared/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
@@ -39,15 +40,13 @@ This is called as follows:
[source,cmake]
----
set(library_SOURCES
add_library(hello_library SHARED
src/Hello.cpp
)
add_library(hello_library SHARED ${library_SOURCES})
----
This will be used to create a shared library with the name libhello_library.so with
the sources from the +library_SOURCES+ variable.
the sources passed to teh +add_library()+ function.
## Alias Target
@@ -67,10 +66,13 @@ executable use the the +target_link_library()+ function to point to your library
[source,cmake]
----
add_executable(hello_binary ${binary_SOURCES})
add_executable(hello_binary
src/main.cpp
)
target_link_libraries( hello_binary
hello::library
target_link_libraries(hello_binary
PRIVATE
hello::library
)
----

View File

@@ -1,8 +1,8 @@
#include <iostream>
#include "Hello.h"
#include "shared/Hello.h"
void Hello::print()
{
std::cout << "Hello Shared Library!" << std::endl;
}
}

View File

@@ -1,8 +1,8 @@
#include "Hello.h"
#include "shared/Hello.h"
int main(int argc, char *argv[])
{
Hello hi;
hi.print();
return 0;
}
}

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.0)
cmake_minimum_required(VERSION 3.5)
project(cmake_examples_install)
@@ -6,34 +6,29 @@ project(cmake_examples_install)
# Create a library
############################################################
# Source files to be used in the library
set(library_SOURCES
#Generate the shared library from the library sources
add_library(cmake_examples_inst SHARED
src/Hello.cpp
)
#Generate the shared library from the library sources
add_library(cmake_examples_inst SHARED ${library_SOURCES})
target_include_directories(cmake_examples_inst
PUBLIC ${PROJECT_SOURCE_DIR}/include
PUBLIC
${PROJECT_SOURCE_DIR}/include
)
############################################################
# Create an executable
############################################################
# Source fles for the binary
set(binary_SOURCES
# Add an executable with the above sources
add_executable(cmake_examples_inst_bin
src/main.cpp
)
# Add an executable with the above sources
add_executable(cmake_examples_inst_bin ${binary_SOURCES})
# link the new hello_library target with the hello_binary target
target_link_libraries( cmake_examples_inst_bin
PRIVATE cmake_examples_inst
PRIVATE
cmake_examples_inst
)
############################################################
@@ -49,6 +44,9 @@ install (TARGETS cmake_examples_inst_bin
install (TARGETS cmake_examples_inst
LIBRARY DESTINATION lib)
# Header files
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/
DESTINATION include)
# Config
install (FILES cmake-examples.conf

View File

@@ -17,7 +17,8 @@ $ tree
├── cmake-examples.conf
├── CMakeLists.txt
├── include
│   └── Hello.h
│   └── installing
│   └── Hello.h
├── README.adoc
└── src
├── Hello.cpp
@@ -26,7 +27,7 @@ $ tree
* link:CMakeLists.txt[] - Contains the CMake commands you wish to run
* link:cmake-examples.conf[] - An example configuration file
* link:include/Hello.h[] - The header file to include
* link:include/installing/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
@@ -72,6 +73,16 @@ install (TARGETS cmake_examples_inst
----
====
[source,cmake]
----
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/
DESTINATION include)
----
Install the header files for developing against the +cmake_examples_inst+ library
into the +${CMAKE_INSTALL_PREFIX}/include+ directory.
[source,cmake]
----
install (FILES cmake-examples.conf

View File

@@ -1,6 +1,6 @@
#include <iostream>
#include "Hello.h"
#include "installing/Hello.h"
void Hello::print()
{

View File

@@ -1,8 +1,8 @@
#include "Hello.h"
#include "installing/Hello.h"
int main(int argc, char *argv[])
{
Hello hi;
hi.print();
return 0;
}
}

View File

@@ -1,7 +1,7 @@
# Set the minimum version of CMake that can be used
# To find the cmake version run
# $ cmake --version
cmake_minimum_required(VERSION 3.0)
cmake_minimum_required(VERSION 3.5)
# Set a default build type if none was specified
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.0)
cmake_minimum_required(VERSION 3.5)
# Set a default C++ compile flag
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DEX2" CACHE STRING "Set C++ Compiler Flags" FORCE)

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.0)
cmake_minimum_required(VERSION 3.5)
# Set the project name
project (third_party_include)
@@ -17,14 +17,8 @@ endif()
# Add an executable
add_executable(third_party_include main.cpp)
# Include the boost headers
target_include_directories( third_party_include
PRIVATE ${Boost_INCLUDE_DIRS}
)
# link against the boost libraries
target_link_libraries( third_party_include
PRIVATE
${Boost_SYSTEM_LIBRARY}
${Boost_FILESYSTEM_LIBRARY}
Boost::filesystem
)

View File

@@ -85,33 +85,63 @@ variable, these are package specific and are typically documented at the top of
The variables exported in this example include:
* `Boost_INCLUDE_DIRS` - The path to the boost header files.
* `Boost_SYSTEM_LIBRARY` - The path to the boost system library.
* `Boost_FILESYSTEM_LIBRARY` - The path to the boost filesystem library.
In some cases you can also check these variables by examining the cache using
ccmake or cmake-gui.
## Alias variables
## Alias / Imported targets
Some modern CMake libraries export +ALIAS+ targets in their module files. For example, starting from v3.5+ of CMake, the
Most modern CMake libraries link:https://cmake.org/cmake/help/v3.6/prop_tgt/IMPORTED.html#prop_tgt:IMPORTED[export] +ALIAS+ targets in their module files.
The benefit of imported targets are that they can also populate include directories and linked libraries.
For example, starting from v3.5+ of CMake, the
Boost module supports this. Similar to using your own ALIAS target for libraires, an +ALIAS+ in a module can make referencing found targets eaiser.
In the case of Boost, you could replace the following from this example:
In the case of Boost, all targets are exported using the `Boost::` identifier and then the name
of the subsystem. For example you can use:
* `Boost_INCLUDE_DIRS` with `Boost::boost` for header only libraries
* `Boost_FILESYSTEM_LIBRARY` with `Boost::filesystem`
* `Boost_SYSTEM_LIBRARY` with `Boost::system`. If you include `Boost::filesystem` it automatically includes `Boost::system`
* `Boost::boost` for header only libraries
* `Boost::system` for the boost system library.
* `Boost::filesystem` for filesystem library.
Using the new alias sytem, to replicate this example you only have to link the following:
As with your own targets, these targets include their dependencies, so linking against
`Boost::filesystem` will automatically add `Boost::boost` and `Boost::system` dependencies.
To link against an imported target you can use the following:
[source,cmake]
----
target_link_libraries( third_party_include
PRIVATE
Boost::filesystem
Boost::filesystem
)
----
## Non-alias targets
While most modern libraries use imported targets, not all modules have been updated. In the
case where a library hasn't been updated you will often find the following variables available:
* xxx_INCLUDE_DIRS - A varialble pointing to the include directory for the library.
* xxx_LIBRARY - A variable pointing to the library path.
These can then be added to your +target_include_directories+ and +target_link_libraries+ as:
[source,cmake]
----
# Include the boost headers
target_include_directories( third_party_include
PRIVATE ${Boost_INCLUDE_DIRS}
)
# link against the boost libraries
target_link_libraries( third_party_include
PRIVATE
${Boost_SYSTEM_LIBRARY}
${Boost_FILESYSTEM_LIBRARY}
)
----
# Building the Example
[source,bash]

View File

@@ -1,7 +1,7 @@
# Set the minimum version of CMake that can be used
# To find the cmake version run
# $ cmake --version
cmake_minimum_required(VERSION 3.0)
cmake_minimum_required(VERSION 3.5)
# Set the project name
project (hello_cmake)

View File

@@ -1,7 +1,7 @@
# Set the minimum version of CMake that can be used
# To find the cmake version run
# $ cmake --version
cmake_minimum_required(VERSION 3.0)
cmake_minimum_required(VERSION 3.5)
# Set the project name
project (hello_cmake)

View File

@@ -20,5 +20,5 @@ add_executable(imported_targets main.cpp)
# link against the boost libraries
target_link_libraries( imported_targets
PRIVATE
Boost::filesystem
Boost::filesystem
)

View File

@@ -32,8 +32,7 @@ This example requires the following:
## Imported Target
Imported targets are read-only targets that are exported by FindXXX modules. The benefit of imported
targets are that they can also populate include directories and linked libraries.
Imported targets are read-only targets that are exported by FindXXX modules.
To include boost filesystem you can do the following:
@@ -41,7 +40,7 @@ To include boost filesystem you can do the following:
----
target_link_libraries( imported_targets
PRIVATE
Boost::filesystem
Boost::filesystem
)
----