summaryrefslogtreecommitdiff
path: root/Tests/Tutorial/Step9/directions.txt
diff options
context:
space:
mode:
Diffstat (limited to 'Tests/Tutorial/Step9/directions.txt')
-rw-r--r--Tests/Tutorial/Step9/directions.txt166
1 files changed, 166 insertions, 0 deletions
diff --git a/Tests/Tutorial/Step9/directions.txt b/Tests/Tutorial/Step9/directions.txt
new file mode 100644
index 000000000..8771637d2
--- /dev/null
+++ b/Tests/Tutorial/Step9/directions.txt
@@ -0,0 +1,166 @@
+# Mixing Static and Shared #
+
+In this section we will show how by using the BUILD_SHARED_LIBS variable we can
+control the default behavior of add_library, and allow control over how
+libraries without an explicit type ( STATIC/SHARED/MODULE/OBJECT ) are built.
+
+To accomplish this we need to add BUILD_SHARED_LIBS to the top level
+CMakeLists.txt. We use the 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
+MathFuctions, 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:
+
+ cmake_minimum_required(VERSION 3.3)
+ project(Tutorial)
+
+ # 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}")
+ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
+
+ set(CMAKE_CXX_STANDARD 11)
+ set(CMAKE_CXX_STANDARD_REQUIRED True)
+
+ option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
+
+ # the version number.
+ set(Tutorial_VERSION_MAJOR 1)
+ set(Tutorial_VERSION_MINOR 0)
+
+ # configure a header file to pass the version number only
+ configure_file(
+ "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
+ "${PROJECT_BINARY_DIR}/TutorialConfig.h"
+ )
+
+ # add the MathFunctions library
+ add_subdirectory(MathFunctions)
+
+ # add the executable
+ add_executable(Tutorial tutorial.cxx)
+ target_link_libraries(Tutorial PUBLIC MathFunctions)
+
+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 when USE_MYMATH is
+enabled. Now, since this is a tutorial, we are going to explicitly require
+that SqrtLibrary is built statically.
+
+The end result is that MathFunctions/CMakeLists.txt should look like:
+
+ # 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.
+ target_include_directories(MathFunctions
+ INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
+ )
+
+ # should we use our own math functions
+ option(USE_MYMATH "Use tutorial provided math implementation" ON)
+ if(USE_MYMATH)
+
+ # does this system provide the log and exp functions?
+ include(CheckSymbolExists)
+ set(CMAKE_REQUIRED_LIBRARIES "m")
+ check_symbol_exists(log "math.h" HAVE_LOG)
+ check_symbol_exists(exp "math.h" HAVE_EXP)
+
+ # 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
+ )
+
+ # 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_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")
+ if(HAVE_LOG AND HAVE_EXP)
+ target_compile_definitions(SqrtLibrary
+ PRIVATE "HAVE_LOG" "HAVE_EXP")
+ endif()
+
+ target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
+ endif()
+
+ # define the symbol stating we are using the declspec(dllexport) when
+ # building on windows
+ target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH")
+
+ install(TARGETS MathFunctions DESTINATION lib)
+ install(FILES MathFunctions.h DESTINATION include)
+
+Next, update MathFunctions/mysqrt.cxx to use the mathfunctions and detail namespaces:
+
+ #include <iostream>
+ #include "MathFunctions.h"
+
+ // include the generated table
+ #include "Table.h"
+
+ #include <cmath>
+
+ namespace mathfunctions {
+ namespace detail {
+ // a hack square root calculation using simple operations
+ double mysqrt(double x)
+ {
+ ...
+
+ return result;
+ }
+ }
+ }
+
+We also need to make some changes in tutorial.cxx, so that it no longer uses USE_MYMATH:
+1. Always include MathFunctions.h
+2. Always use mathfunctions::sqrt
+
+Finally, update MathFunctions/MathFunctions.h to use dll export defines:
+
+ #if defined(_WIN32)
+ #if defined(EXPORTING_MYMATH)
+ #define DECLSPEC __declspec(dllexport)
+ #else
+ #define DECLSPEC __declspec(dllimport)
+ #endif
+ #else //non windows
+ #define DECLSPEC
+ #endif
+
+ namespace mathfunctions
+ {
+ double DECLSPEC sqrt(double x);
+ }
+
+At this point, if you build everything, you will notice that linking fails
+as we are combining a static library without position enabled code with a
+library that has position enabled code. This solution to this is to explicitly
+set the POSITION_INDEPENDENT_CODE target property of SqrtLibrary to be True no
+matter the build type.
+
+Exercise: We modified MathFunctions.h to use dll export defines. Using CMake
+documentation can you find a helper module to simplify this?
+
+Exercise: Determine what command is enabling PIC for SqrtLibrary.
+What happens if we remove said command?