Tutorial: Refactor MathFunctions code

Propagate the refactor in Step 10 MathFunctions through all of the
steps. Use MathFunctions/MathFunctions.cxx instead of Tutorial.cxx
to determine which sqrt library is called. Adds .h files which
correspond to their .cxx files by name.
This commit is contained in:
Markus Ferrell
2023-02-10 16:07:06 -05:00
parent 78299083d2
commit 8ddf32196c
81 changed files with 650 additions and 521 deletions

View File

@@ -160,7 +160,7 @@ The last command to call for a basic project is
:name: CMakeLists.txt-add_executable
:language: cmake
:start-after: # add the executable
:end-before: # TODO 9:
:end-before: # TODO 3:
.. raw:: html
@@ -240,7 +240,7 @@ the following:
:name: tutorial.cxx-cxx11
:language: c++
:start-after: // convert input to double
:end-before: // TODO 12:
:end-before: // TODO 6:
.. raw:: html
@@ -265,7 +265,7 @@ add the :variable:`CMAKE_CXX_STANDARD` declarations above the call to
:name: CMakeLists.txt-CXX_STANDARD
:language: cmake
:start-after: # specify the C++ standard
:end-before: # TODO 7:
:end-before: # configure a header file
.. raw:: html
@@ -375,7 +375,7 @@ specified CMake variables replaced:
:name: CMakeLists.txt-configure_file
:language: cmake
:start-after: # to the source code
:end-before: # TODO 8:
:end-before: # TODO 2:
.. raw:: html
@@ -420,7 +420,6 @@ be replaced with the corresponding version numbers from the project in
:caption: TODO 10: TutorialConfig.h.in
:name: TutorialConfig.h.in
:language: c++
:end-before: // TODO 13:
.. raw:: html

View File

@@ -299,7 +299,7 @@ condition. The resulting full code looks like the following:
:name: CMakeLists.txt-target_compile_options-genex
:language: cmake
:start-after: set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>")
:end-before: # should we use our own math functions
:end-before: # configure a header file to pass some of the CMake settings
.. raw:: html

View File

@@ -119,7 +119,7 @@ our source code can tell what resources are available. If both ``log`` and
:name: MathFunctions/CMakeLists.txt-target_compile_definitions
:language: cmake
:start-after: # add compile definitions
:end-before: # install libs
:end-before: # state
.. raw:: html
@@ -136,7 +136,8 @@ Since we may be using ``log`` and ``exp``, we need to modify
:caption: TODO 4: MathFunctions/mysqrt.cxx
:name: MathFunctions/mysqrt.cxx-include-cmath
:language: c++
:end-before: #include <iostream>
:start-after: #include "mysqrt.h"
:end-before: include <iostream>
.. raw:: html

View File

@@ -100,7 +100,7 @@ follows:
:name: MathFunctions/CMakeLists.txt-target_include_directories-INTERFACE
:language: cmake
:start-after: # to find MathFunctions.h
:end-before: # TODO 3: Link to
:end-before: option
.. raw:: html
@@ -119,7 +119,7 @@ safely remove our uses of the ``EXTRA_INCLUDES`` variable from the top-level
:name: CMakeLists.txt-remove-EXTRA_INCLUDES
:language: cmake
:start-after: # add the MathFunctions library
:end-before: # add the executable
:end-before: # TODO 2: Link to tutorial_compiler_flags
.. raw:: html

View File

@@ -23,15 +23,25 @@ The next step is to add the appropriate commands to the
then run it as part of the build process. A few commands are needed to
accomplish this.
First, at the top of ``MathFunctions/CMakeLists.txt``, the executable for
``MakeTable`` is added as any other executable would be added.
First, in the ``USE_MYMATH`` section of ``MathFunctions/CMakeLists.txt``,
we add an executable for ``MakeTable``.
.. literalinclude:: Step9/MathFunctions/CMakeLists.txt
:caption: MathFunctions/CMakeLists.txt
:name: MathFunctions/CMakeLists.txt-add_executable-MakeTable
:language: cmake
:start-after: # first we add the executable that generates the table
:end-before: # add the command to generate the source code
:end-before: target_link_libraries
After creating the executable, we add the ``tutorial_compiler_flags`` to our
executable using :command:`target_link_libraries`.
.. literalinclude:: Step9/MathFunctions/CMakeLists.txt
:caption: MathFunctions/CMakeLists.txt
:name: MathFunctions/CMakeLists.txt-link-tutorial-compiler-flags
:language: cmake
:start-after: add_executable
:end-before: # add the command to generate
Then we add a custom command that specifies how to produce ``Table.h``
by running MakeTable.
@@ -41,7 +51,7 @@ by running MakeTable.
:name: MathFunctions/CMakeLists.txt-add_custom_command-Table.h
:language: cmake
:start-after: # add the command to generate the source code
:end-before: # add the main library
:end-before: # library that just does sqrt
Next we have to let CMake know that ``mysqrt.cxx`` depends on the generated
file ``Table.h``. This is done by adding the generated ``Table.h`` to the list
@@ -51,8 +61,8 @@ of sources for the library MathFunctions.
:caption: MathFunctions/CMakeLists.txt
:name: MathFunctions/CMakeLists.txt-add_library-Table.h
:language: cmake
:start-after: # add the main library
:end-before: # state that anybody linking
:start-after: # library that just does sqrt
:end-before: # state that we depend on
We also have to add the current binary directory to the list of include
directories so that ``Table.h`` can be found and included by ``mysqrt.cxx``.
@@ -62,7 +72,19 @@ directories so that ``Table.h`` can be found and included by ``mysqrt.cxx``.
:name: MathFunctions/CMakeLists.txt-target_include_directories-Table.h
:language: cmake
:start-after: # state that we depend on our bin
:end-before: # install libs
:end-before: target_link_libraries
As the last thing in our ``USE_MYMATH`` section, we need to link the our
flags onto ``SqrtLibrary`` and then link ``SqrtLibrary`` onto
``MathFunctions``. This makes the resulting ``USE_MYMATH`` section look like
the following:
.. literalinclude:: Step9/MathFunctions/CMakeLists.txt
:caption: MathFunctions/CMakeLists.txt
:name: MathFunctions/CMakeLists.txt-full_USE_MYMATH-section
:language: cmake
:start-after: if (USE_MYMATH)
:end-before: endif()
Now let's use the generated table. First, modify ``mysqrt.cxx`` to include
``Table.h``. Next, we can rewrite the ``mysqrt`` function to use the table:

View File

@@ -51,11 +51,13 @@ then use this library instead of the standard square root function provided by
the compiler.
For this tutorial we will put the library into a subdirectory called
``MathFunctions``. This directory already contains a header file,
``MathFunctions.h``, and a source file ``mysqrt.cxx``. We will not need to
modify either of these files. The source file has one function called
``MathFunctions``. This directory already contains the header files
``MathFunctions.h`` and ``mysqrt.h``. Their respective source files
``MathFunctions.cxx`` and ``mysqrt.cxx`` are also provided. We will not need
to modify any of these files. ``mysqrt.cxx`` has one function called
``mysqrt`` that provides similar functionality to the compiler's ``sqrt``
function.
function. ``MathFunctions.cxx`` contains one function ``sqrt`` which serves
to hide the implementation details of ``sqrt``.
From the ``Help/guide/tutorial/Step2`` directory, start with ``TODO 1`` and
complete through ``TODO 6``.
@@ -91,10 +93,10 @@ Solution
In the ``CMakeLists.txt`` file in the ``MathFunctions`` directory, we create
a library target called ``MathFunctions`` with :command:`add_library`. The
source file for the library is passed as an argument to
source files for the library are passed as an argument to
:command:`add_library`. This looks like the following line:
.. raw:: html
.. raw:: html/
<details><summary>TODO 1: Click to show/hide answer</summary>
@@ -171,36 +173,40 @@ Now let's use our library. In ``tutorial.cxx``, include ``MathFunctions.h``:
<details><summary>TODO 5: Click to show/hide answer</summary>
.. code-block:: c++
:caption: TODO 5 : tutorial.cxx
:name: tutorial.cxx-include_MathFunctions.h
#include "MathFunctions.h"
.. literalinclude:: Step3/tutorial.cxx
:caption: TODO 5: tutorial.cxx
:name: CMakeLists.txt-include-MathFunctions.h
:language: cmake
:start-after: #include <string>
:end-before: #include "TutorialConfig.h"
.. raw:: html
</details>
Lastly, replace ``sqrt`` with our library function ``mysqrt``.
Lastly, replace ``sqrt`` with our library function ``mathfunctions::mysqrt``.
.. raw:: html
<details><summary>TODO 6: Click to show/hide answer</summary>
.. code-block:: c++
:caption: TODO 6 : tutorial.cxx
:name: tutorial.cxx-call_mysqrt
const double outputValue = mysqrt(inputValue);
.. literalinclude:: Step3/tutorial.cxx
:caption: TODO 7: tutorial.cxx
:name: CMakeLists.txt-option
:language: cmake
:start-after: const double inputValue = std::stod(argv[1]);
:end-before: std::cout
.. raw:: html
</details>
Exercise 2 - Making Our Library Optional
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Exercise 2 - Adding an Option
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Now let us make the MathFunctions library optional. While for the tutorial
Now let us add an option in the MathFunctions library to allow developers to
select either the custom square root implementation or the built in standard
implementation. While for the tutorial
there really isn't any need to do so, for larger projects this is a common
occurrence.
@@ -219,28 +225,26 @@ Helpful Resources
-----------------
* :command:`if`
* :command:`list`
* :command:`option`
* :command:`cmakedefine <configure_file>`
* :command:`target_compile_definitions`
Files to Edit
-------------
* ``CMakeLists.txt``
* ``tutorial.cxx``
* ``TutorialConfig.h.in``
* ``MathFunctions/CMakeLists.txt``
* ``MathFunctions/MathFunctions.cxx``
Getting Started
---------------
Start with the resulting files from Exercise 1. Complete ``TODO 7`` through
``TODO 13``.
``TODO 9``.
First create a variable ``USE_MYMATH`` using the :command:`option` command
in the top-level ``CMakeLists.txt`` file. In that same file, use that option
to determine whether to build and use the ``MathFunctions`` library.
in ``MathFunctions/CMakeLists.txt``. In that same file, use that option
to pass a compile definition to the ``MathFunctions`` library.
Then, update ``tutorial.cxx`` and ``TutorialConfig.h.in`` to use
Then, update ``MathFunctions.cxx`` to redirect compilation based on
``USE_MYMATH``.
Build and Run
@@ -279,7 +283,7 @@ or ``mysqrt``?
Solution
--------
The first step is to add an option to the top-level ``CMakeLists.txt`` file.
The first step is to add an option to ``MathFunctions/CMakeLists.txt``.
This option will be displayed in the :manual:`cmake-gui <cmake-gui(1)>` and
:manual:`ccmake <ccmake(1)>` with a default value of ``ON`` that can be
changed by the user.
@@ -288,172 +292,95 @@ changed by the user.
<details><summary>TODO 7: Click to show/hide answer</summary>
.. literalinclude:: Step3/CMakeLists.txt
:caption: TODO 7: CMakeLists.txt
:name: CMakeLists.txt-option
.. literalinclude:: Step3/MathFunctions/CMakeLists.txt
:caption: TODO 7: MathFunctions/CMakeLists.txt
:name: CMakeLists.txt-option-library-level
:language: cmake
:start-after: # should we use our own math functions
:end-before: # configure a header file to pass some of the CMake settings
:end-before: if (USE_MYMATH)
.. raw:: html
</details>
Next, make building and linking the ``MathFunctions`` library
conditional.
Next, make building and linking our library with ``mysqrt`` function
conditional using this new option.
Start by creating a :command:`list` of the optional library targets for our
project. At the moment, it is just ``MathFunctions``. Let's name our list
``EXTRA_LIBS``.
Similarly, we need to make a :command:`list` for the optional includes which
we will call ``EXTRA_INCLUDES``. In this list, we will ``APPEND`` the path of
the header file needed for our library.
Next, create an :command:`if` statement which checks the value of
Create an :command:`if` statement which checks the value of
``USE_MYMATH``. Inside the :command:`if` block, put the
:command:`add_subdirectory` command from Exercise 1 with the additional
:command:`list` commands.
When ``USE_MYMATH`` is ``ON``, the lists will be generated and will be added to
our project. When ``USE_MYMATH`` is ``OFF``, the lists stay empty. With this
strategy, we allow users to toggle ``USE_MYMATH`` to manipulate what library is
used in the build.
The top-level CMakeLists.txt file will now look like the following:
:command:`target_compile_definitions` command with the compile
definition ``USE_MYMATH``.
.. raw:: html
<details><summary>TODO 8: Click to show/hide answer</summary>
.. literalinclude:: Step3/CMakeLists.txt
:caption: TODO 8: CMakeLists.txt
.. literalinclude:: Step3/MathFunctions/CMakeLists.txt
:caption: TODO 8: MathFunctions/CMakeLists.txt
:name: CMakeLists.txt-USE_MYMATH
:language: cmake
:start-after: # add the MathFunctions library
:end-before: # add the executable
:start-after: USE_MYMATH "Use tutorial provided math implementation" ON)
.. raw:: html
</details>
Now that we have these two lists, we need to update
:command:`target_link_libraries` and :command:`target_include_directories` to
use them. Changing them is fairly straightforward.
For :command:`target_link_libraries`, we replace the written out
library names with ``EXTRA_LIBS``. This looks like the following:
The corresponding changes to the source code are fairly straightforward.
In ``MathFunctions.cxx``, we make ``USE_MYMATH`` control which square root
function is used:
.. raw:: html
<details><summary>TODO 9: Click to show/hide answer</summary>
.. literalinclude:: Step3/CMakeLists.txt
:caption: TODO 9: CMakeLists.txt
:name: CMakeLists.txt-target_link_libraries-EXTRA_LIBS
:language: cmake
:start-after: add_executable(Tutorial tutorial.cxx)
:end-before: # TODO 3
.. literalinclude:: Step3/MathFunctions/MathFunctions.cxx
:caption: TODO 9: MathFunctions/MathFunctions.cxx
:name: MathFunctions-USE_MYMATH-if
:language: c++
:start-after: which square root function should we use?
:end-before: }
.. raw:: html
</details>
Then, we do the same thing with :command:`target_include_directories` and
``EXTRA_INCLUDES``.
Next, we need to include ``mysqrt.h`` if ``USE_MYMATH`` is defined.
.. raw:: html
<details><summary>TODO 10: Click to show/hide answer</summary>
.. literalinclude:: Step3/CMakeLists.txt
:caption: TODO 10 : CMakeLists.txt
:name: CMakeLists.txt-target_link_libraries-EXTRA_INCLUDES
:language: cmake
:start-after: # so that we will find TutorialConfig.h
.. literalinclude:: Step3/MathFunctions/MathFunctions.cxx
:caption: TODO 10: MathFunctions/MathFunctions.cxx
:name: MathFunctions-USE_MYMATH-if-include
:language: c++
:start-after: include <cmath>
:end-before: namespace mathfunctions
.. raw:: html
</details>
Note that this is a classic approach when dealing with many components. We
will cover the modern approach in the Step 3 of the tutorial.
The corresponding changes to the source code are fairly straightforward.
First, in ``tutorial.cxx``, we include the ``MathFunctions.h`` header if
``USE_MYMATH`` is defined.
Finally, we need to include ``cmath`` now that we are using ``std::sqrt``.
.. raw:: html
<details><summary>TODO 11: Click to show/hide answer</summary>
.. literalinclude:: Step3/tutorial.cxx
:caption: TODO 11 : tutorial.cxx
:name: tutorial.cxx-ifdef-include
:language: c++
:start-after: // should we include the MathFunctions header
:end-before: int main
.. code-block:: c++
:caption: TODO 11 : MathFunctions/MathFunctions.cxx
:name: tutorial.cxx-include_cmath
#include <cmath>
.. raw:: html
</details>
Then, in the same file, we make ``USE_MYMATH`` control which square root
function is used:
When ``USE_MYMATH`` is ``ON``, the compile definition ``USE_MYMATH`` will
be set. We can then use this compile definition to enable or disable
sections of our source code. With this strategy, we allow users to
toggle ``USE_MYMATH`` to manipulate what library is used in the build.
.. raw:: html
<details><summary>TODO 12: Click to show/hide answer</summary>
.. literalinclude:: Step3/tutorial.cxx
:caption: TODO 12 : tutorial.cxx
:name: tutorial.cxx-ifdef-const
:language: c++
:start-after: // which square root function should we use?
:end-before: std::cout << "The square root of
.. raw:: html
</details>
Since the source code now requires ``USE_MYMATH`` we can add it to
``TutorialConfig.h.in`` with the following line:
.. raw:: html
<details><summary>TODO 13: Click to show/hide answer</summary>
.. literalinclude:: Step3/TutorialConfig.h.in
:caption: TODO 13 : TutorialConfig.h.in
:name: TutorialConfig.h.in-cmakedefine
:language: c++
:lines: 4
.. raw:: html
</details>
With these changes, our library is now completely optional to whoever is
building and using it.
Bonus Question
--------------
Why is it important that we configure ``TutorialConfig.h.in``
after the option for ``USE_MYMATH``? What would happen if we inverted the two?
Answer
------
.. raw:: html
<details><summary>Click to show/hide answer</summary>
We configure after because ``TutorialConfig.h.in`` uses the value of
``USE_MYMATH``. If we configure the file before
calling :command:`option`, we won't be using the expected value of
``USE_MYMATH``.
.. raw:: html
</details>
With these changes, the ``mysqrt`` function is now completely optional to
whoever is building and using the ``MathFunctions`` library.

View File

@@ -10,6 +10,7 @@
namespace mathfunctions {
double sqrt(double x)
{
// which square root function should we use?
#ifdef USE_MYMATH
return detail::mysqrt(x);
#else

View File

@@ -10,49 +10,22 @@ To accomplish this we need to add :variable:`BUILD_SHARED_LIBS` to the
top-level ``CMakeLists.txt``. We use the :command:`option` command as it allows
users to optionally select if the value should be ``ON`` or ``OFF``.
Next we are going to refactor ``MathFunctions`` to become a real library that
encapsulates using ``mysqrt`` or ``sqrt``, instead of requiring the calling
code to do this logic. This will also mean that ``USE_MYMATH`` will not control
building ``MathFunctions``, but instead will control the behavior of this
library.
The first step is to update the starting section of the top-level
``CMakeLists.txt`` to look like:
.. literalinclude:: Step11/CMakeLists.txt
:caption: CMakeLists.txt
:name: CMakeLists.txt-option-BUILD_SHARED_LIBS
:language: cmake
:end-before: # add the binary tree
:start-after: set(CMAKE_RUNTIME_OUTPUT_DIRECTORY
:end-before: # configure a header file to pass the version number only
Now that we have made ``MathFunctions`` always be used, we will need to update
the logic of that library. So, in ``MathFunctions/CMakeLists.txt`` we need to
create a SqrtLibrary that will conditionally be built and installed when
``USE_MYMATH`` is enabled. Now, since this is a tutorial, we are going to
explicitly require that SqrtLibrary is built statically.
Next, we need to specify output directories for our static and shared
libraries.
The end result is that ``MathFunctions/CMakeLists.txt`` should look like:
.. literalinclude:: Step11/MathFunctions/CMakeLists.txt
:caption: MathFunctions/CMakeLists.txt
:name: MathFunctions/CMakeLists.txt-add_library-STATIC
.. literalinclude:: Step11/CMakeLists.txt
:caption: CMakeLists.txt
:name: CMakeLists.txt-cmake-output-directories
:language: cmake
:lines: 1-36,42-
Next, update ``MathFunctions/mysqrt.cxx`` to use the ``mathfunctions`` and
``detail`` namespaces:
.. literalinclude:: Step11/MathFunctions/mysqrt.cxx
:caption: MathFunctions/mysqrt.cxx
:name: MathFunctions/mysqrt.cxx-namespace
:language: c++
We also need to make some changes in ``tutorial.cxx``, so that it no longer
uses ``USE_MYMATH``:
#. Always include ``MathFunctions.h``
#. Always use ``mathfunctions::sqrt``
#. Don't include ``cmath``
:start-after: # we don't need to tinker with the path to run the executable
:end-before: # configure a header file to pass the version number only
Finally, update ``MathFunctions/MathFunctions.h`` to use dll export defines:

View File

@@ -16,22 +16,15 @@ target_compile_options(tutorial_compiler_flags INTERFACE
"$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>"
)
# should we use our own math functions
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 a header file to pass the version number only
configure_file(TutorialConfig.h.in TutorialConfig.h)
# add the MathFunctions library
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
endif()
add_subdirectory(MathFunctions)
# add the executable
add_executable(Tutorial tutorial.cxx)
target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags)
target_link_libraries(Tutorial PUBLIC MathFunctions tutorial_compiler_flags)
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h

View File

@@ -1,32 +1,51 @@
# first we add the executable that generates the table
add_executable(MakeTable MakeTable.cxx)
# add the command to generate the source code
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
DEPENDS MakeTable
)
# add the main library
add_library(MathFunctions
mysqrt.cxx
${CMAKE_CURRENT_BINARY_DIR}/Table.h
)
# add the library that runs
add_library(MathFunctions MathFunctions.cxx)
# state that anybody linking to us needs to include the current source dir
# to find MathFunctions.h, while we don't.
# state that we depend on our binary dir to find Table.h
target_include_directories(MathFunctions
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
)
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
)
# link our compiler flags interface library
target_link_libraries(MathFunctions tutorial_compiler_flags)
# should we use our own math functions
option(USE_MYMATH "Use tutorial provided math implementation" ON)
if(USE_MYMATH)
target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")
# first we add the executable that generates the table
add_executable(MakeTable MakeTable.cxx)
target_link_libraries(MakeTable PRIVATE tutorial_compiler_flags)
# add the command to generate the source code
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
DEPENDS MakeTable
)
# library that just does sqrt
add_library(SqrtLibrary STATIC
mysqrt.cxx
${CMAKE_CURRENT_BINARY_DIR}/Table.h
)
# state that we depend on our binary dir to find Table.h
target_include_directories(SqrtLibrary PRIVATE
${CMAKE_CURRENT_BINARY_DIR}
)
target_link_libraries(SqrtLibrary PUBLIC tutorial_compiler_flags)
target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
endif()
target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)
# install libs
set(installable_libs MathFunctions tutorial_compiler_flags)
if(TARGET SqrtLibrary)
list(APPEND installable_libs SqrtLibrary)
endif()
install(TARGETS ${installable_libs} DESTINATION lib)
# install include headers
install(FILES MathFunctions.h DESTINATION include)

View File

@@ -10,6 +10,7 @@
namespace mathfunctions {
double sqrt(double x)
{
// which square root function should we use?
#ifdef USE_MYMATH
return detail::mysqrt(x);
#else

View File

@@ -1 +1,3 @@
double mysqrt(double x);
namespace mathfunctions {
double sqrt(double x);
}

View File

@@ -5,6 +5,8 @@
// include the generated table
#include "Table.h"
namespace mathfunctions {
namespace detail {
// a hack square root calculation using simple operations
double mysqrt(double x)
{
@@ -31,3 +33,5 @@ double mysqrt(double x)
return result;
}
}
}

View File

@@ -1,4 +1,3 @@
// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
#cmakedefine USE_MYMATH

View File

@@ -1,15 +1,11 @@
// A simple program that computes the square root of a number
#include <cmath>
#include <iostream>
#include <sstream>
#include <string>
#include "MathFunctions.h"
#include "TutorialConfig.h"
// should we include the MathFunctions header?
#ifdef USE_MYMATH
# include "MathFunctions.h"
#endif
int main(int argc, char* argv[])
{
if (argc < 2) {
@@ -23,12 +19,7 @@ int main(int argc, char* argv[])
// convert input to double
const double inputValue = std::stod(argv[1]);
// which square root function should we use?
#ifdef USE_MYMATH
const double outputValue = mysqrt(inputValue);
#else
const double outputValue = sqrt(inputValue);
#endif
const double outputValue = mathfunctions::sqrt(inputValue);
std::cout << "The square root of " << inputValue << " is " << outputValue
<< std::endl;

View File

@@ -10,6 +10,7 @@
namespace mathfunctions {
double sqrt(double x)
{
// which square root function should we use?
#ifdef USE_MYMATH
return detail::mysqrt(x);
#else

View File

@@ -10,6 +10,7 @@
namespace mathfunctions {
double sqrt(double x)
{
// which square root function should we use?
#ifdef USE_MYMATH
return detail::mysqrt(x);
#else

View File

@@ -7,36 +7,20 @@ project(Tutorial VERSION 1.0)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# TODO 7: Create a variable USE_MYMATH using option and set default to ON
# configure a header file to pass some of the CMake settings
# to the source code
configure_file(TutorialConfig.h.in TutorialConfig.h)
# TODO 8: Use list() and APPEND to create a list of optional libraries
# called EXTRA_LIBS and a list of optional include directories called
# EXTRA_INCLUDES. Add the MathFunctions library and source directory to
# the appropriate lists.
#
# Only call add_subdirectory and only add MathFunctions specific values
# to EXTRA_LIBS and EXTRA_INCLUDES if USE_MYMATH is true.
# TODO 2: Use add_subdirectory() to add MathFunctions to this project
# add the executable
add_executable(Tutorial tutorial.cxx)
# TODO 9: Use EXTRA_LIBS instead of the MathFunctions specific values
# in target_link_libraries.
# TODO 3: Use target_link_libraries to link the library to our executable
# TODO 4: Add MathFunctions to Tutorial's target_include_directories()
# Hint: ${PROJECT_SOURCE_DIR} is a path to the project source. AKA This folder!
# TODO 10: Use EXTRA_INCLUDES instead of the MathFunctions specific values
# in target_include_directories.
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
target_include_directories(Tutorial PUBLIC

View File

@@ -1,2 +1,7 @@
# TODO 1: Add a library called MathFunctions
# Hint: You will need the add_library command
# TODO 7: Create a variable USE_MYMATH using option and set default to ON
# TODO 8: If USE_MYMATH is ON, use target_compile_definitions to pass
# USE_MYMATH as a precompiled definition to our source files

View File

@@ -0,0 +1,15 @@
#include "MathFunctions.h"
// TODO 11: include cmath
// TODO 10: Wrap the mysqrt include in a precompiled ifdef based on USE_MYMATH
#include "mysqrt.h"
namespace mathfunctions {
double sqrt(double x)
{
// TODO 9: If USE_MYMATH is defined, use detail::mysqrt.
// Otherwise, use std::sqrt.
return detail::mysqrt(x);
}
}

View File

@@ -1 +1,5 @@
double mysqrt(double x);
#pragma once
namespace mathfunctions {
double sqrt(double x);
}

View File

@@ -1,5 +1,9 @@
#include "mysqrt.h"
#include <iostream>
namespace mathfunctions {
namespace detail {
// a hack square root calculation using simple operations
double mysqrt(double x)
{
@@ -20,3 +24,5 @@ double mysqrt(double x)
}
return result;
}
}
}

View File

@@ -0,0 +1,7 @@
#pragma once
namespace mathfunctions {
namespace detail {
double mysqrt(double x);
}
}

View File

@@ -1,5 +1,3 @@
// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
// TODO 13: use cmakedefine to define USE_MYMATH

View File

@@ -3,11 +3,8 @@
#include <iostream>
#include <string>
#include "TutorialConfig.h"
// TODO 11: Only include MathFunctions if USE_MYMATH is defined
// TODO 5: Include MathFunctions.h
#include "TutorialConfig.h"
int main(int argc, char* argv[])
{
@@ -22,9 +19,7 @@ int main(int argc, char* argv[])
// convert input to double
const double inputValue = std::stod(argv[1]);
// TODO 12: Use mysqrt if USE_MYMATH is defined and sqrt otherwise
// TODO 6: Replace sqrt with mysqrt
// TODO 6: Replace sqrt with mathfunctions::sqrt
// calculate square root
const double outputValue = sqrt(inputValue);

View File

@@ -7,9 +7,6 @@ project(Tutorial VERSION 1.0)
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)
# configure a header file to pass some of the CMake settings
# to the source code
configure_file(TutorialConfig.h.in TutorialConfig.h)
@@ -17,16 +14,13 @@ configure_file(TutorialConfig.h.in TutorialConfig.h)
# TODO 2: Remove EXTRA_INCLUDES list
# add the MathFunctions library
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")
endif()
add_subdirectory(MathFunctions)
list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")
# add the executable
add_executable(Tutorial tutorial.cxx)
target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})
target_link_libraries(Tutorial PUBLIC MathFunctions)
# TODO 3: Remove use of EXTRA_INCLUDES

View File

@@ -1,5 +1,11 @@
add_library(MathFunctions mysqrt.cxx)
add_library(MathFunctions MathFunctions.cxx mysqrt.cxx)
# TODO 1: State that anybody linking to MathFunctions needs to include the
# current source directory, while MathFunctions itself doesn't.
# Hint: Use target_include_directories with the INTERFACE keyword
# should we use our own math functions
option(USE_MYMATH "Use tutorial provided math implementation" ON)
if (USE_MYMATH)
target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")
endif()

View File

@@ -0,0 +1,19 @@
#include "MathFunctions.h"
#include <cmath>
#ifdef USE_MYMATH
# include "mysqrt.h"
#endif
namespace mathfunctions {
double sqrt(double x)
{
// which square root function should we use?
#ifdef USE_MYMATH
return detail::mysqrt(x);
#else
return std::sqrt(x);
#endif
}
}

View File

@@ -1 +1,5 @@
double mysqrt(double x);
#pragma once
namespace mathfunctions {
double sqrt(double x);
}

View File

@@ -1,7 +1,9 @@
#include "mysqrt.h"
#include <iostream>
#include "MathFunctions.h"
namespace mathfunctions {
namespace detail {
// a hack square root calculation using simple operations
double mysqrt(double x)
{
@@ -22,3 +24,5 @@ double mysqrt(double x)
}
return result;
}
}
}

View File

@@ -0,0 +1,7 @@
#pragma once
namespace mathfunctions {
namespace detail {
double mysqrt(double x);
}
}

View File

@@ -1,4 +1,3 @@
// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
#cmakedefine USE_MYMATH

View File

@@ -3,13 +3,9 @@
#include <iostream>
#include <string>
#include "MathFunctions.h"
#include "TutorialConfig.h"
// should we include the MathFunctions header?
#ifdef USE_MYMATH
# include "MathFunctions.h"
#endif
int main(int argc, char* argv[])
{
if (argc < 2) {
@@ -23,12 +19,7 @@ int main(int argc, char* argv[])
// convert input to double
const double inputValue = std::stod(argv[1]);
// which square root function should we use?
#ifdef USE_MYMATH
const double outputValue = mysqrt(inputValue);
#else
const double outputValue = sqrt(inputValue);
#endif
const double outputValue = mathfunctions::sqrt(inputValue);
std::cout << "The square root of " << inputValue << " is " << outputValue
<< std::endl;

View File

@@ -31,25 +31,19 @@ set(CMAKE_CXX_STANDARD_REQUIRED True)
# build-tree
# Hint: Use BUILD_INTERFACE
# should we use our own math functions
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(TutorialConfig.h.in TutorialConfig.h)
# add the MathFunctions library
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
endif()
add_subdirectory(MathFunctions)
# add the executable
add_executable(Tutorial tutorial.cxx)
# TODO 2: Link to tutorial_compiler_flags
target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})
target_link_libraries(Tutorial PUBLIC MathFunctions)
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h

View File

@@ -1,9 +1,15 @@
add_library(MathFunctions mysqrt.cxx)
add_library(MathFunctions MathFunctions.cxx mysqrt.cxx)
# state that anybody linking to us needs to include the current source dir
# to find MathFunctions.h, while we don't.
target_include_directories(MathFunctions
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
)
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
)
# should we use our own math functions
option(USE_MYMATH "Use tutorial provided math implementation" ON)
if (USE_MYMATH)
target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")
endif()
# TODO 3: Link to tutorial_compiler_flags

View File

@@ -0,0 +1,19 @@
#include "MathFunctions.h"
#include <cmath>
#ifdef USE_MYMATH
# include "mysqrt.h"
#endif
namespace mathfunctions {
double sqrt(double x)
{
// which square root function should we use?
#ifdef USE_MYMATH
return detail::mysqrt(x);
#else
return std::sqrt(x);
#endif
}
}

View File

@@ -1 +1,5 @@
double mysqrt(double x);
#pragma once
namespace mathfunctions {
double sqrt(double x);
}

View File

@@ -1,7 +1,9 @@
#include "mysqrt.h"
#include <iostream>
#include "MathFunctions.h"
namespace mathfunctions {
namespace detail {
// a hack square root calculation using simple operations
double mysqrt(double x)
{
@@ -22,3 +24,5 @@ double mysqrt(double x)
}
return result;
}
}
}

View File

@@ -0,0 +1,7 @@
#pragma once
namespace mathfunctions {
namespace detail {
double mysqrt(double x);
}
}

View File

@@ -1,4 +1,3 @@
// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
#cmakedefine USE_MYMATH

View File

@@ -3,13 +3,9 @@
#include <iostream>
#include <string>
#include "MathFunctions.h"
#include "TutorialConfig.h"
// should we include the MathFunctions header?
#ifdef USE_MYMATH
# include "MathFunctions.h"
#endif
int main(int argc, char* argv[])
{
if (argc < 2) {
@@ -23,12 +19,7 @@ int main(int argc, char* argv[])
// convert input to double
const double inputValue = std::stod(argv[1]);
// which square root function should we use?
#ifdef USE_MYMATH
const double outputValue = mysqrt(inputValue);
#else
const double outputValue = sqrt(inputValue);
#endif
const double outputValue = mathfunctions::sqrt(inputValue);
std::cout << "The square root of " << inputValue << " is " << outputValue
<< std::endl;

View File

@@ -16,22 +16,17 @@ target_compile_options(tutorial_compiler_flags INTERFACE
"$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>"
)
# should we use our own math functions
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(TutorialConfig.h.in TutorialConfig.h)
# add the MathFunctions library
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
endif()
add_subdirectory(MathFunctions)
# add the executable
add_executable(Tutorial tutorial.cxx)
target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags)
target_link_libraries(Tutorial PUBLIC MathFunctions tutorial_compiler_flags)
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h

View File

@@ -1,13 +1,19 @@
add_library(MathFunctions mysqrt.cxx)
add_library(MathFunctions MathFunctions.cxx mysqrt.cxx)
# state that anybody linking to us needs to include the current source dir
# to find MathFunctions.h, while we don't.
target_include_directories(MathFunctions
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
)
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
)
# should we use our own math functions
option(USE_MYMATH "Use tutorial provided math implementation" ON)
if (USE_MYMATH)
target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")
endif()
# link our compiler flags interface library
target_link_libraries(MathFunctions tutorial_compiler_flags)
target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)
# TODO 1: Create a variable called installable_libs that is a list of all
# libraries we want to install (e.g. MathFunctions and tutorial_compiler_flags)

View File

@@ -0,0 +1,19 @@
#include "MathFunctions.h"
#include <cmath>
#ifdef USE_MYMATH
# include "mysqrt.h"
#endif
namespace mathfunctions {
double sqrt(double x)
{
// which square root function should we use?
#ifdef USE_MYMATH
return detail::mysqrt(x);
#else
return std::sqrt(x);
#endif
}
}

View File

@@ -1 +1,5 @@
double mysqrt(double x);
#pragma once
namespace mathfunctions {
double sqrt(double x);
}

View File

@@ -1,7 +1,9 @@
#include "mysqrt.h"
#include <iostream>
#include "MathFunctions.h"
namespace mathfunctions {
namespace detail {
// a hack square root calculation using simple operations
double mysqrt(double x)
{
@@ -22,3 +24,5 @@ double mysqrt(double x)
}
return result;
}
}
}

View File

@@ -0,0 +1,7 @@
#pragma once
namespace mathfunctions {
namespace detail {
double mysqrt(double x);
}
}

View File

@@ -1,4 +1,3 @@
// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
#cmakedefine USE_MYMATH

View File

@@ -3,13 +3,9 @@
#include <iostream>
#include <string>
#include "MathFunctions.h"
#include "TutorialConfig.h"
// should we include the MathFunctions header?
#ifdef USE_MYMATH
# include "MathFunctions.h"
#endif
int main(int argc, char* argv[])
{
if (argc < 2) {
@@ -23,12 +19,7 @@ int main(int argc, char* argv[])
// convert input to double
const double inputValue = std::stod(argv[1]);
// which square root function should we use?
#ifdef USE_MYMATH
const double outputValue = mysqrt(inputValue);
#else
const double outputValue = sqrt(inputValue);
#endif
const double outputValue = mathfunctions::sqrt(inputValue);
std::cout << "The square root of " << inputValue << " is " << outputValue
<< std::endl;

View File

@@ -16,22 +16,17 @@ target_compile_options(tutorial_compiler_flags INTERFACE
"$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>"
)
# should we use our own math functions
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(TutorialConfig.h.in TutorialConfig.h)
# add the MathFunctions library
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
endif()
add_subdirectory(MathFunctions)
# add the executable
add_executable(Tutorial tutorial.cxx)
target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags)
target_link_libraries(Tutorial PUBLIC MathFunctions tutorial_compiler_flags)
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h

View File

@@ -1,13 +1,19 @@
add_library(MathFunctions mysqrt.cxx)
add_library(MathFunctions MathFunctions.cxx mysqrt.cxx)
# state that anybody linking to us needs to include the current source dir
# to find MathFunctions.h, while we don't.
target_include_directories(MathFunctions
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
)
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
)
# should we use our own math functions
option(USE_MYMATH "Use tutorial provided math implementation" ON)
if (USE_MYMATH)
target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")
endif()
# link our compiler flags interface library
target_link_libraries(MathFunctions tutorial_compiler_flags)
target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)
# install libs
set(installable_libs MathFunctions tutorial_compiler_flags)

View File

@@ -0,0 +1,19 @@
#include "MathFunctions.h"
#include <cmath>
#ifdef USE_MYMATH
# include "mysqrt.h"
#endif
namespace mathfunctions {
double sqrt(double x)
{
// which square root function should we use?
#ifdef USE_MYMATH
return detail::mysqrt(x);
#else
return std::sqrt(x);
#endif
}
}

View File

@@ -1 +1,5 @@
double mysqrt(double x);
#pragma once
namespace mathfunctions {
double sqrt(double x);
}

View File

@@ -1,7 +1,9 @@
#include "mysqrt.h"
#include <iostream>
#include "MathFunctions.h"
namespace mathfunctions {
namespace detail {
// a hack square root calculation using simple operations
double mysqrt(double x)
{
@@ -22,3 +24,5 @@ double mysqrt(double x)
}
return result;
}
}
}

View File

@@ -0,0 +1,7 @@
#pragma once
namespace mathfunctions {
namespace detail {
double mysqrt(double x);
}
}

View File

@@ -1,4 +1,3 @@
// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
#cmakedefine USE_MYMATH

View File

@@ -3,13 +3,9 @@
#include <iostream>
#include <string>
#include "MathFunctions.h"
#include "TutorialConfig.h"
// should we include the MathFunctions header?
#ifdef USE_MYMATH
# include "MathFunctions.h"
#endif
int main(int argc, char* argv[])
{
if (argc < 2) {
@@ -23,12 +19,7 @@ int main(int argc, char* argv[])
// convert input to double
const double inputValue = std::stod(argv[1]);
// which square root function should we use?
#ifdef USE_MYMATH
const double outputValue = mysqrt(inputValue);
#else
const double outputValue = sqrt(inputValue);
#endif
const double outputValue = mathfunctions::sqrt(inputValue);
std::cout << "The square root of " << inputValue << " is " << outputValue
<< std::endl;

View File

@@ -16,22 +16,17 @@ target_compile_options(tutorial_compiler_flags INTERFACE
"$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>"
)
# should we use our own math functions
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(TutorialConfig.h.in TutorialConfig.h)
# add the MathFunctions library
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
endif()
add_subdirectory(MathFunctions)
# add the executable
add_executable(Tutorial tutorial.cxx)
target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags)
target_link_libraries(Tutorial PUBLIC MathFunctions tutorial_compiler_flags)
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h

View File

@@ -1,33 +1,39 @@
add_library(MathFunctions mysqrt.cxx)
add_library(MathFunctions MathFunctions.cxx mysqrt.cxx)
# state that anybody linking to us needs to include the current source dir
# to find MathFunctions.h, while we don't.
target_include_directories(MathFunctions
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
)
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
)
# should we use our own math functions
option(USE_MYMATH "Use tutorial provided math implementation" ON)
if (USE_MYMATH)
target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")
# TODO 1: Include CheckCXXSourceCompiles
# TODO 2: Use check_cxx_source_compiles with simple C++ code to verify
# availability of:
# * std::log
# * std::exp
# Store the results in HAVE_LOG and HAVE_EXP respectively.
# Hint: Sample C++ code which uses log:
# #include <cmath>
# int main() {
# std::log(1.0);
# return 0;
# }
# TODO 3: Conditionally on HAVE_LOG and HAVE_EXP, add private compile
# definitions "HAVE_LOG" and "HAVE_EXP" to the MathFunctions target.
# Hint: Use target_compile_definitions()
endif()
# link our compiler flags interface library
target_link_libraries(MathFunctions tutorial_compiler_flags)
# TODO 1: Include CheckCXXSourceCompiles
# TODO 2: Use check_cxx_source_compiles with simple C++ code to verify
# availability of:
# * std::log
# * std::exp
# Store the results in HAVE_LOG and HAVE_EXP respectively.
# Hint: Sample C++ code which uses log:
# #include <cmath>
# int main() {
# std::log(1.0);
# return 0;
# }
# TODO 3: Conditionally on HAVE_LOG and HAVE_EXP, add private compile
# definitions "HAVE_LOG" and "HAVE_EXP" to the MathFunctions target.
#Hint: Use target_compile_definitions()
target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)
# install libs
set(installable_libs MathFunctions tutorial_compiler_flags)

View File

@@ -0,0 +1,19 @@
#include "MathFunctions.h"
#include <cmath>
#ifdef USE_MYMATH
# include "mysqrt.h"
#endif
namespace mathfunctions {
double sqrt(double x)
{
// which square root function should we use?
#ifdef USE_MYMATH
return detail::mysqrt(x);
#else
return std::sqrt(x);
#endif
}
}

View File

@@ -1 +1,5 @@
double mysqrt(double x);
#pragma once
namespace mathfunctions {
double sqrt(double x);
}

View File

@@ -1,8 +1,9 @@
#include "mysqrt.h"
#include <iostream>
// TODO 4: include cmath
#include "MathFunctions.h"
namespace mathfunctions {
namespace detail {
// a hack square root calculation using simple operations
double mysqrt(double x)
{
@@ -32,3 +33,5 @@ double mysqrt(double x)
return result;
}
}
}

View File

@@ -0,0 +1,7 @@
#pragma once
namespace mathfunctions {
namespace detail {
double mysqrt(double x);
}
}

View File

@@ -1,4 +1,3 @@
// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
#cmakedefine USE_MYMATH

View File

@@ -3,13 +3,9 @@
#include <iostream>
#include <string>
#include "MathFunctions.h"
#include "TutorialConfig.h"
// should we include the MathFunctions header?
#ifdef USE_MYMATH
# include "MathFunctions.h"
#endif
int main(int argc, char* argv[])
{
if (argc < 2) {
@@ -23,12 +19,7 @@ int main(int argc, char* argv[])
// convert input to double
const double inputValue = std::stod(argv[1]);
// which square root function should we use?
#ifdef USE_MYMATH
const double outputValue = mysqrt(inputValue);
#else
const double outputValue = sqrt(inputValue);
#endif
const double outputValue = mathfunctions::sqrt(inputValue);
std::cout << "The square root of " << inputValue << " is " << outputValue
<< std::endl;

View File

@@ -16,23 +16,17 @@ target_compile_options(tutorial_compiler_flags INTERFACE
"$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>"
)
# should we use our own math functions
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(TutorialConfig.h.in TutorialConfig.h)
# add the MathFunctions library
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
endif()
add_subdirectory(MathFunctions)
# add the executable
add_executable(Tutorial tutorial.cxx)
target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags)
target_link_libraries(Tutorial PUBLIC MathFunctions tutorial_compiler_flags)
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h

View File

@@ -1,36 +1,43 @@
add_library(MathFunctions mysqrt.cxx)
add_library(MathFunctions MathFunctions.cxx mysqrt.cxx)
# should we use our own math functions
option(USE_MYMATH "Use tutorial provided math implementation" ON)
if (USE_MYMATH)
target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")
# does this system provide the log and exp functions?
include(CheckCXXSourceCompiles)
check_cxx_source_compiles("
#include <cmath>
int main() {
std::log(1.0);
return 0;
}
" HAVE_LOG)
check_cxx_source_compiles("
#include <cmath>
int main() {
std::exp(1.0);
return 0;
}
" HAVE_EXP)
# add compile definitions
if(HAVE_LOG AND HAVE_EXP)
target_compile_definitions(MathFunctions
PRIVATE "HAVE_LOG" "HAVE_EXP"
)
endif()
endif()
# state that anybody linking to us needs to include the current source dir
# to find MathFunctions.h, while we don't.
target_include_directories(MathFunctions
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
)
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
)
# link our compiler flags interface library
target_link_libraries(MathFunctions tutorial_compiler_flags)
# does this system provide the log and exp functions?
include(CheckCXXSourceCompiles)
check_cxx_source_compiles("
#include <cmath>
int main() {
std::log(1.0);
return 0;
}
" HAVE_LOG)
check_cxx_source_compiles("
#include <cmath>
int main() {
std::exp(1.0);
return 0;
}
" HAVE_EXP)
# add compile definitions
if(HAVE_LOG AND HAVE_EXP)
target_compile_definitions(MathFunctions
PRIVATE "HAVE_LOG" "HAVE_EXP")
endif()
target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)
# install libs
set(installable_libs MathFunctions tutorial_compiler_flags)

View File

@@ -0,0 +1,19 @@
#include "MathFunctions.h"
#include <cmath>
#ifdef USE_MYMATH
# include "mysqrt.h"
#endif
namespace mathfunctions {
double sqrt(double x)
{
// which square root function should we use?
#ifdef USE_MYMATH
return detail::mysqrt(x);
#else
return std::sqrt(x);
#endif
}
}

View File

@@ -1 +1,5 @@
double mysqrt(double x);
#pragma once
namespace mathfunctions {
double sqrt(double x);
}

View File

@@ -1,8 +1,10 @@
#include "mysqrt.h"
#include <cmath>
#include <iostream>
#include "MathFunctions.h"
namespace mathfunctions {
namespace detail {
// a hack square root calculation using simple operations
double mysqrt(double x)
{
@@ -30,3 +32,5 @@ double mysqrt(double x)
#endif
return result;
}
}
}

View File

@@ -0,0 +1,7 @@
#pragma once
namespace mathfunctions {
namespace detail {
double mysqrt(double x);
}
}

View File

@@ -1,4 +1,3 @@
// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
#cmakedefine USE_MYMATH

View File

@@ -3,13 +3,9 @@
#include <iostream>
#include <string>
#include "MathFunctions.h"
#include "TutorialConfig.h"
// should we include the MathFunctions header?
#ifdef USE_MYMATH
# include "MathFunctions.h"
#endif
int main(int argc, char* argv[])
{
if (argc < 2) {
@@ -23,12 +19,7 @@ int main(int argc, char* argv[])
// convert input to double
const double inputValue = std::stod(argv[1]);
// which square root function should we use?
#ifdef USE_MYMATH
const double outputValue = mysqrt(inputValue);
#else
const double outputValue = sqrt(inputValue);
#endif
const double outputValue = mathfunctions::sqrt(inputValue);
std::cout << "The square root of " << inputValue << " is " << outputValue
<< std::endl;

View File

@@ -16,22 +16,17 @@ target_compile_options(tutorial_compiler_flags INTERFACE
"$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>"
)
# should we use our own math functions
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(TutorialConfig.h.in TutorialConfig.h)
# add the MathFunctions library
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
endif()
add_subdirectory(MathFunctions)
# add the executable
add_executable(Tutorial tutorial.cxx)
target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags)
target_link_libraries(Tutorial PUBLIC MathFunctions tutorial_compiler_flags)
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h

View File

@@ -1,34 +1,49 @@
# first we add the executable that generates the table
add_executable(MakeTable MakeTable.cxx)
# add the command to generate the source code
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
DEPENDS MakeTable
)
# add the main library
add_library(MathFunctions
mysqrt.cxx
${CMAKE_CURRENT_BINARY_DIR}/Table.h
)
add_library(MathFunctions MathFunctions.cxx)
# state that anybody linking to us needs to include the current source dir
# to find MathFunctions.h, while we don't.
# state that we depend on Tutorial_BINARY_DIR but consumers don't, as the
# TutorialConfig.h include is an implementation detail
# state that we depend on our binary dir to find Table.h
target_include_directories(MathFunctions
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
)
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
)
# link our compiler flags interface library
target_link_libraries(MathFunctions tutorial_compiler_flags)
# should we use our own math functions
option(USE_MYMATH "Use tutorial provided math implementation" ON)
if (USE_MYMATH)
target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")
# first we add the executable that generates the table
add_executable(MakeTable MakeTable.cxx)
target_link_libraries(MakeTable PRIVATE tutorial_compiler_flags)
# add the command to generate the source code
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
DEPENDS MakeTable
)
# library that just does sqrt
add_library(SqrtLibrary STATIC
mysqrt.cxx
${CMAKE_CURRENT_BINARY_DIR}/Table.h
)
# state that we depend on our binary dir to find Table.h
target_include_directories(SqrtLibrary PRIVATE
${CMAKE_CURRENT_BINARY_DIR}
)
target_link_libraries(SqrtLibrary PUBLIC tutorial_compiler_flags)
target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
endif()
target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)
# install libs
set(installable_libs MathFunctions tutorial_compiler_flags)
if(TARGET SqrtLibrary)
list(APPEND installable_libs SqrtLibrary)
endif()
install(TARGETS ${installable_libs} DESTINATION lib)
# install include headers
install(FILES MathFunctions.h DESTINATION include)

View File

@@ -0,0 +1,19 @@
#include "MathFunctions.h"
#include <cmath>
#ifdef USE_MYMATH
# include "mysqrt.h"
#endif
namespace mathfunctions {
double sqrt(double x)
{
// which square root function should we use?
#ifdef USE_MYMATH
return detail::mysqrt(x);
#else
return std::sqrt(x);
#endif
}
}

View File

@@ -1 +1,5 @@
double mysqrt(double x);
#pragma once
namespace mathfunctions {
double sqrt(double x);
}

View File

@@ -1,10 +1,12 @@
#include <iostream>
#include "mysqrt.h"
#include "MathFunctions.h"
#include <iostream>
// include the generated table
#include "Table.h"
namespace mathfunctions {
namespace detail {
// a hack square root calculation using simple operations
double mysqrt(double x)
{
@@ -31,3 +33,5 @@ double mysqrt(double x)
return result;
}
}
}

View File

@@ -0,0 +1,7 @@
#pragma once
namespace mathfunctions {
namespace detail {
double mysqrt(double x);
}
}

View File

@@ -1,4 +1,3 @@
// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
#cmakedefine USE_MYMATH

View File

@@ -3,13 +3,9 @@
#include <iostream>
#include <string>
#include "MathFunctions.h"
#include "TutorialConfig.h"
// should we include the MathFunctions header?
#ifdef USE_MYMATH
# include "MathFunctions.h"
#endif
int main(int argc, char* argv[])
{
if (argc < 2) {
@@ -23,12 +19,7 @@ int main(int argc, char* argv[])
// convert input to double
const double inputValue = std::stod(argv[1]);
// which square root function should we use?
#ifdef USE_MYMATH
const double outputValue = mysqrt(inputValue);
#else
const double outputValue = sqrt(inputValue);
#endif
const double outputValue = mathfunctions::sqrt(inputValue);
std::cout << "The square root of " << inputValue << " is " << outputValue
<< std::endl;