diff --git a/01-basic/B-hello-headers/README.adoc b/01-basic/B-hello-headers/README.adoc index e7176ca..2c8221a 100644 --- a/01-basic/B-hello-headers/README.adoc +++ b/01-basic/B-hello-headers/README.adoc @@ -86,7 +86,7 @@ file(GLOB SOURCES "src/*.cpp") ## Including Directories When you have different include folders, you can make your compiler aware of them using the -+target_include_directories()+ function. When compiling this target this will add these directories to the compiler with the -I flag e.g. `-I/directory/path` ++target_include_directories()+ link:https://cmake.org/cmake/help/v3.0/command/target_include_directories.html[function]. When compiling this target this will add these directories to the compiler with the -I flag e.g. `-I/directory/path` [source,cmake] ---- diff --git a/01-basic/C-static-library/README.adoc b/01-basic/C-static-library/README.adoc index 46cbcd5..fc02cb1 100644 --- a/01-basic/C-static-library/README.adoc +++ b/01-basic/C-static-library/README.adoc @@ -48,7 +48,16 @@ the sources from the +library_SOURCES+ variable. ## Populating Including Directories -In this example, we include directories in the library using the +target_include_directories()+ function with the scope set to +PUBLIC+. This will cause the included directory used in the following places: +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}/inc +) +---- + +This will cause the included directory used in the following places: * When compiling the library * When compiling any additional target that links the library. diff --git a/01-basic/D-shared-library/README.adoc b/01-basic/D-shared-library/README.adoc index 1d8c8f0..02685db 100644 --- a/01-basic/D-shared-library/README.adoc +++ b/01-basic/D-shared-library/README.adoc @@ -33,7 +33,6 @@ $ tree ## Adding a Shared Library - As with the previous example on static libraries, the +add_library()+ function is also used to create a shared library from some source files. This is called as follows: @@ -52,14 +51,14 @@ the sources from the +library_SOURCES+ variable. ## Alias Target -As the name suggests an alias target is an alternative name for a target that can be used instead of the real target name in read-only contexts. +As the name suggests an link:https://cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html#alias-targets[alias target] is an alternative name for a target that can be used instead of the real target name in read-only contexts. [source,cmake] ---- add_library(hello::library ALIAS hello_library) ---- -As show below, this allows you to reference the target using the alias name when linking it against other targets. +As shown below, this allows you to reference the target using the alias name when linking it against other targets. ## Linking a Shared Library diff --git a/01-basic/G-compile-flags/README.adoc b/01-basic/G-compile-flags/README.adoc index 26c1652..a1c808f 100644 --- a/01-basic/G-compile-flags/README.adoc +++ b/01-basic/G-compile-flags/README.adoc @@ -6,8 +6,10 @@ toc::[] # Introduction -CMake supports setting compile flags using the +CMAKE_C_FLAGS+ and +CMAKE_CXX_FLAGS+ -variables. Similarly linker flags can be set using the +CMAKE_LINKER_FLAGS+. +CMake supports setting compile flags in a number of different ways: + + * using +target_compile_definitions()+ function + * using the +CMAKE_C_FLAGS+ and +CMAKE_CXX_FLAGS+ variables. The files in this tutorial are below: @@ -23,22 +25,24 @@ $ tree # Concepts +# Set Per-Target C++ Flags -## Set C++ Flag - -Similar to the build type a global C++ compiler flag can be set using the following methods. - - - Using a gui tool such as ccmake / cmake-gui - -image::cmake-gui-set-cxx-flag.png[cmake-gui set cxx flag] - - - Passing into cmake +The recommended way to set C++ flags in modern CMake is to use per-target flags which can be populated to other targets +through the +target_compile_definitions()+ link:https://cmake.org/cmake/help/v3.0/command/target_compile_definitions.html?highlight=target_compile_definitions[function]. This will populate the link:https://cmake.org/cmake/help/v3.0/prop_tgt/INTERFACE_COMPILE_DEFINITIONS.html#prop_tgt:INTERFACE_COMPILE_DEFINITIONS[INTERFACE_COMPILE_DEFINITIONS] for the library and push the definition to the linked target depending on the scope. [source,cmake] ---- -cmake .. -DCMAKE_CXX_FLAGS="-DEX3" +target_compile_definitions(cmake_examples_compile_flags + PRIVATE EX3 +) ---- +This will cause the compiler to add the definition +-DEX3+ when compiling the target. + +In the target was a library, and the scope +PUBLIC+ or +INTERFACE+ has been choosen the definition would also be included in any targets that link this target. + +For compiler options you can also use the +target_compile_options()+ link:https://cmake.org/cmake/help/v3.0/command/target_compile_options.html[function]. + ## Set Default C++ Flags The default `CMAKE_CXX_FLAGS` is either empty or contains the appropriate flags @@ -52,6 +56,11 @@ top level CMakeLists.txt set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DEX2" CACHE STRING "Set C++ Compiler Flags" FORCE) ---- +Similarly to +CMAKE_CXX_FLAGS+ other options include: + + * Setting C compiler flags using +CMAKE_C_FLAGS+ + * Setting linker flags using +CMAKE_LINKER_FLAGS+. + [NOTE] ==== The values `CACHE STRING "Set C++ Compiler Flags" FORCE` from the above command @@ -60,19 +69,24 @@ are used to force this variable to be set in the CMakeCache.txt file. For more details, see https://cmake.org/cmake/help/v3.0/command/set.html[here] ==== -## Set Per-Target C++ Flags -Once set the +CMAKE_C_FLAGS+ and +CMAKE_CXX_FLAGS+ will set a compler flag / definiton globally for all targets in this directory or any included sub-directories. To set a compiler definitons for a specific target you can use the +target_compile_defintions()+ link:https://cmake.org/cmake/help/v3.0/command/target_compile_definitions.html[function]. This will cause the compiler to add the definition +-DEX3+ when compiling the target. +Once set the +CMAKE_C_FLAGS+ and +CMAKE_CXX_FLAGS+ will set a compler flag / definiton globally for all targets in this directory or any included sub-directories. This method is not recommended for general usage now and the +target_compile_definitions+ function is preferred. + +### Set CMake Flags + +Similar to the build type a global C++ compiler flag can be set using the following methods. + + - Using a gui tool such as ccmake / cmake-gui + +image::cmake-gui-set-cxx-flag.png[cmake-gui set cxx flag] + + - Passing into cmake [source,cmake] ---- -target_compile_defintions(cmake_examples_compile_flags - PRIVATE EX3 -) +cmake .. -DCMAKE_CXX_FLAGS="-DEX3" ---- -Depending on the scope this defintion may also be included in any targets that link this target. For compiler options you can also use the +target_compile_options()+ link:https://cmake.org/cmake/help/v3.0/command/target_compile_options.html[function]. - # Building the Example [source,bash] diff --git a/01-basic/H-third-party-library/CMakeLists.txt b/01-basic/H-third-party-library/CMakeLists.txt index 2bb5a89..f2dec7a 100644 --- a/01-basic/H-third-party-library/CMakeLists.txt +++ b/01-basic/H-third-party-library/CMakeLists.txt @@ -1,11 +1,11 @@ -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.4) # Set the project name project (third_party_include) # find a boost install with the libraries filesystem and system -find_package(Boost 1.46.1 REQUIRED COMPONENTS filesystem system) +find_package(Boost REQUIRED COMPONENTS filesystem system) # check if boost was found if(Boost_FOUND) @@ -18,13 +18,12 @@ endif() add_executable(third_party_include main.cpp) # Include the boost headers -target_include_directories( third_party_include - PRIVATE ${Boost_INCLUDE_DIRS} -) +#target_include_directories( third_party_include +# PRIVATE Boost::boost +#) # link against the boost libraries target_link_libraries( third_party_include PRIVATE - ${Boost_SYSTEM_LIBRARY} - ${Boost_FILESYSTEM_LIBRARY} + Boost::filesystem ) diff --git a/01-basic/H-third-party-library/README.adoc b/01-basic/H-third-party-library/README.adoc index 8eb8288..6b0ce4c 100644 --- a/01-basic/H-third-party-library/README.adoc +++ b/01-basic/H-third-party-library/README.adoc @@ -91,6 +91,27 @@ The variables exported in this example include: In some cases you can also check these variables by examining the cache using ccmake or cmake-gui. +## Alias variables + +Some modern CMake libraries export +ALIAS+ targets in their module files. For example, starting in later versions of CMake (v3.5+), +Boost uses this. +ALIAS+ targets make referencing found targets eaiser. This is similar to using your own alias targets for libraries. + +In the case of Boost, you could replace the following from this example: + + * `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` + +Using the new alias sytem, to replicate this example you only have to link the following: + +[source,cmake] +---- + target_link_libraries( third_party_include + PRIVATE + Boost::filesystem + ) +---- + # Building the Example [source,bash] diff --git a/README.adoc b/README.adoc index 410d84b..e190181 100644 --- a/README.adoc +++ b/README.adoc @@ -18,16 +18,20 @@ more complex use cases. These examples have been tested on Ubuntu 14.04 but should work under any Linux system that supports CMake. +This branch works with the CMake version 3.x onwards. For examples that use CMake version 2.x see the branch link:https://github.com/ttroy50/cmake-examples/tree/v2-style-includes[v2-style-includes]. + image:https://travis-ci.org/ttroy50/cmake-examples.svg?branch=master["Build Status", link="https://travis-ci.org/ttroy50/cmake-examples"] # Requirements The basic requirements for most examples are: -* CMake +* CMake v3.x * A c++ compiler (defaults to gcc) * make +## Installation on Ubuntu + The easiest way to install the above on Ubuntu is as follows [source,bash] @@ -59,11 +63,29 @@ Some specific examples may require other tools including: $ sudo apt-get install ninja-build +## Docker + +Docker container will all requirements and different versions of CMake are generated to help make testing the examples easier. These are available from the docker hub repository link:https://hub.docker.com/r/matrim/cmake-examples/[matrim/cmake-examples]. + +To build the full set of cmake-examples test cases you can run: + +[source,bash] +---- +docker run -it matrim/cmake-examples:3.4.3 +git clone https://github.com/ttroy50/cmake-examples.git +cd cmake-examples +./test.sh +---- + +For more details on build and running the docker containers link:here[dockerfiles]. + # Other Links There are many CMake tutorials and examples online. The list below includes links to some of these which I have found helpful in my CMake journey. + * http://www.kdab.com/~stephen/moderncmake.pdf[Modern CMake Slides] + * https://rix0r.nl/blog/2015/08/13/cmake-guide/[rix0r Modern CMake Blog] * https://cmake.org/cmake-tutorial/[Official CMake Tutorial] * https://cmake.org/Wiki/Main_Page[Official CMake Wiki] * https://cmake.org/Wiki/CMake_Useful_Variables[CMake Useful Variables] diff --git a/test.sh b/test.sh index a40a777..59b4f0a 100755 --- a/test.sh +++ b/test.sh @@ -9,7 +9,7 @@ cmake --help EXAMPLES_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" echo "running examples in $EXAMPLES_DIR" -cd $EXAMPLES_DIR +cd $EXAMPHLES_DIR dirs=( ./01-basic/A-hello-cmake \ ./01-basic/B-hello-headers \