Step 10: Selecting Static or Shared Libraries

In this section we will show how the BUILD_SHARED_LIBS variable can be used to control the default behavior of add_library(), and allow control over how libraries without an explicit type (STATIC, SHARED, MODULE or 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.

CMakeLists.txt
option(BUILD_SHARED_LIBS "Build using shared libraries" ON)

Next, we need to specify output directories for our static and shared libraries.

CMakeLists.txt
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")

option(BUILD_SHARED_LIBS "Build using shared libraries" ON)

Finally, update MathFunctions/MathFunctions.h to use dll export defines:

MathFunctions/MathFunctions.h
#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 may notice that linking fails as we are combining a static library without position independent code with a library that has position independent code. The solution to this is to explicitly set the POSITION_INDEPENDENT_CODE target property of SqrtLibrary to be True when building shared libraries.

MathFunctions/CMakeLists.txt
  # state that SqrtLibrary need PIC when the default is shared libraries
  set_target_properties(SqrtLibrary PROPERTIES
                        POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS}
                        )

Define EXPORTING_MYMATH stating we are using declspec(dllexport) when building on Windows.

MathFunctions/CMakeLists.txt
# define the symbol stating we are using the declspec(dllexport) when
# building on windows
target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH")

Exercise: We modified MathFunctions.h to use dll export defines. Using CMake documentation can you find a helper module to simplify this?