From 51ec64470e200dec51580dc92bcd7158048c100e Mon Sep 17 00:00:00 2001 From: alves Date: Fri, 5 Dec 2025 13:06:46 +0800 Subject: [PATCH] feature merge mac sentry to win platform. --- CMakeLists.txt | 19 ++++++- build_release_vs2022.bat | 2 +- deps/CMakeLists.txt | 8 --- deps/Sentry/Sentry.cmake | 58 +++++++++++++++++++--- src/CMakeLists.txt | 29 ++++++++++- src/Snapmaker_Orca.cpp | 12 ++++- src/sentry_wrapper/SentryWrapper.cpp | 74 +++++++++++++++++++--------- src/sentry_wrapper/SentryWrapper.hpp | 2 +- src/slic3r/GUI/Preferences.cpp | 5 ++ 9 files changed, 163 insertions(+), 46 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 13642a8cb2..d461af3025 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -543,7 +543,12 @@ find_package(TBB REQUIRED) find_package(OpenSSL REQUIRED) find_package(CURL REQUIRED) if (SLIC3R_SENTRY) - find_package(Sentry REQUIRED) + find_package(Sentry QUIET) + if (NOT Sentry_FOUND) + message(WARNING "Sentry SDK not found. SLIC3R_SENTRY will be disabled. " + "Build deps with Sentry support or use -DSLIC3R_SENTRY=OFF") + set(SLIC3R_SENTRY OFF CACHE BOOL "Enable Sentry crash reporting SDK" FORCE) + endif() endif() find_package(Freetype REQUIRED) @@ -569,7 +574,17 @@ if (SLIC3R_SENTRY) else() message(WARNING "sentry.lib not found in ${CMAKE_PREFIX_PATH}/lib. Sentry SDK may not have been built yet.") endif() - endif() + elseif (APPLE AND CMAKE_PREFIX_PATH) + # Try to find libsentry.dylib in the install prefix for macOS + file(GLOB _sentry_lib "${CMAKE_PREFIX_PATH}/lib/libsentry.dylib") + if (_sentry_lib) + target_link_directories(sentry INTERFACE "${CMAKE_PREFIX_PATH}/lib") + target_link_libraries(sentry INTERFACE "sentry") + message(STATUS "Found libsentry.dylib at: ${CMAKE_PREFIX_PATH}/lib") + else() + message(WARNING "libsentry.dylib not found in ${CMAKE_PREFIX_PATH}/lib. Sentry SDK may not have been built yet.") + endif() + endif() endif() # Fixing curl's cmake config script bugs diff --git a/build_release_vs2022.bat b/build_release_vs2022.bat index 488f02fe07..2724bf876f 100644 --- a/build_release_vs2022.bat +++ b/build_release_vs2022.bat @@ -47,7 +47,7 @@ if "%1"=="slicer" ( echo "building deps.." echo on -cmake ../ -G "Visual Studio 17 2022" -A x64 -DDESTDIR="%DEPS%" -DCMAKE_BUILD_TYPE=%build_type% -DDEP_DEBUG=%debug% -DORCA_INCLUDE_DEBUG_INFO=%debuginfo% +cmake ../ -G "Visual Studio 17 2022" -A x64 -DDESTDIR="%DEPS%" -DCMAKE_BUILD_TYPE=%build_type% -DDEP_DEBUG=%debug% -DORCA_INCLUDE_DEBUG_INFO=%debuginfo% -DSLIC3R_SENTRY=ON cmake --build . --config %build_type% --target deps -- -m @echo off diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index de9fae0bc5..126da82e8c 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -62,14 +62,6 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux") option(DEP_WX_GTK3 "Build wxWidgets against GTK3" OFF) endif() -# Sentry crash reporting - enabled only on Windows by default -if (WIN32) - set(SLIC3R_SENTRY_DEFAULT ON) -else() - set(SLIC3R_SENTRY_DEFAULT OFF) -endif() -option(SLIC3R_SENTRY "Enable Sentry crash reporting SDK" ${SLIC3R_SENTRY_DEFAULT}) - set(IS_CROSS_COMPILE FALSE) if (APPLE) diff --git a/deps/Sentry/Sentry.cmake b/deps/Sentry/Sentry.cmake index 91e49fc74b..f636281dbe 100644 --- a/deps/Sentry/Sentry.cmake +++ b/deps/Sentry/Sentry.cmake @@ -2,7 +2,7 @@ set(_sentry_platform_flags -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DSENTRY_BUILD_TESTS=OFF -DSENTRY_EXAMPLES=OFF - -DSENTRY_CRASHPAD_BACKEND=ON + -DSENTRY_BACKEND=crashpad -DSENTRY_ENABLE_INSTALL=ON ) @@ -25,16 +25,35 @@ if (WIN32) set(_sentry_cmake_generator -G "Visual Studio 17 2022") endif() elseif (APPLE) - # macOS: Use Unix Makefiles (install will put libs in ${DESTDIR}/bin or lib) + # macOS: build shared libs so we get libsentry.dylib + # Note: CURL transport requires OpenSSL, need to link it explicitly + # DESTDIR already contains /usr/local/ suffix, so use it directly set(_sentry_platform_flags ${_sentry_platform_flags} -DSENTRY_TRANSPORT_CURL=ON - -DSENTRY_BUILD_SHARED_LIBS=OFF + -DSENTRY_BUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo - -DCMAKE_C_FLAGS:STRING=-g -O2 - -DCMAKE_CXX_FLAGS:STRING=-g -O2 + -DOPENSSL_ROOT_DIR:PATH=${DESTDIR} + -DOPENSSL_USE_STATIC_LIBS:BOOL=ON + -DCMAKE_SHARED_LINKER_FLAGS:STRING=-L${DESTDIR}/lib\ -lssl\ -lcrypto ) set(_sentry_cmake_generator -G "Unix Makefiles") + + # Sentry/crashpad requires macOS 12.0+ due to kIOMainPortDefault API usage + # Force minimum deployment target to 12.0 for Sentry build + set(_sentry_osx_deployment_target "12.0") + if (CMAKE_OSX_DEPLOYMENT_TARGET AND CMAKE_OSX_DEPLOYMENT_TARGET VERSION_GREATER "12.0") + set(_sentry_osx_deployment_target ${CMAKE_OSX_DEPLOYMENT_TARGET}) + endif() + + # Add macOS architecture and deployment target for sentry build + if (CMAKE_OSX_ARCHITECTURES) + set(_sentry_platform_flags ${_sentry_platform_flags} -DCMAKE_OSX_ARCHITECTURES:STRING=${CMAKE_OSX_ARCHITECTURES}) + endif() + set(_sentry_platform_flags ${_sentry_platform_flags} -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=${_sentry_osx_deployment_target}) + if (CMAKE_OSX_SYSROOT) + set(_sentry_platform_flags ${_sentry_platform_flags} -DCMAKE_OSX_SYSROOT:STRING=${CMAKE_OSX_SYSROOT}) + endif() elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") # Linux: Use Unix Makefiles set(_sentry_platform_flags @@ -42,22 +61,45 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") -DSENTRY_TRANSPORT_CURL=ON -DSENTRY_BUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo - -DCMAKE_C_FLAGS:STRING=-g -O2 - -DCMAKE_CXX_FLAGS:STRING=-g -O2 ) set(_sentry_cmake_generator -G "Unix Makefiles") endif () +if(WIN32) + set(SENTRY_PATCH_COMMAND + ${GIT_EXECUTABLE} submodule update --init --recursive && ${CMAKE_COMMAND} -S external/crashpad -B external/crashpad/build ${_sentry_cmake_generator} -DCMAKE_BUILD_TYPE=Release && ${CMAKE_COMMAND} --build external/crashpad/build --config Release + ) +elseif(APPLE) + set(SENTRY_PATCH_COMMAND + ${GIT_EXECUTABLE} submodule update --init --recursive + ) +else() + set(SENTRY_PATCH_COMMAND + ${GIT_EXECUTABLE} submodule update --init --recursive + ) +endif() + Snapmaker_Orca_add_cmake_project(Sentry GIT_REPOSITORY https://github.com/getsentry/sentry-native.git GIT_TAG 0.12.1 - PATCH_COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive && ${CMAKE_COMMAND} -S external/crashpad -B external/crashpad/build ${_sentry_cmake_generator} -DCMAKE_BUILD_TYPE=Release && ${CMAKE_COMMAND} --build external/crashpad/build --config Release + PATCH_COMMAND ${SENTRY_PATCH_COMMAND} CMAKE_ARGS ${_sentry_cmake_generator} -DCMAKE_INSTALL_DATADIR:STRING=share ${_sentry_platform_flags} ) +# Sentry depends on CURL which depends on OpenSSL +# Ensure they are built before Sentry +if(APPLE) + if (TARGET dep_CURL) + add_dependencies(dep_Sentry dep_CURL) + endif() + if (TARGET dep_OpenSSL) + add_dependencies(dep_Sentry dep_OpenSSL) + endif() +endif() + if (MSVC) add_debug_dep(dep_Sentry) endif () diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ca9e209e0c..2e07f3929a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -117,7 +117,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/dev-utils/platform/osx/Info.plist.in if (WIN32) add_library(Snapmaker_Orca SHARED Snapmaker_Orca.cpp Snapmaker_Orca.hpp dev-utils/BaseException.cpp dev-utils/BaseException.h dev-utils/StackWalker.cpp dev-utils/StackWalker.h sentry_wrapper/SentryWrapper.hpp sentry_wrapper/SentryWrapper.cpp) else () - add_executable(Snapmaker_Orca Snapmaker_Orca.cpp Snapmaker_Orca.hpp) + add_executable(Snapmaker_Orca Snapmaker_Orca.cpp Snapmaker_Orca.hpp sentry_wrapper/SentryWrapper.hpp sentry_wrapper/SentryWrapper.cpp) endif () if (MINGW) @@ -159,6 +159,8 @@ target_link_libraries(Snapmaker_Orca libslic3r_gui) target_link_libraries(Snapmaker_Orca ws2_32 uxtheme setupapi) elseif (APPLE) target_link_libraries(Snapmaker_Orca "-framework OpenGL") + # Link Sentry for crash reporting on macOS + target_link_libraries(Snapmaker_Orca sentry::sentry) else () target_link_libraries(Snapmaker_Orca -ldl) endif () @@ -246,6 +248,16 @@ else () COMMAND ln -sf Snapmaker_Orca snapmaker-orca WORKING_DIRECTORY "$" VERBATIM) + # Copy Sentry crashpad_handler to executable directory for non-bundle builds (e.g., Xcode debugging) + add_custom_command(TARGET Snapmaker_Orca POST_BUILD + COMMAND sh -c "if [ -f '${CMAKE_PREFIX_PATH}/bin/crashpad_handler' ]; then cp -f '${CMAKE_PREFIX_PATH}/bin/crashpad_handler' '$/crashpad_handler' && codesign --force --sign - '$/crashpad_handler' 2>/dev/null || true; fi" + COMMENT "Copying crashpad_handler for Sentry crash reporting" + VERBATIM) + # Copy libsentry.dylib to executable directory for non-bundle builds + add_custom_command(TARGET Snapmaker_Orca POST_BUILD + COMMAND sh -c "if [ -f '${CMAKE_PREFIX_PATH}/lib/libsentry.dylib' ]; then cp -f '${CMAKE_PREFIX_PATH}/lib/libsentry.dylib' '$/libsentry.dylib' && codesign --force --sign - '$/libsentry.dylib' 2>/dev/null || true; fi" + COMMENT "Copying libsentry.dylib for Sentry crash reporting" + VERBATIM) else () add_custom_command(TARGET Snapmaker_Orca POST_BUILD WORKING_DIRECTORY "$" @@ -278,6 +290,21 @@ else () COMMAND ${CMAKE_COMMAND} -E create_symlink "${SLIC3R_RESOURCES_DIR}" "$/../Resources" COMMENT "Symlinking the resources directory into the build tree" VERBATIM) + # Copy Sentry crashpad_handler to MacOS directory (same directory as executable) + add_custom_command(TARGET Snapmaker_Orca POST_BUILD + COMMAND sh -c "if [ -f '${CMAKE_PREFIX_PATH}/bin/crashpad_handler' ]; then cp -f '${CMAKE_PREFIX_PATH}/bin/crashpad_handler' '$/crashpad_handler' && codesign --force --sign - '$/crashpad_handler'; fi" + COMMENT "Copying and signing crashpad_handler for Sentry crash reporting" + VERBATIM) + # Copy libsentry.dylib to Frameworks directory + add_custom_command(TARGET Snapmaker_Orca POST_BUILD + COMMAND sh -c "if [ -f '${CMAKE_PREFIX_PATH}/lib/libsentry.dylib' ]; then mkdir -p '$/../Frameworks' && cp -f '${CMAKE_PREFIX_PATH}/lib/libsentry.dylib' '$/../Frameworks/libsentry.dylib' && codesign --force --sign - '$/../Frameworks/libsentry.dylib'; fi" + COMMENT "Copying and signing libsentry.dylib for Sentry crash reporting" + VERBATIM) + # Update the rpath for libsentry.dylib + add_custom_command(TARGET Snapmaker_Orca POST_BUILD + COMMAND install_name_tool -change "@rpath/libsentry.dylib" "@executable_path/../Frameworks/libsentry.dylib" "$" || true + COMMENT "Updating rpath for libsentry.dylib" + VERBATIM) endif() endif () diff --git a/src/Snapmaker_Orca.cpp b/src/Snapmaker_Orca.cpp index 60176d5c3a..1b1c197a4f 100644 --- a/src/Snapmaker_Orca.cpp +++ b/src/Snapmaker_Orca.cpp @@ -33,6 +33,10 @@ using namespace nlohmann; #endif +#ifdef SLIC3R_SENTRY +#include "sentry_wrapper/SentryWrapper.hpp" +#endif + #include #include #include @@ -6291,6 +6295,12 @@ extern "C" { #else /* _MSC_VER */ int main(int argc, char **argv) { - return CLI().run(argc, argv); + initSentry(); + + auto res = CLI().run(argc, argv); + + exitSentry(); + + return res; } #endif /* _MSC_VER */ diff --git a/src/sentry_wrapper/SentryWrapper.cpp b/src/sentry_wrapper/SentryWrapper.cpp index 1103fbb420..613ca3dda4 100644 --- a/src/sentry_wrapper/SentryWrapper.cpp +++ b/src/sentry_wrapper/SentryWrapper.cpp @@ -10,14 +10,19 @@ #ifdef SLIC3R_SENTRY #include "sentry.h" +#endif #ifdef _WIN32 #include #include #endif +#ifdef __APPLE__ +#include +#include #endif +#include #include namespace Slic3r { @@ -36,41 +41,60 @@ static sentry_value_t on_crash_callback(const sentry_ucontext_t* uctx, sentry_va void initSentryEx() { sentry_options_t* options = sentry_options_new(); + std::string dsn = ""; { -#ifdef WIN32 +#ifdef __APPLE__ + + std::string dsn = std::string("https://ac473187efb8877f36bd31694ffd5dec@o4508125599563776.ingest.us.sentry.io/4510425212059648"); + +#elif _WIN32 std::string dsn = std::string("https://c74b617c2aedc291444d3a238d23e780@o4508125599563776.ingest.us.sentry.io/4510425163956224"); - +#endif sentry_options_set_dsn(options, dsn.c_str()); + std::string handlerDir = ""; + std::string dataBaseDir = ""; +#ifdef __APPLE__ + + char exe_path[PATH_MAX] = {0}; + uint32_t buf_size = PATH_MAX; + + if (_NSGetExecutablePath(exe_path, &buf_size) != 0) { + throw std::runtime_error("Buffer too small for executable path"); + } + + // Get the directory containing the executable, not the executable path itself + boost::filesystem::path exe_dir = boost::filesystem::path(exe_path).parent_path(); + handlerDir = (exe_dir / "crashpad_handler").string(); + + const char* home_env = getenv("HOME"); + + dataBaseDir = home_env; + dataBaseDir = dataBaseDir + "/Library/Application Support/Snapmaker_Orca/SentryData"; +#elif _WIN32 wchar_t exeDir[MAX_PATH]; ::GetModuleFileNameW(nullptr, exeDir, MAX_PATH); std::wstring wsExeDir(exeDir); int nPos = wsExeDir.find_last_of('\\'); std::wstring wsDmpDir = wsExeDir.substr(0, nPos + 1); - - std::wstring handlerDir = wsDmpDir + L"crashpad_handler.exe"; + std::wstring desDir = wsDmpDir + L"crashpad_handler.exe"; wsDmpDir += L"dump"; auto wstringTostring = [](std::wstring wTmpStr) -> std::string { std::string resStr = std::string(); int len = WideCharToMultiByte(CP_UTF8, 0, wTmpStr.c_str(), -1, nullptr, 0, nullptr, nullptr); - if (len <= 0) return std::string(); + std::string desStr(len, 0); - WideCharToMultiByte(CP_UTF8, 0, wTmpStr.c_str(), -1, &desStr[0], len, nullptr, nullptr); - resStr = desStr; return resStr; }; - std::string desDir = wstringTostring(handlerDir); - if (!desDir.empty()) - sentry_options_set_handler_path(options, desDir.c_str()); - desDir = wstringTostring(wsDmpDir); - desDir = wstringTostring(wsDmpDir); + handlerDir = wstringTostring(desDir); + wchar_t appDataPath[MAX_PATH] = {0}; auto hr = SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, appDataPath); char* path = new char[MAX_PATH]; @@ -78,13 +102,16 @@ void initSentryEx() wcstombs_s(&pathLength, path, MAX_PATH, appDataPath, MAX_PATH); std::string filePath = path; std::string appName = "\\" + std::string("Snapmaker_Orca\\"); - filePath = filePath + appName; - - if (!filePath.empty()) - sentry_options_set_database_path(options, filePath.c_str()); + dataBaseDir = filePath + appName; #endif + + if (!handlerDir.empty()) + sentry_options_set_handler_path(options, handlerDir.c_str()); + + if (!dataBaseDir.empty()) + sentry_options_set_database_path(options, dataBaseDir.c_str()); + std::string softVersion = "snapmaker_orca_2.2.0_beta2"; - // Snapmaker_VERSION sentry_options_set_release(options, softVersion.c_str()); #if defined(_DEBUG) || !defined(NDEBUG) @@ -92,17 +119,16 @@ void initSentryEx() #else sentry_options_set_debug(options, 0); #endif - // release version environment(Testing/production/development/Staging) + sentry_options_set_environment(options, "develop"); - sentry_options_set_auto_session_tracking(options, false); - sentry_options_set_symbolize_stacktraces(options, true); + + sentry_options_set_auto_session_tracking(options, 0); + sentry_options_set_symbolize_stacktraces(options, 1); sentry_options_set_on_crash(options, on_crash_callback, NULL); - // Enable before_send hook for filtering sensitive data sentry_options_set_before_send(options, NULL, NULL); - // Ensure all events and crashes are captured (sample rate 100%) - sentry_options_set_sample_rate(options, 1.0); // Capture 100% of events - sentry_options_set_traces_sample_rate(options, 1.0); // Capture 100% of traces + sentry_options_set_sample_rate(options, 1.0); + sentry_options_set_traces_sample_rate(options, 1.0); sentry_init(options); sentry_start_session(); diff --git a/src/sentry_wrapper/SentryWrapper.hpp b/src/sentry_wrapper/SentryWrapper.hpp index 32f46f210d..29de368b0e 100644 --- a/src/sentry_wrapper/SentryWrapper.hpp +++ b/src/sentry_wrapper/SentryWrapper.hpp @@ -19,7 +19,7 @@ namespace Slic3r { }; void sentryReportLog(SENTRY_LOG_LEVEL logLevel, - const std::string& logContent, + const std::string& logContent, const std::string& funcModule = "", const std::string& logTagKey = "", const std::string& logTagValue = "", diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 9f6da051dd..e6accab238 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -1021,6 +1021,11 @@ PreferencesDialog::PreferencesDialog(wxWindow *parent, wxWindowID id, const wxSt : DPIDialog(parent, id, _L("Preferences"), pos, size, style) { SetBackgroundColour(*wxWHITE); + + wxPanel* pPanel = new wxPanel(nullptr); + delete pPanel; + delete pPanel; + create(); wxGetApp().UpdateDlgDarkUI(this); Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& event) {