Building Shared or Static Libraries with CMake's TARGET_SUPPORTS_SHARED_LIBS
TARGET_SUPPORTS_SHARED_LIBS
- Impact
The value ofTARGET_SUPPORTS_SHARED_LIBS
influences how CMake generates build rules. If it'sTRUE
(the default for most platforms), CMake will attempt to create shared libraries for targets. If it'sFALSE
, CMake will focus on generating static libraries or executables, as shared libraries might not be supported. - Default Value
By default, CMake assumes most general-purpose operating systems support shared libraries. However, this can be overridden based on platform detection or specific toolchain configurations. - Purpose
This boolean property in CMake indicates whether the target platform supports creating shared libraries (.so
on Linux,.dll
on Windows, etc.).
Understanding Properties of Global Scope
- Properties can be used to control various aspects of the build process, including:
- Build flags (e.g., compiler optimization settings)
- Dependencies
- Visibility of targets
- And more
- Global properties, like
TARGET_SUPPORTS_SHARED_LIBS
, have project-wide scope. They can be set once and affect all targets within the project unless overridden for specific targets. - Properties are attributes associated with targets, sources, files, and other entities in a CMake project.
How TARGET_SUPPORTS_SHARED_LIBS
is Used
- You can also explicitly set it in your
CMakeLists.txt
file using theset_target_properties
command: - CMake automatically sets this property based on platform detection during project configuration.
set_target_properties(my_target PROPERTIES TARGET_SUPPORTS_SHARED_LIBS FALSE)
This would instruct CMake to generate a static library (or executable) for the target my_target
even if the platform generally supports shared libraries.
Common Scenarios for Overriding TARGET_SUPPORTS_SHARED_LIBS
- Custom Toolchains
If you're using a custom toolchain that doesn't support shared libraries, you'd set this property toFALSE
for all targets within that toolchain. - Embedded Systems
Some embedded systems might have limited memory or lack support for dynamic linking, making shared libraries unsuitable. In such cases, you'd setTARGET_SUPPORTS_SHARED_LIBS
toFALSE
to ensure static libraries are generated.
Example 1: Platform-Specific Shared Library Behavior
cmake_minimum_required(VERSION 3.10)
project(my_project)
# Detect the platform
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
# Shared libraries are likely supported on Linux
set(TARGET_SUPPORTS_SHARED_LIBS TRUE)
elseif(CMAKE_SYSTEM_NAME MATCHES "Windows")
# Shared libraries are also supported on Windows
set(TARGET_SUPPORTS_SHARED_LIBS TRUE)
else()
# Assume other platforms might not support shared libraries
set(TARGET_SUPPORTS_SHARED_LIBS FALSE)
message(WARNING "Platform '${CMAKE_SYSTEM_NAME}' may not support shared libraries. Building static libraries by default.")
endif()
# Create a library (type will be determined based on TARGET_SUPPORTS_SHARED_LIBS)
add_library(my_lib my_lib.cpp)
In this example, CMake checks the operating system name and sets TARGET_SUPPORTS_SHARED_LIBS
accordingly. The library my_lib
will be built as a shared library on Linux and Windows, but as a static library on other platforms.
Example 2: Explicitly Forcing Static Library
cmake_minimum_required(VERSION 3.5)
project(my_project)
# Create a library and explicitly force it to be static
add_library(my_lib STATIC my_lib.cpp)
# Even if the platform supports shared libraries, this one will be static
set_target_properties(my_lib PROPERTIES TARGET_SUPPORTS_SHARED_LIBS FALSE)
Here, regardless of the platform, my_lib
will be built as a static library because TARGET_SUPPORTS_SHARED_LIBS
is set to FALSE
explicitly.
cmake_minimum_required(VERSION 3.15)
project(my_project)
option(BUILD_SHARED_LIBS "Build shared libraries (default: ON)" ON)
# Set TARGET_SUPPORTS_SHARED_LIBS based on the user's choice
set(TARGET_SUPPORTS_SHARED_LIBS ${BUILD_SHARED_LIBS})
add_library(my_lib my_lib.cpp)
if(TARGET_SUPPORTS_SHARED_LIBS)
message(STATUS "Building my_lib as a shared library.")
else()
message(STATUS "Building my_lib as a static library.")
endif()
- Use
CMAKE_SYSTEM_NAME
or other platform detection methods to check the operating system. - Based on the platform, use
if
statements to explicitly specify the library type inadd_library
:
if(CMAKE_SYSTEM_NAME MATCHES "Linux") add_library(my_lib SHARED my_lib.cpp) else() add_library(my_lib STATIC my_lib.cpp) endif()
- Use
BUILD_SHARED_LIBS Variable
- CMake provides the
BUILD_SHARED_LIBS
boolean variable. Projects often useoption
to create a user-controllable option with this variable:
option(BUILD_SHARED_LIBS "Build using shared libraries" ON) add_library(my_lib ${sources}) if(BUILD_SHARED_LIBS) set_target_properties(my_lib PROPERTIES LIBRARY_SHARED TRUE) else() set_target_properties(my_lib PROPERTIES LIBRARY_SHARED FALSE) endif()
Here,
add_library
doesn't specify the type. Based on theBUILD_SHARED_LIBS
value, the library type is set usingset_target_properties
.- CMake provides the
External Toolchains
- If you have custom toolchains that don't support shared libraries, consider setting
BUILD_SHARED_LIBS
toOFF
for targets built with that toolchain.
- If you have custom toolchains that don't support shared libraries, consider setting
Choosing the Best Approach
- For managing custom toolchains, consider a combination of
BUILD_SHARED_LIBS
and toolchain-specific configurations. - If you want user control over library type, the
BUILD_SHARED_LIBS
option is a good choice. - For simple platform-specific behavior, conditional logic with
if
andelse
might be sufficient.