Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
- Improve log and metric delivery when telemetry is captured faster than envelopes can be serialized by offloading serialization to an internal thread pool. ([#1946](https://github.com/getsentry/sentry-native/pull/1946))
- Wine: fix OS version detection and cross-compiling Windows builds from Linux. ([#2001](https://github.com/getsentry/sentry-native/pull/2001))
- Destroy condition variables as approriate when no longer needed. ([#2004](https://github.com/getsentry/sentry-native/pull/2004))
- CMake: `pkg-config` is no longer a hard build requirement. `SENTRY_LIBUNWIND_SYSTEM` and `SENTRY_BREAKPAD_SYSTEM` still prefer the `pkg-config` metadata of the system package, but now fall back to `find_library()`/`find_path()` when the tool or the `.pc` file is missing. The same applies to the exported CMake config, which no longer requires consumers of a static build to have `pkg-config` installed.
- Crashpad/Windows: preserve module CodeView UUIDs for minimal PDB70 records with empty PDB filenames. ([#2003](https://github.com/getsentry/sentry-native/pull/2003))

## 0.16.3
Expand Down
23 changes: 12 additions & 11 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,7 @@ if(WIN32)
endif()

include(cmake/utils.cmake)
include(cmake/sentry-find-system-library.cmake)
if (WIN32 AND SENTRY_BUILD_SHARED_LIBS)
sentry_add_version_resource(sentry "Client Library")
endif()
Expand Down Expand Up @@ -705,12 +706,11 @@ endif()
if(SENTRY_WITH_LIBUNWIND)
if(LINUX)
if(SENTRY_LIBUNWIND_SYSTEM)
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBUNWIND REQUIRED IMPORTED_TARGET libunwind)
sentry_find_libunwind()
if(SENTRY_BUILD_SHARED_LIBS)
target_link_libraries(sentry PRIVATE PkgConfig::LIBUNWIND)
target_link_libraries(sentry PRIVATE sentry::libunwind)
else()
target_link_libraries(sentry PUBLIC PkgConfig::LIBUNWIND)
target_link_libraries(sentry PUBLIC sentry::libunwind)
endif()
else()
# Use vendored libunwind
Expand Down Expand Up @@ -802,13 +802,12 @@ elseif(SENTRY_BACKEND_BREAKPAD)
option(SENTRY_BREAKPAD_SYSTEM "Use system breakpad" OFF)
if(SENTRY_BREAKPAD_SYSTEM)
target_compile_definitions(sentry PRIVATE SENTRY_BREAKPAD_SYSTEM)
# system breakpad is using pkg-config, see `external/breakpad/breakpad-client.pc.in`
find_package(PkgConfig REQUIRED)
pkg_check_modules(BREAKPAD REQUIRED IMPORTED_TARGET breakpad-client)
# system breakpad ships pkg-config metadata, see `external/breakpad/breakpad-client.pc.in`
sentry_find_breakpad_client()
if(SENTRY_BUILD_SHARED_LIBS)
target_link_libraries(sentry PRIVATE PkgConfig::BREAKPAD)
target_link_libraries(sentry PRIVATE sentry::breakpad-client)
else()
target_link_libraries(sentry PUBLIC PkgConfig::BREAKPAD)
target_link_libraries(sentry PUBLIC sentry::breakpad-client)
endif()
else()
add_subdirectory(external)
Expand Down Expand Up @@ -934,8 +933,8 @@ elseif(SENTRY_BACKEND_NATIVE)

if(SENTRY_WITH_LIBUNWIND AND LINUX)
if(SENTRY_LIBUNWIND_SYSTEM)
pkg_check_modules(LIBUNWIND_PTRACE REQUIRED IMPORTED_TARGET libunwind-ptrace)
target_link_libraries(sentry-crash PRIVATE PkgConfig::LIBUNWIND PkgConfig::LIBUNWIND_PTRACE)
sentry_find_libunwind_ptrace()
target_link_libraries(sentry-crash PRIVATE sentry::libunwind sentry::libunwind-ptrace)
else()
# Use unwind_remote for the daemon (includes ptrace accessors
# for remote DWARF unwinding of the crashed process)
Expand Down Expand Up @@ -1018,6 +1017,8 @@ sentry_install(
FILES
"${PROJECT_BINARY_DIR}/sentry-config.cmake"
"${PROJECT_BINARY_DIR}/sentry-config-version.cmake"
# `sentry-config.cmake` recreates the system-library targets for consumers of a static build
"${SENTRY_SOURCE_DIR}/cmake/sentry-find-system-library.cmake"
DESTINATION "${CMAKE_INSTALL_CMAKEDIR}")
if(WIN32 AND MSVC AND SENTRY_BUILD_SHARED_LIBS)
sentry_install(FILES $<TARGET_PDB_FILE:sentry>
Expand Down
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -266,15 +266,20 @@ using `cmake -D BUILD_SHARED_LIBS=OFF ..`.
This instructs the build system to use system-installed breakpad libraries instead of the in-tree version.

- `SENTRY_LIBUNWIND_SYSTEM` (Default: `OFF`, only for Linux):
This instructs the build system to use a system-installed `libunwind` (found via `pkg-config`) instead of the
vendored copy in `vendor/libunwind`.
This instructs the build system to use a system-installed `libunwind` instead of the vendored copy in
`vendor/libunwind`.

In contrast to the vendored `libunwind` which is always built as a static archive and either linked into the
resulting shared library or colocated with the other static artifacts, with `SENTRY_LIBUNWIND_SYSTEM=ON`, the library
type (shared or static) is determined by the host distribution's package. The `SENTRY_BUILD_SHARED_LIBS` option only
controls how the dependency is exposed to consuming CMake projects, not the library type of the system `libunwind`
itself. Ensure matching build and target environments when using system packages.

Both `SENTRY_BREAKPAD_SYSTEM` and `SENTRY_LIBUNWIND_SYSTEM` read the `pkg-config` metadata of the system package
when `pkg-config`/`pkgconf` is installed, and fall back to CMake's own `find_library()`/`find_path()` lookup when it
is not, so `pkg-config` is a convenience rather than a build requirement for either option. The only remaining
build-time user of `pkg-config` is the vendored `crashpad`, and only on Linux with `CRASHPAD_ENABLE_STACKTRACE=ON`.

- `SENTRY_TRANSPORT_COMPRESSION` (Default: `OFF`):
Adds Gzip transport compression. Requires `zlib`.

Expand Down
112 changes: 112 additions & 0 deletions cmake/sentry-find-system-library.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# Locates a system library, preferring `pkg-config` metadata when both the tool and the requested module are
# available, and falling back to plain `find_library()`/`find_path()` when they are not.
#
# `pkg-config` is only ever consulted for the optional `SENTRY_LIBUNWIND_SYSTEM` and `SENTRY_BREAKPAD_SYSTEM` code
# paths, and only on Linux. Requesting it with `find_package(PkgConfig REQUIRED)` nevertheless turned the tool into a
# hard build requirement for anyone packaging sentry-native, which is why package managers end up declaring it on
# every platform, including those where it is never invoked.
#
# On success the imported target `TGT` is defined regardless of which of the two lookups provided it, so neither the
# call sites nor the installed `sentry-config.cmake` have to branch on the outcome.
#
# sentry_find_system_library(<TGT>
# PKG_CONFIG_MODULE <module>
# LIBRARY_NAMES <name>...
# [HEADER_NAMES <header>...]
# [HEADER_PATH_SUFFIXES <suffix>...])
function(sentry_find_system_library TGT)
cmake_parse_arguments(SFSL "" "PKG_CONFIG_MODULE" "LIBRARY_NAMES;HEADER_NAMES;HEADER_PATH_SUFFIXES" ${ARGN})

if(TARGET "${TGT}")
return()
endif()

string(MAKE_C_IDENTIFIER "${TGT}" prefix)
string(TOUPPER "${prefix}" prefix)

# `pkg-config` resolves transitive `Requires:` and `Libs.private:` entries for us, so prefer it when available.
find_package(PkgConfig QUIET)
if(PKG_CONFIG_FOUND)
pkg_check_modules("${prefix}" QUIET IMPORTED_TARGET "${SFSL_PKG_CONFIG_MODULE}")
endif()

if(TARGET "PkgConfig::${prefix}")
add_library("${TGT}" INTERFACE IMPORTED)
set_target_properties("${TGT}" PROPERTIES INTERFACE_LINK_LIBRARIES "PkgConfig::${prefix}")
return()
endif()

# No usable `pkg-config` module, so resolve the library and its headers ourselves.
set(libraries "")
set(missing "")
foreach(name IN LISTS SFSL_LIBRARY_NAMES)
string(MAKE_C_IDENTIFIER "SENTRY_${prefix}_${name}_LIBRARY" cache_var)
find_library("${cache_var}" NAMES "${name}")
mark_as_advanced("${cache_var}")
if(${cache_var})
list(APPEND libraries "${${cache_var}}")
else()
list(APPEND missing "lib${name}")
endif()
endforeach()

set(include_dir "")
if(SFSL_HEADER_NAMES)
string(MAKE_C_IDENTIFIER "SENTRY_${prefix}_INCLUDE_DIR" cache_var)
if(SFSL_HEADER_PATH_SUFFIXES)
find_path("${cache_var}" NAMES ${SFSL_HEADER_NAMES} PATH_SUFFIXES ${SFSL_HEADER_PATH_SUFFIXES})
else()
find_path("${cache_var}" NAMES ${SFSL_HEADER_NAMES})
endif()
mark_as_advanced("${cache_var}")
if(${cache_var})
set(include_dir "${${cache_var}}")
else()
list(GET SFSL_HEADER_NAMES 0 header)
list(APPEND missing "${header}")
endif()
endif()

if(missing)
string(REPLACE ";" ", " missing "${missing}")
message(FATAL_ERROR
"Could not find the system dependency `${SFSL_PKG_CONFIG_MODULE}` needed for `${TGT}`.\n"
"Missing: ${missing}.\n"
"Install the matching development package, point CMake at it via `CMAKE_PREFIX_PATH`, or install "
"`pkg-config`/`pkgconf` so that `${SFSL_PKG_CONFIG_MODULE}.pc` can be used instead.")
endif()

add_library("${TGT}" INTERFACE IMPORTED)
set_target_properties("${TGT}" PROPERTIES INTERFACE_LINK_LIBRARIES "${libraries}")
if(include_dir)
set_target_properties("${TGT}" PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${include_dir}")
endif()
endfunction()

# The lookups below are shared between the build itself and the installed `sentry-config.cmake`, which has to recreate
# the same imported targets for consumers of a static sentry-native. Keeping them here means the two cannot drift.

function(sentry_find_libunwind)
sentry_find_system_library(sentry::libunwind
PKG_CONFIG_MODULE libunwind
LIBRARY_NAMES unwind
HEADER_NAMES libunwind.h)
endfunction()

function(sentry_find_libunwind_ptrace)
# `libunwind-ptrace.pc` pulls in `libunwind-generic`, so the fallback has to link it explicitly.
sentry_find_system_library(sentry::libunwind-ptrace
PKG_CONFIG_MODULE libunwind-ptrace
LIBRARY_NAMES unwind-ptrace unwind-generic
HEADER_NAMES libunwind-ptrace.h)
endfunction()

function(sentry_find_breakpad_client)
# `breakpad-client.pc` exposes the headers below `${includedir}/breakpad`, matching the `client/<os>/...`
# includes in `src/backends/sentry_backend_breakpad.cpp`.
sentry_find_system_library(sentry::breakpad-client
PKG_CONFIG_MODULE breakpad-client
LIBRARY_NAMES breakpad_client
HEADER_NAMES google_breakpad/common/breakpad_types.h
HEADER_PATH_SUFFIXES breakpad)
endfunction()
7 changes: 3 additions & 4 deletions sentry-config.cmake.in
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
@PACKAGE_INIT@
include(CMakeFindDependencyMacro)
include("${CMAKE_CURRENT_LIST_DIR}/sentry-find-system-library.cmake")

set(SENTRY_BACKEND @SENTRY_BACKEND@)
set(SENTRY_TRANSPORT @SENTRY_TRANSPORT@)
Expand All @@ -16,12 +17,10 @@ if(NOT SENTRY_BUILD_SHARED_LIBS)
find_dependency(ZLIB)
endif()
if(SENTRY_BACKEND STREQUAL "breakpad" AND SENTRY_BREAKPAD_SYSTEM)
find_dependency(PkgConfig)
pkg_check_modules(BREAKPAD REQUIRED IMPORTED_TARGET breakpad-client)
sentry_find_breakpad_client()
endif()
if(SENTRY_LIBUNWIND_SYSTEM)
find_dependency(PkgConfig)
pkg_check_modules(LIBUNWIND REQUIRED IMPORTED_TARGET libunwind)
sentry_find_libunwind()
endif()
if(SENTRY_TRANSPORT STREQUAL "curl" AND NOT SENTRY_LINK_CURL STREQUAL "OFF")
find_dependency(CURL)
Expand Down
Loading