Commit b402d99e authored by Markus Ferrell's avatar Markus Ferrell
Browse files

Help: Add workbook guide lessons 1 and 2

parent 0beb0ec2
# TODO: Set the minimum required version of cmake to be 3.10
# TODO: Create a project by setting the project name as Exercise1
# TODO: Add an executable to the project
# Hint: Be sure to specify the source code as exercise1.cxx
#include <iostream>
int main()
{
std::cout << "Hello World" << std::endl;
return 0;
}
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Exercise2 VERSION 1.0)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# TODO: Add MathFunctions as a subdirectory to this project
# Hint: You will need the add_subdirectory command
# TODO: Create a list of libraries using the list command
# Hint: The APPEND feature will come in handy here!
# TODO: Create a list of include directory paths
# Hint: ${PROJECT_SOURCE_DIR} is a path to the project source : AKA : This folder!
# add the executable
add_executable(Exercise2 exercise2.cxx)
# TODO: Link the added libraries to the current executable target
# Hint: You will need the target_link_libraries command
# TODO: Include the added MathFunctions include directory to the current executable target
# Hint: You will need the target_include_directories command
# TODO: Fill in this file to make this folder a library
# Hint: You will need the add_library command
#include <iostream>
// a hack addition calculation using simple operations
double myAdd(double x, double y)
{
return x + y;
}
// A simple program that computes additions
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <string>
#include "MathFunctions.h"
int main(int argc, char* argv[])
{
// ensure that user provides enough arguments
if (argc < 3) {
std::cout << "Usage: " << argv[0] << " number number" << std::endl;
return 1;
}
// convert input to double
const double inputValue1 = atof(argv[1]);
const double inputValue2 = atof(argv[2]);
// calculate addition
const double outputValue = myAdd(inputValue1, inputValue2);
// display calculation
std::cout << inputValue1 << " + " << inputValue2 << " = " << outputValue
<< std::endl;
return 0;
}
Lesson 1: Your First CMakeList
================================
Intro
-----
Where do I start with CMake? This lesson will teach you the basic
syntax and scope of CMake. To finish, we will create a very simple
CMake project.
CMake Background Info
---------------------
CMake is a procedural based scripting language. This means
that all of the lines of code that you write will be executed
sequentially. In addition, the language is going use higher
level operations.
CMake is aimed at being a build system generator. A build system
manages the sourcefiles and interdependencies of a project and
converts them to programs or libraries. CMake aims to facilitate
building these build systems without you needing to know the fine
details.
Another perk of CMake is it's a cross-platform, open
source tool that quickly integrates new tool functionality. This
way you can use the development environment that you like most.
Now, with that out of the way, lets get started on learning CMake!
CMake Syntax
------------
CMake has most of the core functionality of a standard programming
language. This means that it has the following:
* :command:`boolean and <option>`:command:`string types <set>`
* :command:`variables <set>`
* :command:`mathematical operators <math>`
* :command:`lists <list>`
* :command:`if statements <if>`
* :command:`foreach loops <foreach>`
* :command:`while loops <while>`
* :command:`functions <function>`
* :command:`macros <macro>`
* :command:`include statements <include>`
Please look at the linked documentation to see the specific syntax.
These all behave as you would expect from another C based language.
The only exception can be with variable scope and we will go into
more detail on that later on.
As we can see above, all of the syntax is in the form of commands.
With all of our commands, the arguments are passed in separated
by whitespace. Commands can also span any number of lines as the
extra whitespace will be read over. For readability, it's very common
to see commands like the following:
.. code-block:: cmake
:caption: CMakeLists.txt
set(sources
CellSet.cxx
CellSetExplicit.cxx
)
For more info on each command and to see the exhaustive list, take
a look at :manual:`the documentation <cmake-commands(7)>`. As we go, I
will reference individual commands as we encounter them.
For more info on specific syntax and how the language works, please
refer to :manual:`this documentation <cmake-language(7)>`.
Variable Scope and the Cache
----------------------------
Most variables are created using :command:`set`. Booleans can be
created using :command:`option`. With basic use, variable scope acts
as it would in any other C based language. A variable initialized
inside of a function, loop, or if statement will only exist inside of
the initialized scope. Upon exiting, the function, it will be removed.
CMake supports breaking those intitial scope rules too. Using
:command:`set` with PARENT_SCOPE specified will add the variable into
the scope one higher than its own.
The cache is what CMake uses to store configuration information for your
builds. It's just a simple text file CMakeCache.txt. Variables stored
in the cache are kept from run to run and act as global variables. These
can be :command:`set` using the CACHE keyword.
Note: local variable names override cache variable names. If we make a
cache variable FOO and a local variable FOO, the local variable will be
referenced. The cache variable will be accessible after the local
variable is gone.
For more information on variables and for more specific insights on
the CMake Language syntax, please refer to
:manual:`this documentation <cmake-language(7)>`.
Exercise 1
----------
**Goal:** Understand how to set up a basic project.
**Helpful Materials:**
* :command:`add_executable`
* :command:`cmake_minimum_required`
* :command:`project`
From the workbook directory, navigate to the Exercises/Exercise1 directory
to find the starting materials.
If you do not have the workbook downloaded, go to
https://gitlab.kitware.com/cmake/cmake and clone the CMake repo. In the
CMake repo, navigate to Help/guide/workbook/Exercises/Exercise1 .
**Getting Started:** Open up the CMakeLists.txt file. CMakeLists.txt files
are where you will put your CMake code. Think of them like a .py file but
for CMake code. Next, go through and fill in all of the ``TODO:``
messages with cmake code. Each ``TODO:`` will have more helpful information
for what they want in that specific instance. In addition, take a look
at the helpful materials listed above. These will contain information
that's highly relevant to the current exercise. If you get too stuck, take
a look at the solution in the Solutions directory. When you think you have
the right solution, follow the instructions in **Building** to test it out.
With that, we wish you the best of luck in the first exercise!
Note: each ``TODO:`` corresponds to one line of code unless specifically
mentioned otherwise in the ``TODO:`` statement. This will apply for all
subsequent exercises as well.
**Building:** To build your attempt, start from the Exercises/Exercise1
directory and use the following code from the command line:
.. code-block:: console
cd ../../Builds/Exercise1
cmake ../../Exercises/Exercise1
cmake --build .
If your project built without any errors, then you completed this
exercise!
cd navigates us to the build directory for this exercise. Then we
configure our project using the first cmake command. Note that the
path for the first command points to our source code directory. Then,
we call cmake a second time with the build flag specified. This will
build our project. Note that the path on the cmake build command
uses ``.`` to specify the current directory as the build directory.
The CMake workflow is split into two parts, configuration and build.
``cmake <path>`` corresponds to the configure phase while
``cmake --build <path>`` corresponds to the build phase. Once the
configure phase is done, you do not need to configure again unless
you are changing variables in the cache. If you make only code changes,
you can simply call ``cmake --build .`` from the project build directory
to rebuild the code with your changes added.
**Solution:** To see the solution code, navigate to the Solutions/Exercise1
directory and open the CMakeLists.txt file. The Solutions directory will
contain the solutions for all of the later exercises as well.
Lesson 2: Add a Library
=========================
Intro
-----
At this point, you have seen how to create a basic project using
CMake. How do you take a projet one step further by adding libraries?
In this lesson, we will learn about targets, libraries, includes, and
linking so that we can add a library to a basic project.
Targets in CMake
----------------
CMake uses a set of high-level targets to manage the buildsystem.
Targets are like objects from another programming language. With
a created target, we can attach dependencies, commands, and more to
develop our unique project architecture.
A target can either be any of the following:
* :command:`executable <add_executable>`
* :command:`library <add_library>`
* :command:`custom <add_custom_target>`
We were introduced to an executable target through the :command:`add_executable`
command in Lesson 1. In this lesson, we will explore more about target libraries.
In later lessons, we will explore custom commands and targets.
With a target made, we can do many things to it to build up our project.
Some examples that we will use soon are as follows:
* :command:`target_include_directories`
* :command:`target_link_libraries`
To get a better idea of what each of these do, please refer each one's
linked documentation. To get an exhaustive list of target based commands,
please refer :manual:`here <cmake-commands(7)>`.
This was a very brief overview of targets. For a deeper understanding,
please refer to the :manual:`full documentation <cmake-buildsystem(7)>`.
Libraries
---------
Libraries are a colleciton of code that you use to complete commonly done
tasks. As we saw above, CMake lets us create our own libraries as targets
using :command:`add_library` in the ``CMakeLists.txt`` at the root directory of
the library.
To use a library, you have to include the required headers and then link
the library code. CMake accomplishes this through the functions
:command:`target_include_directories` and :command:`target_link_libraries`.
These would be placed in the project root directory ``CMakeLists.txt``.
Including to a Project
----------------------
Including is when you pass function definitions to the code. This is the
same process as including a header file in C or C++. This creates all of
the definitions so that the code can compile, however there are usually no
filled in functions attached at this time.
CMake handles includes using the following commands:
* :command:`include_directories`
* :command:`target_include_directories`
Both of these allow you to provide CMake paths to search for library include
directories. Their difference between is the later only provides the includes
for the specified target whereas the former provides it for everything. In
general, reducing the scope to only what we need is better, so we are going to
use :command:`target_include_directories` whenever we can.
CMake has the :command:`include` command for when you need more functionality
in your CMake code. This behaves like includes in other languages. We will
use this in the later lessons.
For more information on how including works, please search around online.
There are many great resources that go into far more detail than what was
covered here.
Linking to a Project
--------------------
Linking is when all of the functions are referenced from the various object
file definitions. Linking matches all of the code symbols together and produces
the full code.
CMake handles linking using the following commands:
* :command:`link_directories`
* :command:`target_link_directories`
* :command:`link_libraries`
* :command:`target_link_libraries`
The commands referring to directories allow you to pass a directory and CMake
will search that directory for all libraries and link them. The commands
referring to libraries allow you to provide library names to be linked. These
named libraries have to be in the project directory tree. The commands with
target only link that library to the single target whereas the other commands
would link it to everything.
For more information on linking, please look online as there are many excellent
resources which are far more comprehensive than this.
Exercise 2
----------
**Goal:** Understand how to include and link a library to a project using
lists.
**Helpful Materials:**
* :command:`add_library`
* :command:`add_subdirectory`
* :command:`list`
* :command:`target_include_directories`
* :command:`target_link_libraries`
From the workbook directory, navigate to the Exercises/Exercise2 directory
to find the starting materials. If you do not have the starting materials,
please refer to the **Helpful Materials** section of Lesson 1 to get set up.
**Getting Started:** There is a CMakeList file at both the Exercise2 root
directory and the Exercise2/MathFunctions directory. Go through these files
and fill in all of the ``TODO:`` comments. Each one will have helpful
instructions as well as hints to get you moving along. If you get too stuck, take
a look at the solution in the Solutions directory. When you think you have
the right solution, follow the instructions in **Building** to test it out.
**Building:** To build your attempt, start from the Exercises/Exercise2
directory and use the following code from the command line:
.. code-block:: console
cd ../../Builds/Exercise2
cmake ../../Exercises/Exercise2
cmake --build .
Now the project should be built in /Builds/Exercise2. The project executable
will be in the Debug folder by default. Check and see if your executable is
a simple adding calculator by calling ``./Debug/Exercise2.exe 10 5``. If it works,
then you've completed this lesson!
cmake_minimum_required(VERSION 3.10)
project(Exercise1)
add_executable(Exercise1 exercise1.cxx)
#include <iostream>
int main()
{
std::cout << "Hello World" << std::endl;
return 0;
}
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Exercise2 VERSION 1.0)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")
# add the executable
add_executable(Exercise2 exercise2.cxx)
# link the libraries to the target executable
target_link_libraries(Exercise2 PUBLIC ${EXTRA_LIBS})
# include the directories to the target executable
target_include_directories(Exercise2 PUBLIC ${EXTRA_INCLUDES})
#include <iostream>
// a hack addition calculation using simple operations
double myAdd(double x, double y)
{
return x + y;
}
// A simple program that computes additions
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <string>
#include "MathFunctions.h"
int main(int argc, char* argv[])
{
// ensure that user provides enough arguments
if (argc < 3) {
std::cout << "Usage: " << argv[0] << " number number" << std::endl;
return 1;
}
// convert input to double
const double inputValue1 = atof(argv[1]);
const double inputValue2 = atof(argv[2]);
// calculate addition
const double outputValue = myAdd(inputValue1, inputValue2);
// display calculation
std::cout << inputValue1 << " + " << inputValue2 << " = " << outputValue
<< std::endl;
return 0;
}
CMake Workbook
**************
Introduction
============
Welcome to the CMake Workbook! Here you will find lots of great
exercises for most of your CMake needs. The purpose of this
book is to teach you CMake from the ground up through guided instruction
and accompanying exercises to solidify the information. Each exercise
is independent from the last but the information is cummulative.
It is recommended that you start on exercise 1 and continue from
there. With that, please enjoy the workbook and let us know if there
is anything else you would like to see added or changed!
Exercises
=========
.. include:: source.txt
|workbook_source|
The workbook is split into Exercises, Solutions, and Builds. You will
be working in the Exercises directory and then building each exercise
in the respective Exercise folder in the Builds directory. The Solutions
directory is there for you to check your answers. Also, see the Solutions
side of this online workbook to see a explanation of the answer if you
are stuck.
.. toctree::
:maxdepth: 2
Lesson 1 - Your First CMakeList
Lesson 2 - Add a Library
..
Whenever an exercise above is renamed or removed, leave forwarding text in
its original document file, and list it below to preserve old links
to cmake.org/cmake/help/latest/ URLs.
.. toctree::
:maxdepth: 1
:hidden:
.. |workbook_source| replace::
The code examples can be found in the ``Help/guide/workbook``
directory of the CMake source code tree.
......@@ -82,6 +82,7 @@ Reference Manuals
.. toctree::
:maxdepth: 1
/guide/workbook/index
/guide/tutorial/index
/guide/user-interaction/index
/guide/using-dependencies/index
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment