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
.
option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
Next, we need to specify output directories for our static and shared libraries.
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:
#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.
# 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.
# 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?