This document explains how the DNG SDK CMake package system handles transitive dependencies for static library builds.
When you build a static library and link it into an application, the application also needs to link against all the dependencies that the static library uses. This is different from shared/dynamic libraries, where the dependencies are resolved at runtime.
If libdng_sdk.a was built with JPEG-XL support, it internally uses:
libjxl.alibjxl_threads.alibhwy.a(Highway SIMD library)libbrotlidec.a,libbrotlienc.a,libbrotlicommon.a(Brotli compression)
When you link your application against libdng_sdk.a, you must also link against all these libraries, or you'll get linker errors like "undefined reference to jxl::...".
All dependencies are linked with PUBLIC linkage instead of PRIVATE:
# cmake/dng_sdk.cmake
target_link_libraries(dng_sdk PUBLIC
Threads::Threads
jxl::jxl
jxl::jxl_threads
hwy::hwy
brotli::brotlidec
brotli::brotlienc
brotli::brotlicommon
)What this does:
- When you link against
dng_sdk, CMake automatically adds all PUBLIC dependencies to your link command - The dependency information is saved in the installed
dng_sdk-targets.cmakefile
The dng_sdk-config.cmake.in file uses find_dependency() to locate all required libraries:
# Find JPEG-XL and dependencies
if(@DNG_WITH_JXL@)
find_package(libjxl CONFIG QUIET)
if(NOT libjxl_FOUND)
# Fallback to PkgConfig
pkg_check_modules(JXL REQUIRED libjxl)
pkg_check_modules(HWY REQUIRED libhwy)
# ... etc
endif()
endif()What this does:
- When a downstream project calls
find_package(dng_sdk), CMake automatically finds all dependencies - Uses multiple strategies: CMake config files, pkg-config, or manual library finding
- Creates imported targets for all dependencies
Your Application
└─> dng_sdk::dng_sdk
├─> Threads::Threads
├─> JPEG::JPEG (if DNG_WITH_JPEG=ON)
├─> XMP::XMPCoreStatic (if DNG_WITH_XMP=ON)
│ ├─> EXPAT::EXPAT
│ └─> ZLIB::ZLIB
├─> XMP::XMPFilesStatic (if DNG_WITH_XMP=ON)
│ └─> XMP::XMPCoreStatic
└─> jxl::jxl (if DNG_WITH_JXL=ON)
├─> jxl::jxl_threads
├─> hwy::hwy
├─> brotli::brotlidec
├─> brotli::brotlienc
└─> brotli::brotlicommon
All of these dependencies are automatically resolved when you link against dng_sdk::dng_sdk.
cmake_minimum_required(VERSION 3.16)
project(my_app)
# Find dng_sdk - this automatically finds ALL dependencies
find_package(dng_sdk 1.7 REQUIRED)
add_executable(my_app main.cpp)
# This ONE line links everything you need
target_link_libraries(my_app PRIVATE dng_sdk::dng_sdk)
# No need to manually link JPEG, JXL, brotli, highway, etc.
# CMake does it automatically!# Get all compiler and linker flags including dependencies
CFLAGS=$(pkg-config --cflags dng_sdk)
LIBS=$(pkg-config --libs dng_sdk)
g++ main.cpp $CFLAGS $LIBS -o my_appWhen you target_link_libraries(my_app PRIVATE dng_sdk::dng_sdk):
Always linked:
pthread(Threads::Threads)
If DNG_WITH_JPEG=ON:
libjpeg
If DNG_WITH_JXL=ON:
libjxllibjxl_threadslibhwylibbrotlideclibbrotlienclibbrotlicommon
If DNG_WITH_XMP=ON:
libXMPCoreStatic(which linkslibexpatandlibz)libXMPFilesStatic(which linkslibXMPCoreStatic)
Cause: You're linking against libdng_sdk.a manually without CMake's target system.
Solution: Use find_package(dng_sdk) and link against dng_sdk::dng_sdk target, not the raw library file.
Cause: The JPEG library is not in CMake's search path.
Solution:
# Option 1: Set CMAKE_PREFIX_PATH
cmake -DCMAKE_PREFIX_PATH="/path/to/jpeg;/path/to/other/libs" ..
# Option 2: Set specific package directories
cmake -DJPEG_ROOT=/path/to/jpeg ..
# Option 3: Install libraries to standard locations (/usr/local, etc.)Cause: Trying to link static libdng_sdk.a with shared libjxl.so.
Solution: Ensure all dependencies match the link type:
- Static build: Use static versions of all dependencies (
.a,.lib) - Shared build: Use shared versions of all dependencies (
.so,.dll)
find_package(dng_sdk REQUIRED)
# Print the target's link libraries
get_target_property(DNG_LINK_LIBS dng_sdk::dng_sdk INTERFACE_LINK_LIBRARIES)
message(STATUS "dng_sdk links to: ${DNG_LINK_LIBS}")# Linux: Check what's linked in your executable
ldd my_app
# macOS: Check dependencies
otool -L my_app
# Windows: Check DLL dependencies
dumpbin /dependents my_app.exeIf CMake can't find a dependency automatically, you can help it:
# Set hints for specific libraries
set(EXPAT_ROOT "/opt/expat")
set(ZLIB_ROOT "/usr/local")
set(JPEG_ROOT "/opt/libjpeg-turbo")
# Or use CMAKE_PREFIX_PATH for all
list(APPEND CMAKE_PREFIX_PATH
"/opt/expat"
"/usr/local"
"/opt/libjpeg-turbo"
)
find_package(dng_sdk REQUIRED)The installed dng_sdk-targets.cmake contains:
# Pseudo-code showing what's exported
add_library(dng_sdk::dng_sdk STATIC IMPORTED)
set_target_properties(dng_sdk::dng_sdk PROPERTIES
IMPORTED_LOCATION "/usr/local/lib/libdng_sdk.a"
INTERFACE_LINK_LIBRARIES "Threads::Threads;jxl::jxl;hwy::hwy;..."
INTERFACE_INCLUDE_DIRECTORIES "/usr/local/include/dng_sdk"
)The INTERFACE_LINK_LIBRARIES property contains all transitive dependencies.
dng_sdk-config.cmake tries multiple methods to find each dependency:
- CMake Config -
find_package(libjxl CONFIG) - pkg-config -
pkg_check_modules(JXL libjxl) - Manual -
find_library(JXL_LIBRARY NAMES jxl)
This ensures maximum compatibility across different systems and installation methods.
- Always use
find_package()instead of manually specifying library paths - Link against imported targets (
dng_sdk::dng_sdk) not raw libraries - Install all dependencies before building projects that use dng_sdk
- Use the same build type (Debug/Release) for all libraries
- Match static/shared - don't mix static and shared libraries
- CMake documentation: Imported Targets
- CMake documentation: target_link_libraries()
- pkg-config guide: Writing pkg-config files