Since CMake version 2.8.8, you can use "object libraries" to avoid the duplicated compilation of the object files. Using Christopher Bruns' example of a library with two source files:

# list of source files
set(libsrc source1.c source2.c)

# this is the "object library" target: compiles the sources only once
add_library(objlib OBJECT ${libsrc})

# shared libraries need PIC
set_property(TARGET objlib PROPERTY POSITION_INDEPENDENT_CODE 1)

# shared and static libraries built from the same object files
add_library(MyLib_shared SHARED $<TARGET_OBJECTS:objlib>)
add_library(MyLib_static STATIC $<TARGET_OBJECTS:objlib>)

From the CMake docs:

An object library compiles source files but does not archive or link their object files into a library. Instead other targets created by add_library() or add_executable() may reference the objects using an expression of the form $<TARGET_OBJECTS:objlib> as a source, where objlib is the object library name.

Simply put, the add_library(objlib OBJECT ${libsrc}) command instructs CMake to compile the source files to *.o object files. This collection of *.o files is then referred to as $<TARGET_OBJECT:objlib> in the two add_library(...) commands that invoke the appropriate library creation commands that build the shared and static libraries from the same set of object files. If you have lots of source files, then compiling the *.o files can take quite long; with object libraries you compile them only once.

The price you pay is that the object files must be built as position-independent code because shared libraries need this (static libs don't care). Note that position-independent code may be less efficient, so if you aim for maximal performance then you'd go for static libraries. Furthermore, it is easier to distribute statically linked executables.

Answer from András Aszódi on Stack Overflow
🌐
CMake
cmake.org › cmake › help › latest › guide › tutorial › Selecting Static or Shared Libraries.html
Step 10: Selecting Static or Shared Libraries — CMake 4.3.0-rc3 Documentation
Step 10: Selecting Static or Shared Libraries · This page was once part of an older version of the CMake tutorial which last appeared in CMake 4.1. See the current tutorial version here. To see the older version, follow this link or select the drop-down in the page header. Step 9: Packaging an Installer · Step 11: Adding ...
🌐
CMake
cmake.org › cmake › help › latest › command › add_library.html
add_library — CMake 4.3.0-rc3 Documentation
Add a library target called <name> to be built from the source files listed in the command invocation. The optional <type> specifies the type of library to be created: ... A Static Library: an archive of object files for use when linking other targets. ... A Shared Library: a dynamic library ...
Discussions

One library target building both static and shared - Development - CMake Discourse
Pre-coffee irrational idea, but thought why not put it out there for discussion anyway. A single library target can be built as static or shared, but not both. This presents problems for some consumers who specifically need one or the other. It gets more complicated when the consumer itself ... More on discourse.cmake.org
🌐 discourse.cmake.org
3
April 15, 2021
Add CMake option to choose building SHARED vs STATIC
It's a pretty common convention to use options to expose the shared/static choice to consumers: https://cmake.org/cmake/help/latest/variable/BUILD_SHARED_LIBS.html · Note: Libraries such as this should not use the BUILD_SHARED_LIBS global value, but instead should use their own specific option ... More on github.com
🌐 github.com
13
June 24, 2019
Static vs Shared lib
I’m somewhat amazed you understand kernel module loading but not shared libraries. The second last paragraph is mostly right, yes, besides some odd use of verbiage. Can you explain what you mean by “in the context of CMake”? The description you provide is just general shared libraries, and not specific to CMake. See https://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html Edit: referenced the wrong paragraph More on reddit.com
🌐 r/cpp_questions
6
5
October 3, 2022
c++ - Difference between static and shared libraries? - Stack Overflow
What is the difference between static and shared libraries? I use Eclipse and there are several project types including Static Libraries and Shared Libraries? Does one have an advantage over the o... More on stackoverflow.com
🌐 stackoverflow.com
Top answer
1 of 5
158

Since CMake version 2.8.8, you can use "object libraries" to avoid the duplicated compilation of the object files. Using Christopher Bruns' example of a library with two source files:

# list of source files
set(libsrc source1.c source2.c)

# this is the "object library" target: compiles the sources only once
add_library(objlib OBJECT ${libsrc})

# shared libraries need PIC
set_property(TARGET objlib PROPERTY POSITION_INDEPENDENT_CODE 1)

# shared and static libraries built from the same object files
add_library(MyLib_shared SHARED $<TARGET_OBJECTS:objlib>)
add_library(MyLib_static STATIC $<TARGET_OBJECTS:objlib>)

From the CMake docs:

An object library compiles source files but does not archive or link their object files into a library. Instead other targets created by add_library() or add_executable() may reference the objects using an expression of the form $<TARGET_OBJECTS:objlib> as a source, where objlib is the object library name.

Simply put, the add_library(objlib OBJECT ${libsrc}) command instructs CMake to compile the source files to *.o object files. This collection of *.o files is then referred to as $<TARGET_OBJECT:objlib> in the two add_library(...) commands that invoke the appropriate library creation commands that build the shared and static libraries from the same set of object files. If you have lots of source files, then compiling the *.o files can take quite long; with object libraries you compile them only once.

The price you pay is that the object files must be built as position-independent code because shared libraries need this (static libs don't care). Note that position-independent code may be less efficient, so if you aim for maximal performance then you'd go for static libraries. Furthermore, it is easier to distribute statically linked executables.

2 of 5
149

Yes, it's moderately easy. Just use two "add_library" commands:

add_library(MyLib SHARED source1.c source2.c)
add_library(MyLibStatic STATIC source1.c source2.c)

Even if you have many source files, you can place the list of sources in a Cmake variable, so it's still easy to do.

On Windows you should probably give each library a different name, since there is a ".lib" file for both shared and static. But on Linux and Mac you can even give both libraries the same name (e.g. libMyLib.a and libMyLib.so):

set_target_properties(MyLibStatic PROPERTIES OUTPUT_NAME MyLib)

But I don't recommend giving both the static and dynamic versions of the library the same name. I prefer to use different names because that makes it easier to choose static vs. dynamic linkage on the compile line for tools that link to the library. Usually I choose names like libMyLib.so (shared) and libMyLib_static.a (static). (Those would be the names on linux.)

🌐
CMake
cmake.org › cmake › help › v3.23 › guide › tutorial › Selecting Static or Shared Libraries.html
Step 9: Selecting Static or Shared Libraries — CMake 3.23.5 Documentation
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.
🌐
CGold
cgold.readthedocs.io › en › latest › tutorials › libraries › static-shared.html
3.11.3. Static + shared — CGold 0.1 documentation
Here is an overview how it should be done in CMake. ... We will start with the right one. Command add_library should be used without STATIC or SHARED specifier, type of the library will be determined by value of BUILD_SHARED_LIBS variable (default type is static):
🌐
CMake Discourse
discourse.cmake.org › development
One library target building both static and shared - Development - CMake Discourse
April 15, 2021 - Pre-coffee irrational idea, but thought why not put it out there for discussion anyway. A single library target can be built as static or shared, but not both. This presents problems for some consumers who specifically need one or the other. It gets more complicated when the consumer itself might have switchable behavior which can select whether it wants to consume static or shared libs.
🌐
Alexreinking
alexreinking.com › blog › building-a-dual-shared-and-static-library-with-cmake.html
Building a Dual Shared and Static Library with CMake
March 6, 2021 - Static and shared libraries are typically produced from the same set of sources, too, so new CMake users sometimes expect that a single call to add_library will provide whatever mix of types they want.
Find elsewhere
🌐
GitHub
github.com › microsoft › mimalloc › issues › 36
Add CMake option to choose building SHARED vs STATIC · Issue #36 · microsoft/mimalloc
June 24, 2019 - It's a pretty common convention to use options to expose the shared/static choice to consumers: https://cmake.org/cmake/help/latest/variable/BUILD_SHARED_LIBS.html · Note: Libraries such as this should not use the BUILD_SHARED_LIBS global value, but instead should use their own specific option name such as MI_BUILD_SHARED and/or MI_BUILD_STATIC.
Author   solvingj
🌐
CMake
cmake.org › cmake › help › latest › variable › BUILD_SHARED_LIBS.html
BUILD_SHARED_LIBS — CMake 4.3.0-rc3 Documentation
Tell add_library() to default to SHARED libraries, instead of STATIC libraries, when called with no explicit library type.
🌐
Reddit
reddit.com › r/cpp_questions › static vs shared lib
r/cpp_questions on Reddit: Static vs Shared lib
October 3, 2022 -

Trying to understand the difference between a static and shared lib in the context of CMake.

The latter is linked dynamically and loaded at runtime (not sure how it's loaded at runtime though. The dynamic linking I can relate to is for kernel modules which can be added/removed via modprobe/rmmod but that certainly isn't the case here) whereas static lib is picked up at compile time.

Is the idea that a Shared lib doesn't get integrated into the actual executable of the program (which saves some space & exists in separate .so files) and rather only referred/linked to when there's a call to it in the application for instance?

Top answer
1 of 9
929

Shared libraries are .so (or in Windows .dll, or in OS X .dylib) files. All the code relating to the library is in this file, and it is referenced by programs using it at run-time. A program using a shared library only makes reference to the code that it uses in the shared library.

Static libraries are .a (or in Windows .lib) files. All the code relating to the library is in this file, and it is directly linked into the program at compile time. A program using a static library takes copies of the code that it uses from the static library and makes it part of the program. [Windows also has .lib files which are used to reference .dll files, but they act the same way as the first one].

There are advantages and disadvantages in each method:

  • Shared libraries reduce the amount of code that is duplicated in each program that makes use of the library, keeping the binaries small. It also allows you to replace the shared object with one that is functionally equivalent, but may have added performance benefits without needing to recompile the program that makes use of it. Shared libraries will, however have a small additional cost for the execution of the functions as well as a run-time loading cost as all the symbols in the library need to be connected to the things they use. Additionally, shared libraries can be loaded into an application at run-time, which is the general mechanism for implementing binary plug-in systems.

  • Static libraries increase the overall size of the binary, but it means that you don't need to carry along a copy of the library that is being used. As the code is connected at compile time there are not any additional run-time loading costs. The code is simply there.

Personally, I prefer shared libraries, but use static libraries when needing to ensure that the binary does not have many external dependencies that may be difficult to meet, such as specific versions of the C++ standard library or specific versions of the Boost C++ library.

2 of 9
450

A static library is like a bookstore, and a shared library is like... a library. With the former, you get your own copy of the book/function to take home; with the latter you and everyone else go to the library to use the same book/function. So anyone who wants to use the (shared) library needs to know where it is, because you have to "go get" the book/function. With a static library, the book/function is yours to own, and you keep it within your home/program, and once you have it you don't care where or when you got it.

🌐
GitLab
gitlab.kitware.com › cmake › cmake › #20675
static and shared builds of the same library (#20675) · Issues · CMake / CMake · GitLab
When trying to build an all-static (Windows) application, i’m currently (mis)using setting BUILD_SHARED_LIBS=FALSE to be able to implicitly (via add_library...
🌐
CMake
cmake.cmake.narkive.com › vvb4susL › static-shared-library
[CMake] static & shared library
Permalink is it possible to build a static and shared library (without re-running cmake) for the same target? Something like: ADD_LIBRARY(target STATIC ...) ADD_LIBRARY(target SHARED ...) cmake doesn't allow add_library twice for the same target, so it sort of makes sense that the above doesn't ...
🌐
Rip Tutorial
riptutorial.com › libraries
cmake Tutorial => Libraries
add_library(my_shared_lib SHARED lib.cpp) # Builds an shared library add_library(my_static_lib STATIC lib.cpp) # Builds an static library
🌐
CMake
cmake.org › cmake › help › latest › guide › tutorial › In-Depth CMake Library Concepts.html
Step 5: In-Depth CMake Library Concepts — CMake 4.3.0-rc3 Documentation
If BUILD_SHARED_LIBS is true, a SHARED library will be created, otherwise it will be STATIC. add_library(MyLib-static STATIC) add_library(MyLib-shared SHARED) # Depends on BUILD_SHARED_LIBS add_library(MyLib)
🌐
CMake
cmake.cmake.narkive.com › nZQNh2It › creating-a-shared-and-static-library-of-the-same-name
[CMake] creating a shared and static library of the same name
May 15, 2006 - Note that the CLEAN_DIRECT_OUTPUT property does not yet exist and I made it up for this example. It tells CMake to not remove the static copy of a library when linking the shared one and vice versa (currently this is done to avoid problems when a project switches between shared and static builds).
🌐
CMake
cmake.org › cmake › help › v3.0 › command › add_library.html
add_library — CMake 3.0.2 Documentation
Adds a library target called <name> to be built from the source files listed in the command invocation. The <name> corresponds to the logical target name and must be globally unique within a project. The actual file name of the library built is constructed based on conventions of the native platform (such as lib<name>.a or <name>.lib). STATIC, SHARED, or MODULE may be given to specify the type of library to be created.
🌐
CMake Discourse
discourse.cmake.org › code
Installation behavior of shared versus static libraries - Code - CMake Discourse
May 31, 2023 - ▶ Context Question I am wondering why making a shared library would cause it to install once and show as up-to-date on subsequent invocations of cmake --install whereas using the default library type (which is ostensibly STATIC on my system) would cause it to have to be installed regardless of whether cmake --install had already been invoked.
🌐
Reddit
reddit.com › r/cpp › building a dual shared and static library with cmake
r/cpp on Reddit: Building a Dual Shared and Static Library with CMake
March 8, 2021 - Linux development packages typically install static libraries alongside the shared ones from the runtime package. ... The issues regarding non-CMake users are addressed in the GitHub issue you linked: it inflicts a compiler flag (for the ...
🌐
CMake
cmake.org › cmake › help › v3.4 › command › add_library.html
add_library — CMake 3.4.3 Documentation
Adds a library target called <name> to be built from the source files listed in the command invocation. The <name> corresponds to the logical target name and must be globally unique within a project. The actual file name of the library built is constructed based on conventions of the native platform (such as lib<name>.a or <name>.lib). STATIC, SHARED, or MODULE may be given to specify the type of library to be created.