diff --git a/.editorconfig b/.editorconfig index 6aa024cb1..90692beba 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,3 +8,6 @@ charset = utf-8 [Makefile] indent_style = tab + +[{CMakeLists.txt, *.cmake*}] +indent_style = tab diff --git a/CMakeLists.txt b/CMakeLists.txt index 895de2bf8..518277691 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,8 @@ cmake_minimum_required (VERSION 3.10) -project (Sentry-Native LANGUAGES C CXX ASM) +project(Sentry-Native LANGUAGES C CXX ASM) + +include(GNUInstallDirs) +set(CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/sentry") if(CMAKE_SYSTEM_NAME STREQUAL "Linux") set(LINUX TRUE) @@ -13,7 +16,26 @@ else() set(SENTRY_DEFAULT_BACKEND "inproc") endif() -OPTION(BUILD_SHARED_LIBS "Build shared libraries (.dll/.so) instead of static ones (.lib/.a)" ON) +option(BUILD_SHARED_LIBS "Build shared libraries (.dll/.so) instead of static ones (.lib/.a)" ON) + +option(SENTRY_BUILD_TESTS "Build sentry-native tests" ON) +option(SENTRY_BUILD_EXAMPLES "Build sentry-native example(s)" ON) + +if(SENTRY_BUILD_TESTS OR SENTRY_BUILD_EXAMPLES) + enable_testing() +endif() + +if("${CMAKE_SOURCE_DIR}" STREQUAL "${PROJECT_SOURCE_DIR}") + set(SENTRY_MAIN_PROJECT ON) +endif() + +option(SENTRY_ENABLE_INSTALL "Enable sentry installation" "${SENTRY_MAIN_PROJECT}") + +function(sentry_install) + if(SENTRY_ENABLE_INSTALL) + install(${ARGN}) + endif() +endfunction() if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "RelWithDebInfo") @@ -31,19 +53,25 @@ elseif(SENTRY_BACKEND STREQUAL "breakpad") elseif(SENTRY_BACKEND STREQUAL "none") set(BACKEND_NONE TRUE) else() - message(FATAL_ERROR "SENTRY_BACKEND must be one of 'none', 'inproc' or 'crashpad'") + message(FATAL_ERROR "SENTRY_BACKEND must be one of 'crashpad', 'inproc', 'breakpad' or 'none'") endif() -if(BACKEND_CRASHPAD AND NOT APPLE AND NOT WIN32) +if(BACKEND_CRASHPAD AND NOT (APPLE OR WIN32)) message(FATAL_ERROR "The Crashpad backend is currently only supported on macOS and Windows") endif() -if(BACKEND_BREAKPAD AND NOT LINUX AND NOT ANDROID) +if(BACKEND_BREAKPAD AND NOT (LINUX OR ANDROID)) message(FATAL_ERROR "The Breakpad backend is currently only supported on Linux and Android") endif() if(BACKEND_INPROC AND WIN32) message(FATAL_ERROR "The in-process backend is not supported on Windows") endif() +if(ANDROID) + set(WITH_LIBUNWINDSTACK TRUE) +elseif(NOT WIN32) + set(WITH_LIBBACKTRACE TRUE) +endif() + # use -O3 when doing `RelWithDebInfo` builds foreach(lang ASM C CXX) # unix-like syntax @@ -64,164 +92,181 @@ if(APPLE) endif() endif() - -OPTION(WITH_ASAN_OPTION "Build sentry-native with address sanitizer" OFF) +option(WITH_ASAN_OPTION "Build sentry-native with address sanitizer" OFF) if(WITH_ASAN_OPTION) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -fsanitize=address -fno-omit-frame-pointer") - link_libraries("-fsanitize=address") + add_compile_options(-g -fsanitize=address -fno-omit-frame-pointer) + link_libraries(-fsanitize=address) endif() -OPTION(WITH_TSAN_OPTION "Build sentry-native with thread sanitizer" OFF) +option(WITH_TSAN_OPTION "Build sentry-native with thread sanitizer" OFF) if(WITH_TSAN_OPTION) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -fsanitize=thread -fno-omit-frame-pointer") - link_libraries("-fsanitize=thread") + add_compile_options(-g -fsanitize=thread -fno-omit-frame-pointer) + link_libraries(-fsanitize=thread) endif() -if(BUILD_SHARED_LIBS) - add_definitions(-DSENTRY_BUILD_SHARED) -else() - add_definitions(-DSENTRY_BUILD_STATIC) -endif() +option(SENTRY_CURL_SUPPORT "Builds sentry-native with curl support" ON) -FIND_PACKAGE(CURL) -if(CURL_FOUND) - set(WITH_CURL TRUE) - add_definitions(-DSENTRY_WITH_LIBCURL_TRANSPORT) - include_directories(${CURL_INCLUDE_DIR}) - set(LINK_LIBRARIES ${LINK_LIBRARIES} ${CURL_LIBRARIES}) -endif() -if(WIN32) - add_definitions(-DSENTRY_WITH_WINHTTP_TRANSPORT) - set(LINK_LIBRARIES ${LINK_LIBRARIES} "winhttp.lib") +# helper function to add sources to existing TARGET prepended with ${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR} +function(sentry_target_sources_cwd TARGET) + cmake_parse_arguments(STSC "" "SUBDIR" "" ${ARGN}) + foreach(src ${STSC_UNPARSED_ARGUMENTS}) + if(IS_ABSOLUTE "${src}") + target_sources(${TARGET} PRIVATE ${src}) + else() + target_sources(${TARGET} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/${STSC_SUBDIR}/${src}") + endif() + endforeach() +endfunction() + +# ===== sentry library ===== + +add_library(sentry "${PROJECT_SOURCE_DIR}/vendor/mpack.c") +add_library(sentry::sentry ALIAS sentry) +add_subdirectory(src) + +set_target_properties(sentry PROPERTIES PUBLIC_HEADER "include/sentry.h") + +# https://gitlab.kitware.com/cmake/cmake/issues/18393 +if(BUILD_SHARED_LIBS) + if(APPLE) + sentry_install(FILES "$.dSYM" DESTINATION "${CMAKE_INSTALL_LIBDIR}") + elseif(MSVC) + sentry_install(FILES "$<$,$>:$>" + DESTINATION "${CMAKE_INSTALL_BINDIR}") + endif() endif() -if(BACKEND_CRASHPAD) - set(CMAKE_CXX_STANDARD 14) +if(BUILD_SHARED_LIBS) + target_compile_definitions(sentry PRIVATE SENTRY_BUILD_SHARED) else() - set(CMAKE_CXX_STANDARD 11) + target_compile_definitions(sentry PUBLIC SENTRY_BUILD_STATIC) endif() -#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=implicit-function-declaration -Werror=incompatible-function-pointer-types -Wall -fvisibility=hidden") -if(NOT WIN32) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wpedantic -fvisibility=hidden") +if(SENTRY_CURL_SUPPORT) + find_package(CURL REQUIRED) + target_compile_definitions(sentry PUBLIC SENTRY_WITH_LIBCURL_TRANSPORT) + target_include_directories(sentry PRIVATE ${CURL_INCLUDE_DIR}) + # The exported sentry target must not contain any path of the build machine, therefore use generator expressions + # FIXME: cmake 3.12 introduced the target CURL::libcurl + string(REPLACE ";" "$" GENEX_CURL_LIBRARIES "${CURL_LIBRARIES}") + string(REPLACE ";" "$" GENEX_CURL_COMPILE_DEFINITIONS "${CURL_COMPILE_DEFINITIONS}") + target_link_libraries(sentry PRIVATE $) + target_compile_definitions(sentry PRIVATE $) endif() -if(BACKEND_CRASHPAD AND WIN32) - # Disable duplicate-define warnings, as the crashpad build defines all the - # "slim windows.h" defines, which sentry_boot also defines. - add_definitions(/wd4005) +if(WIN32) + target_compile_definitions(sentry + PRIVATE WINVER=0x0603 NTDDI_VERSION=0x06030000 + PUBLIC SENTRY_WITH_WINHTTP_TRANSPORT + ) + target_link_libraries(sentry PRIVATE winhttp) endif() -if(ANDROID) - set(WITH_LIBUNWINDSTACK TRUE) -elseif(NOT WIN32) - set(WITH_LIBBACKTRACE TRUE) +#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=implicit-function-declaration -Werror=incompatible-function-pointer-types -Wall -fvisibility=hidden") +set_property(TARGET sentry PROPERTY C_VISIBILITY_PRESET hidden) +if(MSVC) + if(CMAKE_SIZEOF_VOID_P EQUAL 4) + set(CMAKE_ASM_MASM_FLAGS "${CMAKE_ASM_MASM_FLAGS} /safeseh") + endif() +else() + target_compile_options(sentry PUBLIC $) endif() -include_directories("include") -include_directories("src") - -file(GLOB_RECURSE SENTRY_NATIVE_TEST_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/tests/unit/*.c +target_include_directories(sentry PUBLIC + "$" + "$" + "$" ) +# Without this, dladdr can't find functions +# FIXME: cmake 3.13 introduced target_link_options +target_link_libraries(sentry INTERFACE + "$<$,$>:-Wl,--build-id=sha1>") + if(LINUX) - set(LINK_LIBRARIES ${LINK_LIBRARIES} "pthread" "dl") + target_link_libraries(sentry PRIVATE pthread dl) endif() if(WITH_LIBUNWINDSTACK) - include_directories(${CMAKE_CURRENT_SOURCE_DIR}/external/libunwindstack-ndk/include) - add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/external/libunwindstack-ndk/cmake) - set(LINK_LIBRARIES ${LINK_LIBRARIES} "unwindstack") + target_include_directories(sentry PRIVATE + "$") + add_subdirectory("${PROJECT_SOURCE_DIR}/external/libunwindstack-ndk/cmake") + target_link_libraries(sentry PRIVATE unwindstack) + if(NOT BUILD_SHARED_LIBS) + sentry_install(TARGETS unwindstack EXPORT sentry + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + endif() endif() if(WIN32) - set(LINK_LIBRARIES ${LINK_LIBRARIES} "dbghelp.lib" "pathcch.lib") -endif() - -SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) -SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}) -SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}) -SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) -SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}) -SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}) -SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) -SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}) -SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}) - -# builtin `list(TRANSFORM)` (https://cmake.org/cmake/help/latest/command/list.html#transform) -# was only added in cmake 3.12, but we target 3.10, so we define a custom -# functions which can prepend a prefix to all list elements. -# copied from https://stackoverflow.com/a/27630120 -FUNCTION(PREPEND var prefix) - SET(listVar "") - FOREACH(f ${ARGN}) - LIST(APPEND listVar "${prefix}/${f}") - ENDFOREACH(f) - SET(${var} "${listVar}" PARENT_SCOPE) -ENDFUNCTION(PREPEND) + target_link_libraries(sentry PRIVATE dbghelp pathcch) +endif() if(BACKEND_CRASHPAD) add_subdirectory(external/crashpad EXCLUDE_FROM_ALL) - include_directories(external/crashpad external/crashpad/third_party/mini_chromium/mini_chromium) - set(LINK_LIBRARIES ${LINK_LIBRARIES} crashpad_client crashpad_util) - install(TARGETS "crashpad_handler") + target_include_directories(sentry PRIVATE + "$" + "$" + ) + # FIXME: this should be applied to mini_chromium (or at least to crashpad_client/crashpad_handler) + target_compile_features(sentry PUBLIC cxx_std_11) + target_link_libraries(sentry PRIVATE crashpad_client crashpad_util) + if(NOT BUILD_SHARED_LIBS) + sentry_install(TARGETS crashpad_client crashpad_util crashpad_compat getopt mini_chromium zlib EXPORT sentry + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + endif() + sentry_install(TARGETS crashpad_handler + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + ) + add_dependencies(sentry crashpad_handler) elseif(BACKEND_BREAKPAD) add_subdirectory(external) - include_directories(external/breakpad/src) - # because breakpad has an include to `third_party/lss` - include_directories(external) - set(LINK_LIBRARIES ${LINK_LIBRARIES} breakpad_client) -endif() - -# ===== sentry library ===== - -add_library("sentry" "${CMAKE_CURRENT_SOURCE_DIR}/vendor/mpack.c") -add_subdirectory(src) - -set_target_properties("sentry" PROPERTIES PUBLIC_HEADER "include/sentry.h") -target_link_libraries("sentry" ${LINK_LIBRARIES}) -install(TARGETS "sentry" - ARCHIVE DESTINATION lib - LIBRARY DESTINATION lib - PUBLIC_HEADER DESTINATION include) - -# https://gitlab.kitware.com/cmake/cmake/issues/18393 -if(BUILD_SHARED_LIBS) - if(APPLE) - install(FILES "$.dSYM" DESTINATION lib) - elseif(WIN32) - install(FILES $ DESTINATION lib) + target_include_directories(sentry PRIVATE + "$" + ) + target_link_libraries(sentry PRIVATE + breakpad_client + ) + if(NOT BUILD_SHARED_LIBS) + sentry_install(TARGETS breakpad_client EXPORT sentry + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) endif() -endif() -if(BACKEND_CRASHPAD) - add_dependencies("sentry" "crashpad_handler") +elseif(BACKEND_INPROC) + target_compile_definitions(sentry PRIVATE SENTRY_WITH_INPROC_BACKEND) endif() -# ===== tests ===== +include(CMakePackageConfigHelpers) +configure_package_config_file(sentry-config.cmake.in sentry-config.cmake + INSTALL_DESTINATION "${CMAKE_INSTALL_CMAKEDIR}") -# compile tests separately and pass an extra preprocessor define so we can -# switch some internal modes for the unittests. -get_target_property(SENTRY_NATIVE_ALL_SOURCES sentry SOURCES) -add_executable("sentry_test_unit" EXCLUDE_FROM_ALL - ${SENTRY_NATIVE_ALL_SOURCES} - ${SENTRY_NATIVE_TEST_SOURCES} +sentry_install(TARGETS sentry EXPORT sentry + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" + PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" ) -get_target_property(SENTRY_DEFS sentry COMPILE_DEFINITIONS) -target_compile_definitions("sentry_test_unit" PUBLIC SENTRY_UNITTEST ${SENTRY_DEFS}) -target_link_libraries("sentry_test_unit" ${LINK_LIBRARIES}) +sentry_install(EXPORT sentry NAMESPACE sentry:: FILE sentry-targets.cmake + DESTINATION "${CMAKE_INSTALL_CMAKEDIR}") +sentry_install(FILES "${PROJECT_BINARY_DIR}/sentry-config.cmake" + DESTINATION "${CMAKE_INSTALL_CMAKEDIR}") -# to fix some issues with tests (dladdr can't find functions otherwise) -if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "Android") - target_link_libraries("sentry_test_unit" "-Wl,--build-id=sha1,-E") -endif() +# ===== tests ===== -if(BACKEND_CRASHPAD) - add_dependencies("sentry_test_unit" "crashpad_handler") +if(SENTRY_BUILD_TESTS) + add_subdirectory(tests/unit) endif() # ===== example, also used as integration test ===== -add_executable("sentry_example" EXCLUDE_FROM_ALL "./examples/example.c") -target_link_libraries("sentry_example" "sentry") +if(SENTRY_BUILD_EXAMPLES) + add_executable(sentry_example examples/example.c) + target_link_libraries(sentry_example sentry) + add_test(NAME sentry_example COMMAND sentry_example) +endif() diff --git a/README.md b/README.md index be29fc88a..7619dab05 100644 --- a/README.md +++ b/README.md @@ -113,11 +113,11 @@ using `cmake -D BUILD_SHARED_LIBS=OFF ..`. `OFF` will build `sentry` as a static library instead. - `SENTRY_BACKEND` (Default: depending on platform): Sentry can use different backends depending on platform. - **crashpad**: This uses the out-of-process crashpad handler. It is currently + - **crashpad**: This uses the out-of-process crashpad handler. It is currently only supported on Windows and macOS, and used as the default there. - **inproc**: A small in-process handler which is supported on all platforms + - **inproc**: A small in-process handler which is supported on all platforms except Windows, and is used as default on Linux and Android. - **none**: This builds `sentry-native` without a backend, so it does not handle + - **none**: This builds `sentry-native` without a backend, so it does not handle crashes at all. It is primarily used for tests. ### Build Targets diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 0184c957f..afa6893a0 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -63,6 +63,8 @@ stages: -DCMAKE_TOOLCHAIN_FILE=$ANDROID_HOME/ndk/$(ANDROID_NDK)/build/cmake/android.toolchain.cmake \ -DANDROID_ABI=$(ANDROID_ARCH) \ -DANDROID_NATIVE_API_LEVEL=$(ANDROID_API) \ + -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=$PWD \ + -DSENTRY_CURL_SUPPORT=OFF \ .. cmake --build . --parallel --target sentry_test_unit displayName: Build diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 82ed8896e..41f638f97 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -1,55 +1,57 @@ if (LINUX OR ANDROID) # The list is copied from: https://github.com/google/breakpad/blob/c7522272ffafa9b162f135aaee5d02a8895fcb0b/Makefile.am#L153-L188 list(APPEND BREAKPAD_SOURCES - src/client/linux/crash_generation/crash_generation_client.cc - src/client/linux/crash_generation/crash_generation_server.cc - src/client/linux/dump_writer_common/thread_info.cc - src/client/linux/dump_writer_common/ucontext_reader.cc - src/client/linux/handler/exception_handler.cc - src/client/linux/handler/exception_handler.h - src/client/linux/handler/minidump_descriptor.cc - src/client/linux/handler/minidump_descriptor.h - src/client/linux/log/log.cc - src/client/linux/log/log.h - src/client/linux/microdump_writer/microdump_writer.cc - src/client/linux/microdump_writer/microdump_writer.h - src/client/linux/minidump_writer/linux_core_dumper.cc - src/client/linux/minidump_writer/linux_dumper.cc - src/client/linux/minidump_writer/linux_ptrace_dumper.cc - src/client/linux/minidump_writer/minidump_writer.cc - src/client/minidump_file_writer-inl.h - src/client/minidump_file_writer.cc - src/client/minidump_file_writer.h - src/common/convert_UTF.cc - src/common/convert_UTF.h - src/common/md5.cc - src/common/md5.h - src/common/string_conversion.cc - src/common/string_conversion.h - src/common/linux/elf_core_dump.cc - src/common/linux/elfutils.cc - src/common/linux/elfutils.h - src/common/linux/file_id.cc - src/common/linux/file_id.h - src/common/linux/guid_creator.cc - src/common/linux/guid_creator.h - src/common/linux/linux_libc_support.cc - src/common/linux/memory_mapped_file.cc - src/common/linux/safe_readlink.cc + breakpad/src/client/linux/crash_generation/crash_generation_client.cc + breakpad/src/client/linux/crash_generation/crash_generation_server.cc + breakpad/src/client/linux/dump_writer_common/thread_info.cc + breakpad/src/client/linux/dump_writer_common/ucontext_reader.cc + breakpad/src/client/linux/handler/exception_handler.cc + breakpad/src/client/linux/handler/exception_handler.h + breakpad/src/client/linux/handler/minidump_descriptor.cc + breakpad/src/client/linux/handler/minidump_descriptor.h + breakpad/src/client/linux/log/log.cc + breakpad/src/client/linux/log/log.h + breakpad/src/client/linux/microdump_writer/microdump_writer.cc + breakpad/src/client/linux/microdump_writer/microdump_writer.h + breakpad/src/client/linux/minidump_writer/linux_core_dumper.cc + breakpad/src/client/linux/minidump_writer/linux_dumper.cc + breakpad/src/client/linux/minidump_writer/linux_ptrace_dumper.cc + breakpad/src/client/linux/minidump_writer/minidump_writer.cc + breakpad/src/client/minidump_file_writer-inl.h + breakpad/src/client/minidump_file_writer.cc + breakpad/src/client/minidump_file_writer.h + breakpad/src/common/convert_UTF.cc + breakpad/src/common/convert_UTF.h + breakpad/src/common/md5.cc + breakpad/src/common/md5.h + breakpad/src/common/string_conversion.cc + breakpad/src/common/string_conversion.h + breakpad/src/common/linux/elf_core_dump.cc + breakpad/src/common/linux/elfutils.cc + breakpad/src/common/linux/elfutils.h + breakpad/src/common/linux/file_id.cc + breakpad/src/common/linux/file_id.h + breakpad/src/common/linux/guid_creator.cc + breakpad/src/common/linux/guid_creator.h + breakpad/src/common/linux/linux_libc_support.cc + breakpad/src/common/linux/memory_mapped_file.cc + breakpad/src/common/linux/safe_readlink.cc ) endif() if (ANDROID) list(APPEND BREAKPAD_SOURCES - src/common/android/breakpad_getcontext.S + breakpad/src/common/android/breakpad_getcontext.S ) endif() -PREPEND(BREAKPAD_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/breakpad/" ${BREAKPAD_SOURCES}) - -add_library(breakpad_client EXCLUDE_FROM_ALL STATIC ${BREAKPAD_SOURCES}) +add_library(breakpad_client STATIC ${BREAKPAD_SOURCES}) set_property(TARGET breakpad_client PROPERTY POSITION_INDEPENDENT_CODE ON) -target_include_directories(breakpad_client PRIVATE "breakpad/src/") # breakpad has includes directly to `third_party/lss/...`, # which are being resolved correctly when we add the current directory to # the include directories. A giant hack, yes, but it works -target_include_directories(breakpad_client PRIVATE ".") +target_include_directories(breakpad_client + PRIVATE + "$" + PUBLIC + "$" +) diff --git a/sentry-config.cmake.in b/sentry-config.cmake.in new file mode 100644 index 000000000..455d76c5d --- /dev/null +++ b/sentry-config.cmake.in @@ -0,0 +1,14 @@ +set(SENTRY_BACKEND @SENTRY_BACKEND@) +set(SENTRY_CURL_SUPPORT @SENTRY_CURL_SUPPORT@) + +include("${CMAKE_CURRENT_LIST_DIR}/sentry-targets.cmake") + +if(SENTRY_CURL_SUPPORT AND NOT @BUILD_SHARED_LIBS@) + find_package(CURL REQUIRED) + set_property(TARGET sentry::sentry APPEND + PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${CURL_INCLUDE_DIRS}) + set_property(TARGET sentry::sentry APPEND + PROPERTY INTERFACE_LINK_LIBRARIES ${CURL_LIBRARIES}) +endif() + +@PACKAGE_INIT@ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3d2ec7a2b..eba36eb41 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,133 +1,128 @@ -list(APPEND SENTRY_SOURCES - sentry_alloc.c - sentry_alloc.h - sentry_backend.c - sentry_backend.h - sentry_boot.h - sentry_core.c - sentry_core.h - sentry_database.c - sentry_database.h - sentry_envelope.c - sentry_envelope.h - sentry_json.c - sentry_json.h - sentry_modulefinder.h - sentry_path.h - sentry_random.c - sentry_random.h - sentry_scope.c - sentry_scope.h - sentry_slice.c - sentry_slice.h - sentry_string.c - sentry_string.h - sentry_symbolizer.h - sentry_sync.c - sentry_sync.h - sentry_transport.c - sentry_transport.h - sentry_utils.c - sentry_utils.h - sentry_uuid.c - sentry_uuid.h - sentry_value.c - sentry_value.h - path/sentry_path.c - transports/sentry_disk_transport.c - transports/sentry_disk_transport.h - transports/sentry_function_transport.c - transports/sentry_function_transport.h - unwinder/sentry_unwinder.c +sentry_target_sources_cwd(sentry + sentry_alloc.c + sentry_alloc.h + sentry_backend.c + sentry_backend.h + sentry_boot.h + sentry_core.c + sentry_core.h + sentry_database.c + sentry_database.h + sentry_envelope.c + sentry_envelope.h + sentry_json.c + sentry_json.h + sentry_modulefinder.h + sentry_path.h + sentry_random.c + sentry_random.h + sentry_scope.c + sentry_scope.h + sentry_slice.c + sentry_slice.h + sentry_string.c + sentry_string.h + sentry_symbolizer.h + sentry_sync.c + sentry_sync.h + sentry_transport.c + sentry_transport.h + sentry_utils.c + sentry_utils.h + sentry_uuid.c + sentry_uuid.h + sentry_value.c + sentry_value.h + path/sentry_path.c + transports/sentry_disk_transport.c + transports/sentry_disk_transport.h + transports/sentry_function_transport.c + transports/sentry_function_transport.h + unwinder/sentry_unwinder.c ) # generic platform / path / symbolizer if(WIN32) - list(APPEND SENTRY_SOURCES - sentry_windows_dbghelp.c - sentry_windows_dbghelp.h - path/sentry_path_windows.c - symbolizer/sentry_symbolizer_windows.c - ) + sentry_target_sources_cwd(sentry + sentry_windows_dbghelp.c + sentry_windows_dbghelp.h + path/sentry_path_windows.c + symbolizer/sentry_symbolizer_windows.c + ) else() - list(APPEND SENTRY_SOURCES - sentry_unix_pageallocator.c - sentry_unix_pageallocator.h - sentry_unix_spinlock.h - path/sentry_path_unix.c - symbolizer/sentry_symbolizer_unix.c - ) + sentry_target_sources_cwd(sentry + sentry_unix_pageallocator.c + sentry_unix_pageallocator.h + sentry_unix_spinlock.h + path/sentry_path_unix.c + symbolizer/sentry_symbolizer_unix.c + ) endif() # module finder if(WIN32) - list(APPEND SENTRY_SOURCES - modulefinder/sentry_modulefinder_windows.c - ) + sentry_target_sources_cwd(sentry + modulefinder/sentry_modulefinder_windows.c + ) elseif(APPLE) - list(APPEND SENTRY_SOURCES - modulefinder/sentry_modulefinder_apple.c - ) + sentry_target_sources_cwd(sentry + modulefinder/sentry_modulefinder_apple.c + ) elseif(LINUX OR ANDROID) - list(APPEND SENTRY_SOURCES - modulefinder/sentry_modulefinder_linux.c - ) + sentry_target_sources_cwd(sentry + modulefinder/sentry_modulefinder_linux.c + ) endif() # curl transport -if(WITH_CURL) - list(APPEND SENTRY_SOURCES - transports/sentry_libcurl_transport.c - transports/sentry_libcurl_transport.h - ) +if(SENTRY_CURL_SUPPORT) + sentry_target_sources_cwd(sentry + transports/sentry_libcurl_transport.c + transports/sentry_libcurl_transport.h + ) endif() if(WIN32) - list(APPEND SENTRY_SOURCES - transports/sentry_winhttp_transport.c - transports/sentry_winhttp_transport.h - ) + sentry_target_sources_cwd(sentry + transports/sentry_winhttp_transport.c + transports/sentry_winhttp_transport.h + ) endif() # backends if(BACKEND_CRASHPAD) - list(APPEND SENTRY_SOURCES + sentry_target_sources_cwd(sentry backends/sentry_backend_crashpad.cpp ) elseif(BACKEND_BREAKPAD) - list(APPEND SENTRY_SOURCES + sentry_target_sources_cwd(sentry backends/sentry_backend_breakpad.cpp ) elseif(BACKEND_INPROC) - list(APPEND SENTRY_SOURCES + sentry_target_sources_cwd(sentry backends/sentry_backend_inproc.c ) elseif(BACKEND_NONE) - list(APPEND SENTRY_SOURCES + sentry_target_sources_cwd(sentry backends/sentry_backend_none.c ) endif() # unwinder if(WITH_LIBBACKTRACE) - target_compile_definitions(sentry PUBLIC SENTRY_WITH_UNWINDER_LIBBACKTRACE) - list(APPEND SENTRY_SOURCES - unwinder/sentry_unwinder_libbacktrace.c - ) + target_compile_definitions(sentry PUBLIC SENTRY_WITH_UNWINDER_LIBBACKTRACE) + sentry_target_sources_cwd(sentry + unwinder/sentry_unwinder_libbacktrace.c + ) endif() if(WITH_LIBUNWINDSTACK) - target_compile_definitions(sentry PUBLIC SENTRY_WITH_UNWINDER_LIBUNWINDSTACK) - list(APPEND SENTRY_SOURCES - unwinder/sentry_unwinder_libunwindstack.cpp - ) + target_compile_definitions(sentry PUBLIC SENTRY_WITH_UNWINDER_LIBUNWINDSTACK) + sentry_target_sources_cwd(sentry + unwinder/sentry_unwinder_libunwindstack.cpp + ) endif() if(WIN32) - target_compile_definitions(sentry PUBLIC SENTRY_WITH_UNWINDER_DBGHELP) - list(APPEND SENTRY_SOURCES - unwinder/sentry_unwinder_dbghelp.c - ) + target_compile_definitions(sentry PUBLIC SENTRY_WITH_UNWINDER_DBGHELP) + sentry_target_sources_cwd(sentry + unwinder/sentry_unwinder_dbghelp.c + ) endif() - -# make paths absolute -PREPEND(SENTRY_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/" ${SENTRY_SOURCES}) -get_target_property(SENTRY_OLD_SOURCES sentry SOURCES) -target_sources(sentry PRIVATE ${SENTRY_OLD_SOURCES} ${SENTRY_SOURCES}) diff --git a/src/path/sentry_path_windows.c b/src/path/sentry_path_windows.c index a4720d17e..bdd50b04d 100644 --- a/src/path/sentry_path_windows.c +++ b/src/path/sentry_path_windows.c @@ -6,8 +6,8 @@ #include "sentry_string.h" #include "sentry_utils.h" -#include -#include +#include +#include #include #include #include diff --git a/src/sentry_boot.h b/src/sentry_boot.h index ae1325cf6..b861950dc 100644 --- a/src/sentry_boot.h +++ b/src/sentry_boot.h @@ -21,10 +21,16 @@ // make sure on windows we pull in a minimal Windows.h #if defined(_WIN32) -# define WIN32_LEAN_AND_MEAN -# define NOMINMAX -# define _CRT_SECURE_NO_WARNINGS -# include +# if !defined(WIN32_LEAN_AND_MEAN) +# define WIN32_LEAN_AND_MEAN +# endif +# if !defined(NOMINMAX) +# define NOMINMAX +# endif +# if !defined(_CRT_SECURE_NO_WARNINGS) +# define _CRT_SECURE_NO_WARNINGS +# endif +# include #endif #include diff --git a/src/transports/sentry_winhttp_transport.c b/src/transports/sentry_winhttp_transport.c index 880fe882a..cd2003991 100644 --- a/src/transports/sentry_winhttp_transport.c +++ b/src/transports/sentry_winhttp_transport.c @@ -6,7 +6,7 @@ #include "sentry_string.h" #include "sentry_sync.h" -#include +#include #include #include diff --git a/tests/__init__.py b/tests/__init__.py index e2f54c01c..324f34cb4 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -15,10 +15,17 @@ def check_output(*args, **kwargs): stdout = stdout.replace(b"\r\n", b"\n") return stdout -def cmake(cwd, targets, options=[]): +def cmake(cwd, targets, options=None): + if options is None: + options = {} + options.update({ + "CMAKE_RUNTIME_OUTPUT_DIRECTORY": cwd, + "CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG": cwd, + "CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE": cwd, + }) configcmd = ["cmake"] - for option in options: - configcmd.extend(["-D", option]) + for key, value in options.items(): + configcmd.extend(["-D{}={}".format(key, value)]) configcmd.append(os.getcwd()) print("\n{} > {}".format(cwd, " ".join(configcmd)), flush=True) subprocess.run(configcmd, cwd=cwd, check=True) diff --git a/tests/conftest.py b/tests/conftest.py index 6be3d6b2c..2d6de44e7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,8 +1,5 @@ import pytest -import subprocess -import os import re -import sys from . import cmake, run def enumerate_unittests(): @@ -23,7 +20,7 @@ class Unittests: def __init__(self, dir): # for unit tests, the backend does not matter, and we want to keep # the compile-times down - cmake(dir, ["sentry_test_unit"], ["SENTRY_BACKEND=none"]) + cmake(dir, ["sentry_test_unit"], {"SENTRY_BACKEND":"none", "SENTRY_CURL_SUPPORT":"OFF",}) self.dir = dir def run(self, test): run(self.dir, "sentry_test_unit", ["--quiet", test], check=True) diff --git a/tests/test_integration.py b/tests/test_integration.py index f70b5b252..371459b32 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -1,7 +1,6 @@ import pytest import subprocess import sys -import json from . import cmake, check_output, run, Envelope # TODO: @@ -97,7 +96,7 @@ def assert_crash(envelope): def test_capture_stdout(tmp_path): # backend does not matter, but we want to keep compile times down - cmake(tmp_path, ["sentry_example"], ["SENTRY_BACKEND=none", "BUILD_SHARED_LIBS=OFF"]) + cmake(tmp_path, ["sentry_example"], {"SENTRY_BACKEND": "none", "BUILD_SHARED_LIBS":"OFF", "SENTRY_CURL_SUPPORT":"OFF"}) # on linux we can use `ldd` to check that we don’t link to `libsentry.so` if sys.platform == "linux": @@ -116,7 +115,7 @@ def test_capture_stdout(tmp_path): @pytest.mark.skipif(sys.platform == "win32", reason="no inproc backend on windows") def test_inproc_enqueue_stdout(tmp_path): - cmake(tmp_path, ["sentry_example"], ["SENTRY_BACKEND=inproc"]) + cmake(tmp_path, ["sentry_example"], {"SENTRY_BACKEND":"inproc","SENTRY_CURL_SUPPORT":"OFF"}) child = run(tmp_path, "sentry_example", ["attachment", "crash"]) assert child.returncode # well, its a crash after all @@ -132,7 +131,7 @@ def test_inproc_enqueue_stdout(tmp_path): @pytest.mark.skipif(sys.platform != "linux", reason="breakpad only supported on linux") def test_breakpad_enqueue_stdout(tmp_path): - cmake(tmp_path, ["sentry_example"], ["SENTRY_BACKEND=breakpad"]) + cmake(tmp_path, ["sentry_example"], {"SENTRY_BACKEND":"breakpad","SENTRY_CURL_SUPPORT":"OFF"}) child = run(tmp_path, "sentry_example", ["attachment", "crash"]) assert child.returncode # well, its a crash after all @@ -149,4 +148,4 @@ def test_breakpad_enqueue_stdout(tmp_path): @pytest.mark.skipif(sys.platform == "linux" or sys.platform == "win32", reason="crashpad not supported on linux, building is broken in VS2017") def test_crashpad_build(tmp_path): - cmake(tmp_path, ["sentry_example"], ["SENTRY_BACKEND=crashpad"]) + cmake(tmp_path, ["sentry_example"], {"SENTRY_BACKEND":"crashpad","SENTRY_CURL_SUPPORT":"OFF"}) diff --git a/tests/test_unit.py b/tests/test_unit.py index b0c62a336..cb8cc37bc 100644 --- a/tests/test_unit.py +++ b/tests/test_unit.py @@ -1,4 +1,3 @@ -import subprocess def test_unit(unittests, unittest): unittests.run(unittest) diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt new file mode 100644 index 000000000..c6710ed0a --- /dev/null +++ b/tests/unit/CMakeLists.txt @@ -0,0 +1,51 @@ +function(sentry_get_property NAME) + get_target_property(prop sentry "${NAME}") + if(NOT prop) + set(prop) + endif() + set("SENTRY_${NAME}" "${prop}" PARENT_SCOPE) +endfunction() + +sentry_get_property(SOURCES) +sentry_get_property(COMPILE_DEFINITIONS) +sentry_get_property(INTERFACE_INCLUDE_DIRECTORIES) +sentry_get_property(INCLUDE_DIRECTORIES) +sentry_get_property(LINK_LIBRARIES) +sentry_get_property(INTERFACE_LINK_LIBRARIES) + +add_executable(sentry_test_unit + ${SENTRY_SOURCES} + main.c + sentry_testsupport.h + test_attachments.c + test_basic.c + test_consent.c + test_database.c + test_envelopes.c + test_modulefinder.c + test_path.c + tests.inc + test_slice.c + test_symbolizer.c + test_sync.c + test_unwinder.c + test_utils.c + test_uuid.c + test_value.c +) + +# FIXME: cmake 3.13 introduced target_link_options +target_compile_definitions(sentry_test_unit PRIVATE ${SENTRY_COMPILE_DEFINITIONS}) +target_include_directories(sentry_test_unit PRIVATE + ${SENTRY_INTERFACE_INCLUDE_DIRECTORIES} + ${SENTRY_INCLUDE_DIRECTORIES} +) +target_link_libraries(sentry_test_unit PRIVATE + ${SENTRY_LINK_LIBRARIES} + ${SENTRY_INTERFACE_LINK_LIBRARIES} + "$<$,$>:-Wl,-E>" +) + +target_compile_definitions(sentry_test_unit PRIVATE SENTRY_UNITTEST) + +add_test(NAME sentry_test_unit COMMAND sentry_test_unit)