diff options
author | Markus Ferrell <markus.ferrell@kitware.com> | 2022-07-21 17:43:58 (GMT) |
---|---|---|
committer | Markus Ferrell <markus.ferrell@kitware.com> | 2022-08-15 16:06:34 (GMT) |
commit | c59e1641554cb1b18f4b3a62d20559cfb689a9df (patch) | |
tree | 3c50e94d07da244c72ca3b8fafa902920dbac49c /Help/guide | |
parent | 1493ed10a1485053bb0b7101ccd71d0101977402 (diff) | |
download | CMake-c59e1641554cb1b18f4b3a62d20559cfb689a9df.zip CMake-c59e1641554cb1b18f4b3a62d20559cfb689a9df.tar.gz CMake-c59e1641554cb1b18f4b3a62d20559cfb689a9df.tar.bz2 |
Tutorial: Add Step 1 background info and update style
Diffstat (limited to 'Help/guide')
-rw-r--r-- | Help/guide/tutorial/A Basic Starting Point.rst | 392 | ||||
-rw-r--r-- | Help/guide/tutorial/Step1/CMakeLists.txt | 16 | ||||
-rw-r--r-- | Help/guide/tutorial/Step1/TutorialConfig.h.in | 2 | ||||
-rw-r--r-- | Help/guide/tutorial/Step1/tutorial.cxx | 7 |
4 files changed, 313 insertions, 104 deletions
diff --git a/Help/guide/tutorial/A Basic Starting Point.rst b/Help/guide/tutorial/A Basic Starting Point.rst index d57cc35..33f712d 100644 --- a/Help/guide/tutorial/A Basic Starting Point.rst +++ b/Help/guide/tutorial/A Basic Starting Point.rst @@ -1,45 +1,81 @@ Step 1: A Basic Starting Point ============================== -The most basic project is an executable built from source code files. -For simple projects, a three line ``CMakeLists.txt`` file is all that is -required. This will be the starting point for our tutorial. Create a -``CMakeLists.txt`` file in the ``Step1`` directory that looks like: - -.. code-block:: cmake - :caption: CMakeLists.txt - :name: CMakeLists.txt-start - - cmake_minimum_required(VERSION 3.10) - - # set the project name - project(Tutorial) - - # add the executable - add_executable(Tutorial tutorial.cxx) - +Where do I start with CMake? This step will provide an introduction to some of +CMake's basic syntax, commands, and variables. As these concepts are +introduced, we will work through three exercises and create a simple CMake +project. + +Each exercise in this step will start with some background information. Then, a +goal and list of helpful resources are provided. Each file in the +``Files to Edit`` section is in the ``Step1`` directory and contains one or +more ``TODO`` comments. Each ``TODO`` represents a line or two of code to +change or add. The ``TODO`` s are intended to be completed in numerical order, +first complete ``TODO 1`` then ``TODO 2``, etc. The ``Getting Started`` +section will give some helpful hints and guide you through the exercise. Then +the ``Build and Run`` section will walk step-by-step through how to build and +test the exercise. Finally, at the end of each exercise the intended solution +is discussed. + +Also note that each step in the tutorial builds on the next. So, for example, +the starting code for ``Step2`` is the complete solution to ``Step1``. + +Exercise 1 - Building a Basic Project +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The most basic CMake project is an executable built from a single source code +file. For simple projects like this, a ``CMakeLists.txt`` file with three +commands is all that is required. + +**Note:** Although upper, lower and mixed case commands are supported by CMake, +lower case commands are preferred and will be used throughout the tutorial. + +Any project's top most CMakeLists.txt must start by specifying a minimum CMake +version using the :command:`cmake_minimum_required` command. This establishes +policy settings and ensures that the following CMake functions are run with a +compatible version of CMake. + +To start a project, we use the :command:`project` command to set the project +name. This call is required with every project and should be called soon after +:command:`cmake_minimum_required`. As we will see later, this command can +also be used to specify other project level information such as the language +or version number. + +Finally, the :command:`add_executable` command tells CMake to create an +executable using the specified source code files. + +Goal +---- + +Understand how to create a simple CMake project. + +Helpful Resources +----------------- + +* :command:`add_executable` +* :command:`cmake_minimum_required` +* :command:`project` + +Files to Edit +------------- -Any project's top most ``CMakeLists.txt`` must start by specifying -a minimum CMake version using :command:`cmake_minimum_required`. This ensures -that the later CMake functions are run with a compatible version of CMake. +* ``CMakeLists.txt`` -To start a project, we use :command:`project` to set the project name. This -call is required with every project and should be called soon after -:command:`cmake_minimum_required`. +Getting Started +---------------- -Lastly, we use :command:`add_executable` to specify we want an executable -named Tutorial generated using ``tutorial.cxx`` as the source. +The source code for ``tutorial.cxx`` is provided in the +``Help/guide/tutorial/Step1`` directory and can be used to compute the square +root of a number. This file does not need to be edited in this step. -Note that this example uses lower case commands in the ``CMakeLists.txt`` -file. Upper, lower, and mixed case commands are supported by CMake. The source -code for ``tutorial.cxx`` is provided in the ``Step1`` directory and can be -used to compute the square root of a number. +In the same directory is a ``CMakeLists.txt`` file which you will complete. +Start with ``TODO 1`` and work through ``TODO 3``. Build and Run ------------- -That's all that is needed - we can build and run our project now! First, run -the :manual:`cmake <cmake(1)>` executable or the +Once ``TODO 1`` through ``TODO 3`` have been completed, we are ready to build +and run our project! First, run the :manual:`cmake <cmake(1)>` executable or the :manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it with your chosen build tool. @@ -51,8 +87,9 @@ build directory: mkdir Step1_build -Next, navigate to the build directory and run CMake to configure the project -and generate a native build system: +Next, navigate to that build directory and run +:manual:`cmake <cmake(1)>` to configure the project and generate a native build +system: .. code-block:: console @@ -73,115 +110,264 @@ Finally, try to use the newly built ``Tutorial`` with these commands: Tutorial 10 Tutorial +Solution +-------- -Adding a Version Number and Configured Header File --------------------------------------------------- - -The first feature we will add is to provide our executable and project with a -version number. While we could do this exclusively in the source code, using -``CMakeLists.txt`` provides more flexibility. - -First, modify the ``CMakeLists.txt`` file to use the :command:`project` command -to set the project name and version number. +As mentioned above, a three line ``CMakeLists.txt`` is all that we need to get +up and running. The first line is to use :command:`cmake_minimum_required` to +set the CMake version as follows: .. literalinclude:: Step2/CMakeLists.txt - :caption: CMakeLists.txt - :name: CMakeLists.txt-project-VERSION + :caption: TODO 1: CMakeLists.txt + :name: CMakeLists.txt-cmake_minimum_required :language: cmake - :end-before: # specify the C++ standard + :end-before: # set the project name and version -Then use :command:`configure_file` to pass the version number to the source -code: +The next step to make a basic project is to use the :command:`project` +command as follows to set the project name: -.. literalinclude:: Step2/CMakeLists.txt - :caption: CMakeLists.txt - :name: CMakeLists.txt-configure_file - :language: cmake - :start-after: # to the source code - :end-before: # add the executable +.. code-block:: cmake + :caption: TODO 2: CMakeLists.txt + :name: CMakeLists.txt-project -Since the configured file will be written into the binary tree, we -must add that directory to the list of paths to search for include -files. Use :command:`target_include_directories` to add the following lines to -the end of the ``CMakeLists.txt`` file: + project(Tutorial) + + +The last command to call for a basic project is +:command:`add_executable`. We call it as follows: .. literalinclude:: Step2/CMakeLists.txt - :caption: CMakeLists.txt - :name: CMakeLists.txt-target_include_directories + :caption: TODO 3: CMakeLists.txt + :name: CMakeLists.txt-add_executable :language: cmake - :start-after: # so that we will find TutorialConfig.h + :start-after: # add the executable + :end-before: # add the binary tree to the search path for include files -Using your favorite editor, create ``TutorialConfig.h.in`` in the source -directory with the following contents: +Exercise 2 - Specifying the C++ Standard +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. literalinclude:: Step2/TutorialConfig.h.in - :caption: TutorialConfig.h.in - :name: TutorialConfig.h.in - :language: c++ +CMake has some special variables that are either created behind the scenes or +have meaning to CMake when set by project code. Many of these variables start +with ``CMAKE_``. Avoid this naming convention when creating variables for your +projects. Two of these special user settable variables are +:variable:`CMAKE_CXX_STANDARD` and :variable:`CMAKE_CXX_STANDARD_REQUIRED`. +These may be used together to specify the C++ standard needed to build the +project. -When CMake configures this header file, the values for -``@Tutorial_VERSION_MAJOR@`` and ``@Tutorial_VERSION_MINOR@`` will be -replaced with the corresponding version numbers from the project. +Goal +---- -Next modify ``tutorial.cxx`` to include the configured header file, -``TutorialConfig.h``. +Add a feature that requires C++11. -Finally, let's print out the executable name and version number by updating -``tutorial.cxx`` as follows: +Helpful Resources +----------------- -.. literalinclude:: Step2/tutorial.cxx - :caption: tutorial.cxx - :name: tutorial.cxx-print-version - :language: c++ - :start-after: { - :end-before: // convert input to double +* :variable:`CMAKE_CXX_STANDARD` +* :variable:`CMAKE_CXX_STANDARD_REQUIRED` +* :command:`set` + +Files to Edit +------------- + +* ``CMakeLists.txt`` +* ``tutorial.cxx`` + +Getting Started +--------------- -Specify the C++ Standard -------------------------- +Continue editing files in the ``Step1`` directory. Start with ``TODO 4`` and +complete through ``TODO 6``. -Next let's add some C++11 features to our project by replacing ``atof`` with -``std::stod`` in ``tutorial.cxx``. At the same time, remove -``#include <cstdlib>``. +First, edit ``tutorial.cxx`` by adding a feature that requires C++11. Then +update ``CMakeLists.txt`` to require C++11. + +Build and Run +------------- + +Let's build our project again. Since we already created a build directory and +ran CMake for Exercise 1, we can skip to the build step: + +.. code-block:: console + + cd Step1_build + cmake --build . + +Now we can try to use the newly built ``Tutorial`` with same commands as +before: + +.. code-block:: console + + Tutorial 4294967296 + Tutorial 10 + Tutorial + +Solution +-------- + +We start by adding some C++11 features to our project by replacing +``atof`` with ``std::stod`` in ``tutorial.cxx``. This looks like +the following: .. literalinclude:: Step2/tutorial.cxx - :caption: tutorial.cxx + :caption: TODO 4: tutorial.cxx :name: tutorial.cxx-cxx11 :language: c++ :start-after: // convert input to double :end-before: // calculate square root +To complete ``TODO 5``, simply remove ``#include <cstdlib>``. + We will need to explicitly state in the CMake code that it should use the -correct flags. The easiest way to enable support for a specific C++ standard -in CMake is by using the :variable:`CMAKE_CXX_STANDARD` variable. For this -tutorial, :command:`set` the :variable:`CMAKE_CXX_STANDARD` variable in the -``CMakeLists.txt`` file to ``11`` and :variable:`CMAKE_CXX_STANDARD_REQUIRED` -to ``True``. Make sure to add the ``CMAKE_CXX_STANDARD`` declarations above the -call to ``add_executable``. +correct flags. One way to enable support for a specific C++ standard in CMake +is by using the :variable:`CMAKE_CXX_STANDARD` variable. For this tutorial, set +the :variable:`CMAKE_CXX_STANDARD` variable in the ``CMakeLists.txt`` file to +``11`` and :variable:`CMAKE_CXX_STANDARD_REQUIRED` to ``True``. Make sure to +add the :variable:`CMAKE_CXX_STANDARD` declarations above the call to +:command:`add_executable`. .. literalinclude:: Step2/CMakeLists.txt - :caption: CMakeLists.txt + :caption: TODO 6: CMakeLists.txt :name: CMakeLists.txt-CXX_STANDARD :language: cmake + :start-after: # specify the C++ standard :end-before: # configure a header file to pass some of the CMake settings -Rebuild -------- +Exercise 3 - Adding a Version Number and Configured Header File +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Sometimes it may be useful to have a variable that is defined in your +``CMakelists.txt`` file also be available in your source code. In this case, we +would like to print the project version. + +One way to accomplish this is by using a configured header file. We create an +input file with one or more variables to replace. These variables have special +syntax which looks like ``@VAR@``. +Then, we use the :command:`configure_file` command to copy the input file to a +given output file and replace these variables with the current value of ``VAR`` +in the ``CMakelists.txt`` file. -Let's build our project again. We already created a build directory and ran -CMake, so we can skip to the build step: +While we could edit the version directly in the source code, using this +feature is preferred since it creates a single source of truth and avoids +duplication. + +Goal +---- + +Define and report the project's version number. + +Helpful Resources +----------------- + +* :variable:`<PROJECT-NAME>_VERSION_MAJOR` +* :variable:`<PROJECT-NAME>_VERSION_MINOR` +* :command:`configure_file` +* :command:`target_include_directories` + +Files to Edit +------------- + +* ``CMakeLists.txt`` +* ``tutorial.cxx`` + +Getting Started +--------------- + +Continue to edit files from ``Step1``. Start on ``TODO 7`` and complete through +``TODO 12``. In this exercise, we start by adding a project version number in +``CMakeLists.txt``. In that same file, use :command:`configure_file` to copy a +given input file to an output file and substitute some variable values in the +input file content. + +Next, create an input header file ``TutorialConfig.h.in`` defining version +numbers which will accept variables passed from :command:`configure_file`. + +Finally, update ``tutorial.cxx`` to print out its version number. + +Build and Run +------------- + +Let's build our project again. As before, we already created a build directory +and ran CMake so we can skip to the build step: .. code-block:: console cd Step1_build cmake --build . -Now we can try to use the newly built ``Tutorial`` with same commands as before: +Verify that the version number is now reported when running the executable +without any arguments. -.. code-block:: console +Solution +-------- - Tutorial 4294967296 - Tutorial 10 - Tutorial +In this exercise, we improve our executable by printing a version number. +While we could do this exclusively in the source code, using ``CMakeLists.txt`` +lets us maintain a single source of data for the version number. + +First, we modify the ``CMakeLists.txt`` file to use the +:command:`project` command to set both the project name and version number. +When the command:`project` command is called, CMake defines +``Tutorial_VERSION_MAJOR`` and ``Tutorial_VERSION_MINOR`` behind the scenes. + +.. literalinclude:: Step2/CMakeLists.txt + :caption: TODO 7: CMakeLists.txt + :name: CMakeLists.txt-project-VERSION + :language: cmake + :start-after: # set the project name and version + :end-before: # specify the C++ standard + +Then we used :command:`configure_file` to copy the input file with the +specified CMake variables replaced: -Check that the version number is now reported when running the executable without -any arguments. +.. literalinclude:: Step2/CMakeLists.txt + :caption: TODO 8: CMakeLists.txt + :name: CMakeLists.txt-configure_file + :language: cmake + :start-after: # to the source code + :end-before: # add the executable + +Since the configured file will be written into the project binary +directory, we must add that directory to the list of paths to search for +include files. + +**Note:** Throughout this tutorial, we will refer to the project build and +the project binary directory interchangeably. These are the same and are not +meant to refer to a `bin/` directory. + +We used :command:`target_include_directories` to specify +where the executable target should look for include files. + +.. literalinclude:: Step2/CMakeLists.txt + :caption: TODO 9: CMakeLists.txt + :name: CMakeLists.txt-target_include_directories + :language: cmake + :start-after: # so that we will find TutorialConfig.h + +``TutorialConfig.h.in`` is the input header file to be configured. +When :command:`configure_file` is called from our ``CMakeLists.txt``, the +values for ``@Tutorial_VERSION_MAJOR@`` and ``@Tutorial_VERSION_MINOR@`` will +be replaced with the corresponding version numbers from the project in +``TutorialConfig.h``. + +.. literalinclude:: Step2/TutorialConfig.h.in + :caption: TODO 10: TutorialConfig.h.in + :name: TutorialConfig.h.in + :language: c++ + +Next, we need to modify ``tutorial.cxx`` to include the configured header file, +``TutorialConfig.h``. + +.. code-block:: c++ + :caption: TODO 11: tutorial.cxx + + #include "TutorialConfig.h" + +Finally, we print out the executable name and version number by updating +``tutorial.cxx`` as follows: + +.. literalinclude:: Step2/tutorial.cxx + :caption: TODO 12 : tutorial.cxx + :name: tutorial.cxx-print-version + :language: c++ + :start-after: { + :end-before: // convert input to double diff --git a/Help/guide/tutorial/Step1/CMakeLists.txt b/Help/guide/tutorial/Step1/CMakeLists.txt new file mode 100644 index 0000000..282951a --- /dev/null +++ b/Help/guide/tutorial/Step1/CMakeLists.txt @@ -0,0 +1,16 @@ +# TODO 1: Set the minimum required version of CMake to be 3.10 + +# TODO 2: Create a project named Tutorial + +# TODO 7: Set the project version number as 1.0 in the above project command + +# TODO 6: Set the variable CMAKE_CXX_STANDARD to 11 +# and the variable CMAKE_CXX_REQUIRED_STANDARD to True + +# TODO 8: Use configure_file to configure and copy TutorialConfig.h.in to +# TutorialConfig.h + +# TODO 3: Add an executable called Tutorial to the project +# Hint: Be sure to specify the source file as tutorial.cxx + +# TODO 9: Use target_include_directories to include ${PROJECT_BINARY_DIR} diff --git a/Help/guide/tutorial/Step1/TutorialConfig.h.in b/Help/guide/tutorial/Step1/TutorialConfig.h.in new file mode 100644 index 0000000..990bfbd --- /dev/null +++ b/Help/guide/tutorial/Step1/TutorialConfig.h.in @@ -0,0 +1,2 @@ +// the configured options and settings for Tutorial +// TODO 10: Define Tutorial_VERSION_MAJOR and Tutorial_VERSION_MINOR diff --git a/Help/guide/tutorial/Step1/tutorial.cxx b/Help/guide/tutorial/Step1/tutorial.cxx index 08323bf..64d0916 100644 --- a/Help/guide/tutorial/Step1/tutorial.cxx +++ b/Help/guide/tutorial/Step1/tutorial.cxx @@ -1,17 +1,22 @@ // A simple program that computes the square root of a number #include <cmath> -#include <cstdlib> +#include <cstdlib> // TODO 5: Remove this line #include <iostream> #include <string> +// TODO 11: Include TutorialConfig.h + int main(int argc, char* argv[]) { if (argc < 2) { + // TODO 12: Create a print statement using Tutorial_VERSION_MAJOR + // and Tutorial_VERSION_MINOR std::cout << "Usage: " << argv[0] << " number" << std::endl; return 1; } // convert input to double + // TODO 4: Replace atof(argv[1]) with std::stod(argv[1]) const double inputValue = atof(argv[1]); // calculate square root |