Posted Joe Chucpp8 minutes read (About 1.2k words)0 visits
Static And Shared Library
Code distribution among different programs and machines.
1. Introduction
A static library is a collection of object files that are linked into the program during the linking phase of compilation, becoming part of the final executable. A shared library is a collection of object files that are loaded into the program at runtime. Multiple programs can share the same library code in memory.
// mathlib.h #pragma once classMathLib { public: MathLib(); ~MathLib(); doubleadd(double, double); doublesubtract(double, double); doublemultiply(double, double); doubledivide(double, double); }; // mathlib.cpp #include"mathlib.h" #include<iostream> doubleMathLib::add(double a, double b){ return a + b; } doubleMathLib::subtract(double a, double b){ return a - b; } doubleMathLib::multiply(double a, double b){ return a * b; } doubleMathLib::divide(double a, double b){ if (b == 0) { throw std::domain_error("Division by zero."); } return a / b; } MathLib::MathLib() {} MathLib::~MathLib() {}
We will compile it into both static and shared libraries.
1 2 3 4 5 6 7 8 9 10 11
cmake_minimum_required(VERSION 3.5.0) project(Math VERSION 0.0.1 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) # Create a shared library add_library(math_shared SHARED mathlib.cpp) # Create a static library add_library(math_static STATIC mathlib.cpp)
For the most outside CMakeLists.txt, we will generate different executables that link to static/shared libraries.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
cmake_minimum_required(VERSION 3.5.0) project(main VERSION 0.0.1 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) add_subdirectory(${CMAKE_SOURCE_DIR}/math) # add an executable that links to a shared library add_executable(main_shared main.cpp) target_include_directories(main_shared PRIVATE ${CMAKE_SOURCE_DIR}/math) target_link_libraries(main_shared PRIVATE math_shared) # add an executable that links to a static library add_executable(main_static main.cpp) target_include_directories(main_static PRIVATE ${CMAKE_SOURCE_DIR}/math) target_link_libraries(main_static PRIVATE math_static)
2.2 Build
Let’s build it.
1 2 3 4
mkdir build cd build cmake .. make
In the build folder, we can get two executables and inside the math folder, we have generated static/shared libraries. They should have the same output.
> ./main_static input x and y: 10, 5 Addition: 15 Subtraction: 5 Multiplication: 50 Division: 2 > ./main_shared input x and y: 10, 5 Addition: 15 Subtraction: 5 Multiplication: 50 Division: 2
2.3 Inspect
We could use otool on MacOS to check the dependencies of each executable. Or on Linux we could use ldd.
1 2 3 4
> otool -L main_static main_static: /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1500.65.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1319.100.3)
1 2 3 4 5
> otool -L main_shared main_shared: @rpath/libmath_shared.dylib (compatibility version 0.0.0, current version 0.0.0) /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1500.65.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1319.100.3)
Because static libraries will become part of the executable, so libmath_static.a is not a dependency. On the other hand, shared libraries are loaded during runtime, so main_shared replies on libmath_shared.dylib.
2.4 File size
Linking a static library involves incorporating the entire library into the final executable. Compared with linking shared library, executables that link to static library usually will have larger file size.
1 2 3 4
> ls -lh main_static -rwxr-xr-x 1 zongchengchu staff 40K Jun 29 13:55 main_static > ls -lh main_shared -rwxr-xr-x 1 zongchengchu staff 39K Jun 29 13:55 main_shared
2.5 Delete dependencies
If we delete both libmath_static.a and libmath_shared.dylib, main_static can still run without any issues.
1 2 3 4 5 6
> ./main_static input x and y: 10, 5 Addition: 15 Subtraction: 5 Multiplication: 50 Division: 2
However, main_shared needs to load libmath_shared.dylib at runtime, and it looks for the library at current project as well as system paths. If this library is not found, then we will get a link error.
1 2 3 4
> ./main_shared dyld[55250]: Library not loaded: @rpath/libmath_shared.dylib Referenced from: <4F8039F2-AFFB-303C-999C-FAF867191A7C> /Users/zongchengchu/Documents/repos/static_shared_lib/build/main_shared Reason: tried: '/Users/zongchengchu/Documents/repos/static_shared_lib/build/math/libmath_shared.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Users/zongchengchu/Documents/repos/static_shared_lib/build/math/libmath_shared.dylib' (no such file), '/Users/zongchengchu/Documents/repos/static_shared_lib/build/math/libmath_shared.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Users/zongchengchu/Documents/repos/static_shared_lib/build/math/libmath_shared.dylib' (no such file), '/usr/local/lib/libmath_shared.dylib' (no such file), '/usr/lib/libmath_shared.dylib' (no such file, not in dyld cache)
2.5 More
If a static/shared library depends on another library. The relationship can be:
dependencies
valid?
shared_lib links to static_lib
✗
shared_lib links to shared_lib
✓
static_lib links to static_lib
✓
static_lib links to shared_lib
✓
Shared libraries can only be linked to shared libraries. Static libraries can be linked to both shared and static library.
3. Conclusion
static library
Advantages:
Simplicity: No external dependencies are required at runtime.
Performance: Sometimes faster to start and run due to the absence of the need to resolve symbols or load additional libraries at runtime.
Disadvantages:
File Size: Can lead to larger executable sizes because each program has its own copy of the library.
Updates: If the library is updated, all applications using it must be recompiled and redeployed to benefit from the updates.
shared library
Advantages:
Reduced Memory Usage: Since the library is shared in memory among multiple programs, it can reduce memory usage overall.
Ease of Updating: Updating a shared library can provide immediate benefits to all programs that use it, without needing recompilation.
Disadvantages:
Complexity: Requires careful management of versions and dependencies to ensure compatibility.
Startup Time: Can have slower startup times as the operating system needs to link the external libraries dynamically when the program is launched.
void GLRender::nextImage() { LOG_INFO(“switch to next image.”); int next_index = (image_idx + 1) % IMAGE_NUM; sdrImage.setFilepath(files[next_index]);