Commit 82332f81 authored by Betsy McPhail's avatar Betsy McPhail Committed by Brad King

Tutorial: Improve Step 1

* Update minimum required version to 3.10
* Use VERSION argument to project command rather than separate variables
* Replace `endif(USE_MYMATH)` with  more modern `endif()`
* Simplify the call to 'configure_file()'
* Add comments to tutorial.cxx to use as anchors in documentation
* Remove CMakeLists and TutorialConfig.h.in files that users should
  create. Consequently, remove Step1 from CMake tests.
parent 1996e015
cmake_minimum_required(VERSION 3.15)
project(Tutorial)
# set the project name and version
project(Tutorial VERSION 1.0)
add_library(tutorial_compiler_flags INTERFACE)
target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)
......@@ -13,10 +15,6 @@ target_compile_options(tutorial_compiler_flags INTERFACE
"$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>"
)
# set the version number
set(Tutorial_VERSION_MAJOR 1)
set(Tutorial_VERSION_MINOR 0)
# control where the static and shared libraries are built so that on windows
# we don't need to tinker with the path to run the executable
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
......@@ -32,10 +30,7 @@ elseif(UNIX)
endif()
# configure a header file to pass the version number only
configure_file(
"${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
"${PROJECT_BINARY_DIR}/TutorialConfig.h"
)
configure_file(TutorialConfig.h.in TutorialConfig.h)
# add the MathFunctions library
add_subdirectory(MathFunctions)
......
......@@ -15,10 +15,11 @@ int main(int argc, char* argv[])
return 1;
}
double inputValue = std::stod(argv[1]);
// convert input to double
const double inputValue = std::stod(argv[1]);
// calculate square root
const double outputValue = mathfunctions::sqrt(inputValue);
std::cout << "The square root of " << inputValue << " is " << outputValue
<< std::endl;
return 0;
......
cmake_minimum_required(VERSION 3.3)
cmake_minimum_required(VERSION 3.10)
if(NOT DEFINED CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 11)
......
cmake_minimum_required(VERSION 3.3)
project(Tutorial)
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Tutorial VERSION 1.0)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# set the version number
set(Tutorial_VERSION_MAJOR 1)
set(Tutorial_VERSION_MINOR 0)
# control where the static and shared libraries are built so that on windows
# we don't need to tinker with the path to run the executable
......@@ -23,10 +22,7 @@ elseif(UNIX)
endif()
# configure a header file to pass the version number only
configure_file(
"${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
"${PROJECT_BINARY_DIR}/TutorialConfig.h"
)
configure_file(TutorialConfig.h.in TutorialConfig.h)
# add the MathFunctions library
add_subdirectory(MathFunctions)
......
......@@ -15,6 +15,7 @@ int main(int argc, char* argv[])
return 1;
}
// convert input to double
double inputValue = std::stod(argv[1]);
const double outputValue = mathfunctions::sqrt(inputValue);
......
project(Tutorial)
add_executable(Tutorial tutorial.cxx)
// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
......@@ -11,9 +11,11 @@ int main(int argc, char* argv[])
return 1;
}
double inputValue = atof(argv[1]);
// convert input to double
const double inputValue = atof(argv[1]);
double outputValue = sqrt(inputValue);
// calculate square root
const double outputValue = sqrt(inputValue);
std::cout << "The square root of " << inputValue << " is " << outputValue
<< std::endl;
return 0;
......
cmake_minimum_required(VERSION 3.3)
project(Tutorial)
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Tutorial VERSION 1.0)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# Set the version number
set(Tutorial_VERSION_MAJOR 1)
set(Tutorial_VERSION_MINOR 0)
# control where the static and shared libraries are built so that on windows
# we don't need to tinker with the path to run the executable
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
......@@ -17,10 +16,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
# configure a header file to pass the version number only
configure_file(
"${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
"${PROJECT_BINARY_DIR}/TutorialConfig.h"
)
configure_file(TutorialConfig.h.in TutorialConfig.h)
# add the MathFunctions library
add_subdirectory(MathFunctions)
......
......@@ -16,7 +16,8 @@ int main(int argc, char* argv[])
return 1;
}
double inputValue = std::stod(argv[1]);
// convert input to double
const double inputValue = std::stod(argv[1]);
const double outputValue = mathfunctions::sqrt(inputValue);
......
cmake_minimum_required(VERSION 3.15)
project(Tutorial)
# set the project name and version
project(Tutorial VERSION 1.0)
add_library(tutorial_compiler_flags INTERFACE)
target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)
......@@ -13,10 +15,6 @@ target_compile_options(tutorial_compiler_flags INTERFACE
"$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>"
)
# set the version number
set(Tutorial_VERSION_MAJOR 1)
set(Tutorial_VERSION_MINOR 0)
# control where the static and shared libraries are built so that on windows
# we don't need to tinker with the path to run the executable
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
......@@ -26,10 +24,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
# configure a header file to pass the version number only
configure_file(
"${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
"${PROJECT_BINARY_DIR}/TutorialConfig.h"
)
configure_file(TutorialConfig.h.in TutorialConfig.h)
# add the MathFunctions library
add_subdirectory(MathFunctions)
......
......@@ -16,7 +16,8 @@ int main(int argc, char* argv[])
return 1;
}
double inputValue = std::stod(argv[1]);
// convert input to double
const double inputValue = std::stod(argv[1]);
const double outputValue = mathfunctions::sqrt(inputValue);
......
cmake_minimum_required(VERSION 3.3)
project(Tutorial)
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Tutorial VERSION 1.0)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# set the version number
set(Tutorial_VERSION_MAJOR 1)
set(Tutorial_VERSION_MINOR 0)
# configure a header file to pass some of the CMake settings
# to the source code
configure_file(
"${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
"${PROJECT_BINARY_DIR}/TutorialConfig.h"
)
configure_file(TutorialConfig.h.in TutorialConfig.h)
# add the executable
add_executable(Tutorial tutorial.cxx)
......
......@@ -15,9 +15,11 @@ int main(int argc, char* argv[])
return 1;
}
double inputValue = std::stod(argv[1]);
// convert input to double
const double inputValue = std::stod(argv[1]);
double outputValue = sqrt(inputValue);
// calculate square root
const double outputValue = sqrt(inputValue);
std::cout << "The square root of " << inputValue << " is " << outputValue
<< std::endl;
return 0;
......
cmake_minimum_required(VERSION 3.3)
project(Tutorial)
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Tutorial VERSION 1.0)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# should we use our own math functions
option(USE_MYMATH "Use tutorial provided math implementation" ON)
# set the version number
set(Tutorial_VERSION_MAJOR 1)
set(Tutorial_VERSION_MINOR 0)
# configure a header file to pass some of the CMake settings
# to the source code
configure_file(
"${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
"${PROJECT_BINARY_DIR}/TutorialConfig.h"
)
configure_file(TutorialConfig.h.in TutorialConfig.h)
# add the MathFunctions library?
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")
endif(USE_MYMATH)
endif()
# add the executable
add_executable(Tutorial tutorial.cxx)
......
......@@ -20,13 +20,14 @@ int main(int argc, char* argv[])
return 1;
}
double inputValue = std::stod(argv[1]);
// convert input to double
const double inputValue = std::stod(argv[1]);
// which square root function should we use?
#ifdef USE_MYMATH
double outputValue = mysqrt(inputValue);
const double outputValue = mysqrt(inputValue);
#else
double outputValue = sqrt(inputValue);
const double outputValue = sqrt(inputValue);
#endif
std::cout << "The square root of " << inputValue << " is " << outputValue
......
cmake_minimum_required(VERSION 3.3)
project(Tutorial)
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Tutorial VERSION 1.0)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# should we use our own math functions
option(USE_MYMATH "Use tutorial provided math implementation" ON)
# set the version number
set(Tutorial_VERSION_MAJOR 1)
set(Tutorial_VERSION_MINOR 0)
# configure a header file to pass some of the CMake settings
# to the source code
configure_file(
"${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
"${PROJECT_BINARY_DIR}/TutorialConfig.h"
)
configure_file(TutorialConfig.h.in TutorialConfig.h)
# add the MathFunctions library?
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
endif(USE_MYMATH)
endif()
# add the executable
add_executable(Tutorial tutorial.cxx)
......
......@@ -20,13 +20,14 @@ int main(int argc, char* argv[])
return 1;
}
double inputValue = std::stod(argv[1]);
// convert input to double
const double inputValue = std::stod(argv[1]);
// which square root function should we use?
#ifdef USE_MYMATH
double outputValue = mysqrt(inputValue);
const double outputValue = mysqrt(inputValue);
#else
double outputValue = sqrt(inputValue);
const double outputValue = sqrt(inputValue);
#endif
std::cout << "The square root of " << inputValue << " is " << outputValue
......
cmake_minimum_required(VERSION 3.3)
project(Tutorial)
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Tutorial VERSION 1.0)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# should we use our own math functions
option(USE_MYMATH "Use tutorial provided math implementation" ON)
# set the version number
set(Tutorial_VERSION_MAJOR 1)
set(Tutorial_VERSION_MINOR 0)
# configure a header file to pass some of the CMake settings
# to the source code
configure_file(
"${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
"${PROJECT_BINARY_DIR}/TutorialConfig.h"
)
configure_file(TutorialConfig.h.in TutorialConfig.h)
# add the MathFunctions library?
if(USE_MYMATH)
......
......@@ -20,13 +20,14 @@ int main(int argc, char* argv[])
return 1;
}
double inputValue = std::stod(argv[1]);
// convert input to double
const double inputValue = std::stod(argv[1]);
// which square root function should we use?
#ifdef USE_MYMATH
double outputValue = mysqrt(inputValue);
const double outputValue = mysqrt(inputValue);
#else
double outputValue = sqrt(inputValue);
const double outputValue = sqrt(inputValue);
#endif
std::cout << "The square root of " << inputValue << " is " << outputValue
......
cmake_minimum_required(VERSION 3.3)
project(Tutorial)
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Tutorial VERSION 1.0)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# set the version number
set(Tutorial_VERSION_MAJOR 1)
set(Tutorial_VERSION_MINOR 0)
# does this system provide the log and exp functions?
include(CheckSymbolExists)
set(CMAKE_REQUIRED_LIBRARIES "m")
......@@ -19,10 +18,7 @@ option(USE_MYMATH "Use tutorial provided math implementation" ON)
# configure a header file to pass some of the CMake settings
# to the source code
configure_file(
"${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
"${PROJECT_BINARY_DIR}/TutorialConfig.h"
)
configure_file(TutorialConfig.h.in TutorialConfig.h)
# add the MathFunctions library?
if(USE_MYMATH)
......
......@@ -20,13 +20,14 @@ int main(int argc, char* argv[])
return 1;
}
double inputValue = std::stod(argv[1]);
// convert input to double
const double inputValue = std::stod(argv[1]);
// which square root function should we use?
#ifdef USE_MYMATH
double outputValue = mysqrt(inputValue);
const double outputValue = mysqrt(inputValue);
#else
double outputValue = sqrt(inputValue);
const double outputValue = sqrt(inputValue);
#endif
std::cout << "The square root of " << inputValue << " is " << outputValue
......
cmake_minimum_required(VERSION 3.3)
project(Tutorial)
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Tutorial VERSION 1.0)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# set the version number
set(Tutorial_VERSION_MAJOR 1)
set(Tutorial_VERSION_MINOR 0)
# does this system provide the log and exp functions?
include(CheckSymbolExists)
set(CMAKE_REQUIRED_LIBRARIES "m")
......@@ -19,16 +18,13 @@ option(USE_MYMATH "Use tutorial provided math implementation" ON)
# configure a header file to pass some of the CMake settings
# to the source code
configure_file(
"${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
"${PROJECT_BINARY_DIR}/TutorialConfig.h"
)
configure_file(TutorialConfig.h.in TutorialConfig.h)
# add the MathFunctions library?
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
endif(USE_MYMATH)
endif()
# add the executable
add_executable(Tutorial tutorial.cxx)
......
......@@ -20,13 +20,14 @@ int main(int argc, char* argv[])
return 1;
}
double inputValue = std::stod(argv[1]);
// convert input to double
const double inputValue = std::stod(argv[1]);
// which square root function should we use?
#ifdef USE_MYMATH
double outputValue = mysqrt(inputValue);
const double outputValue = mysqrt(inputValue);
#else
double outputValue = sqrt(inputValue);
const double outputValue = sqrt(inputValue);
#endif
std::cout << "The square root of " << inputValue << " is " << outputValue
......
cmake_minimum_required(VERSION 3.3)
project(Tutorial)
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Tutorial VERSION 1.0)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# set the version number
set(Tutorial_VERSION_MAJOR 1)
set(Tutorial_VERSION_MINOR 0)
# does this system provide the log and exp functions?
include(CheckSymbolExists)
set(CMAKE_REQUIRED_LIBRARIES "m")
......@@ -19,16 +18,13 @@ option(USE_MYMATH "Use tutorial provided math implementation" ON)
# configure a header file to pass some of the CMake settings
# to the source code
configure_file(
"${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
"${PROJECT_BINARY_DIR}/TutorialConfig.h"
)
configure_file(TutorialConfig.h.in TutorialConfig.h)
# add the MathFunctions library?
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
endif(USE_MYMATH)
endif()
# add the executable
add_executable(Tutorial tutorial.cxx)
......
......@@ -20,13 +20,14 @@ int main(int argc, char* argv[])
return 1;
}
double inputValue = std::stod(argv[1]);
// convert input to double
const double inputValue = std::stod(argv[1]);
// which square root function should we use?
#ifdef USE_MYMATH
double outputValue = mysqrt(inputValue);
const double outputValue = mysqrt(inputValue);
#else
double outputValue = sqrt(inputValue);
const double outputValue = sqrt(inputValue);
#endif
std::cout << "The square root of " << inputValue << " is " << outputValue
......
cmake_minimum_required(VERSION 3.3)
project(Tutorial)
cmake_minimum_required(VERSION 3.10)
# set the project name and version
project(Tutorial VERSION 1.0)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# set the version number
set(Tutorial_VERSION_MAJOR 1)
set(Tutorial_VERSION_MINOR 0)
# does this system provide the log and exp functions?
include(CheckSymbolExists)
set(CMAKE_REQUIRED_LIBRARIES "m")
......@@ -18,10 +17,7 @@ check_symbol_exists(exp "math.h" HAVE_EXP)
option(USE_MYMATH "Use tutorial provided math implementation" ON)
# configure a header file to pass the version number only
configure_file(
"${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
"${PROJECT_BINARY_DIR}/TutorialConfig.h"
)
configure_file(TutorialConfig.h.in TutorialConfig.h)
# add the MathFunctions library?
if(USE_MYMATH)
......
......@@ -21,13 +21,14 @@ int main(int argc, char* argv[])
return 1;
}
double inputValue = std::stod(argv[1]);
// convert input to double
const double inputValue = std::stod(argv[1]);
// which square root function should we use?
#ifdef USE_MYMATH
double outputValue = mysqrt(inputValue);
const double outputValue = mysqrt(inputValue);
#else
double outputValue = sqrt(inputValue);
const double outputValue = sqrt(inputValue);
#endif
std::cout << "The square root of " << inputValue << " is " << outputValue
......
......@@ -5,33 +5,38 @@ CMake Tutorial
.. contents::
This tutorial provides a step-by-step guide that covers common build
The CMake tutorial provides a step-by-step guide that covers common build
system issues that CMake helps address. Seeing how various topics all
work together in an example project can be very helpful. This tutorial
can be found in the ``Help/guide/tutorial`` directory of the CMake
source code tree. Each topic has its own subdirectory containing code
that may be used as a starting point for that step. The tutorial
examples are progressive so that each step provides the complete
work together in an example project can be very helpful. The tutorial
documentation and source code for examples can be found in the
``Help/guide/tutorial`` directory of the CMake source code tree. Each step has
its own subdirectory containing code that may be used as a starting point. The
tutorial examples are progressive so that each step provides the complete
solution for the previous step.
A Basic Starting Point (Step 1)
===============================
The most basic project is an executable built from source code files.
For simple projects, a two line CMakeLists file is all that is required.
This will be the starting point for our tutorial. The CMakeLists file
looks like:
For simple projects, a three line CMakeLists 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
cmake_minimum_required(VERSION 3.10)
# set the project name
project(Tutorial)
# add the executable
add_executable(Tutorial tutorial.cxx)
.. literalinclude:: Step1/CMakeLists.txt
:language: cmake
Note that this example uses lower case commands in the CMakeLists file.
Upper, lower, and mixed case commands are supported by CMake. The source
code for ``tutorial.cxx`` will compute the square root of a number and
the first version of it is very simple, as follows:
.. literalinclude:: Step1/tutorial.cxx
:language: c++
code for ``tutorial.cxx`` is provided in the ``Step1`` directory and can be
used to compute the square root of a number.
Adding a Version Number and Configured Header File
--------------------------------------------------
......@@ -40,55 +45,70 @@ 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 provides more flexibility.
To add a version number we modify the CMakeLists file as follows:
First, modify the CMakeLists file to set the version number.
.. literalinclude:: Step2/CMakeLists.txt
:language: cmake
:end-before: # specify the C++ standard
Then, configure a header file to pass the version number to the source
code:
.. literalinclude:: Step2/CMakeLists.txt
:language: cmake
:start-after: # set the version number
:end-before: # configure a header file
:start-after: # to the source code
:end-before: # add the executable
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.
files. Add the following lines to the end of the CMakeLists file:
.. literalinclude:: Step2/CMakeLists.txt
:language: cmake
:start-after: # so that we will find TutorialConfig.h
We then create a ``TutorialConfig.h.in`` file in the source tree with the
following contents:
Using your favorite editor, create ``TutorialConfig.h.in`` in the source
directory with the following contents:
.. literalinclude:: Step1/TutorialConfig.h.in
.. literalinclude:: Step2/TutorialConfig.h.in
:language: cmake
When CMake configures this header file the values for
``@Tutorial_VERSION_MAJOR@`` and ``@Tutorial_VERSION_MINOR@`` will be
replaced by the values from the CMakeLists file. Next we modify
``tutorial.cxx`` to include the configured header file and to make use of the
version numbers. The updated source code is listed below.
replaced.
Next modify ``tutorial.cxx`` to include the configured header file,
``TutorialConfig.h``.
Finally, let's print out the version number by updating ``tutorial.cxx`` as
follows:
.. literalinclude:: Step2/tutorial.cxx
:language: c++
:start-after: // report version
:end-before: return 1;
The main changes are the inclusion of the ``TutorialConfig.h`` header
file and printing out a version number as part of the usage message.
:start-after: {
:end-before: // convert input to double
Specify the C++ Standard
-------------------------
Next let's add some C++11 features to our project. We will need to explicitly
state in the CMake code that it should use the correct flags. The easiest way
to enable C++11 support for CMake is by using the ``CMAKE_CXX_STANDARD``
variable.
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, replace ``atof`` with ``std::stod`` in ``tutorial.cxx``.