You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
167 lines
5.5 KiB
167 lines
5.5 KiB
# 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?
|