Features: CrashReporter with Crashpad and Bugsplat.

This commit is contained in:
Julien Wadel 2025-01-22 17:40:38 +01:00
parent 1902fe3029
commit b562c529bc
36 changed files with 762 additions and 37 deletions

View file

@ -180,14 +180,22 @@ win64-ninja-vs2022-scheduled-windows:
needs: []
rules:
- !reference [.rules-merge-request-manual, rules]
- if: $NIGHTLY_MASTER
- if: $NIGHTLY_RELEASE
- if: $PACKAGE_WINDOWS
- if: $DEPLOY_WINDOWS
variables:
CMAKE_OPTIONS: -DENABLE_APP_PACKAGING=YES -DENABLE_G729=ON -DENABLE_PQCRYPTO=ON -DENABLE_GPL_THIRD_PARTIES=OFF
RELEASE_FILE: -DLINPHONE_SDK_MAKE_RELEASE_FILE_URL=$MAKE_RELEASE_FILE_URL/$WINDOWS_PLATFORM/$APP_FOLDER
.vs-win64-package-cr:
stage: package
needs: []
rules:
- if: $NIGHTLY_MASTER
- if: $DEPLOY_WINDOWS
variables:
CMAKE_OPTIONS: -DENABLE_APP_PACKAGING=YES -DENABLE_G729=ON -DENABLE_PQCRYPTO=ON -DENABLE_GPL_THIRD_PARTIES=OFF -DENABLE_BUGSPLAT_SYMBOLS_UPLOAD=ON -DBUGSPPLAT_CLIENT_ID=$BUGSPPLAT_CLIENT_ID -DBUGSPPLAT_CLIENT_SECRET=$BUGSPPLAT_CLIENT_SECRET
RELEASE_FILE: -DLINPHONE_SDK_MAKE_RELEASE_FILE_URL=$MAKE_RELEASE_FILE_URL/$WINDOWS_PLATFORM/$APP_FOLDER
win64-ninja-vs2022-package-windows:
variables:
CMAKE_GENERATOR: "Ninja"
@ -198,6 +206,18 @@ win64-ninja-vs2022-package-windows:
- .windows-ninja-variables
- .vs-win64-package
#Packaging for deployment (Upload symbols at the same time of the packaging)
win64-ninja-vs2022-package-cr-windows:
variables:
CMAKE_GENERATOR: "Ninja"
CMAKE_ARCHITECTURE: ""
PARALLEL_OPTIONS: ""
extends:
- .windows-vs2022
- .windows-ninja-variables
- .vs-win64-package-cr
#################################################
# SIGNING
#################################################
@ -213,8 +233,28 @@ win64-codesigning:
MINGW_TYPE: mingw64
rules:
- !reference [.rules-merge-request-manual, rules]
- if: $NIGHTLY_MASTER
- if: $PACKAGE_WINDOWS
script:
- cd build-desktop/OUTPUT/Packages/
- Invoke-Expression "& ${WINDOWS_SIGN_TOOL} sign /fd SHA256 /t ${WINDOWS_SIGN_TIMESTAMP_URL} /sha1 ${WINDOWS_SIGN_HASH} *.exe"
- 'if (-not ($LastExitCode -eq 0)) {throw "Error: Signature failed"}'
artifacts:
paths:
- build-desktop\OUTPUT\Packages\*
when: always
expire_in: 1 week
win64-codesigning-cr:
stage: signing
allow_failure: true
extends:
- .windows-codesigning
needs:
- win64-ninja-vs2022-package-cr-windows
variables:
MINGW_TYPE: mingw64
rules:
- if: $NIGHTLY_MASTER
- if: $DEPLOY_WINDOWS
script:
- cd build-desktop/OUTPUT/Packages/
@ -246,7 +286,7 @@ win64-ninja-vs2022-upload:
extends:
- .win64-upload
needs:
- win64-codesigning
- win64-codesigning-cr
.win64-plugins-upload:
stage: deploy

9
.gitmodules vendored
View file

@ -1,3 +1,12 @@
[submodule "linphone-sdk"]
path = external/linphone-sdk
url = https://gitlab.linphone.org/BC/public/linphone-sdk.git
[submodule "external/google/gn"]
path = external/google/gn
url = https://gitlab.linphone.org/BC/public/external/gn.git
[submodule "external/google/crashpad"]
path = external/google/crashpad
url = https://gitlab.linphone.org/BC/public/external/crashpad.git
[submodule "external/google/chromium-depot-tools"]
path = external/google/chromium-depot-tools
url = https://gitlab.linphone.org/BC/public/external/chromium-depot-tools.git

View file

@ -177,6 +177,7 @@ add_option(OPTION_LIST ENABLE_UNIT_TESTS "Enable unit test of SDK." OFF)
add_option(OPTION_LIST ENABLE_UPDATE_CHECK "Enable update check." ON)
add_option(OPTION_LIST ENABLE_VIDEO "Enable Video support." YES)
add_option(OPTION_LIST ENABLE_WINDOWS_TOOLS_CHECK "Enable tools checks on Windows for auto install." OFF)
add_option(OPTION_LIST ENABLE_CRASH_HANDLER "Enable Crash Handler" YES)
add_cache(OPTION_LIST LINPHONE_SDK_MAKE_RELEASE_FILE_URL "Make a RELEASE file that work along check_version and use this URL" "")
@ -184,6 +185,12 @@ add_cache(OPTION_LIST LINPHONE_SDK_MAKE_RELEASE_FILE_URL "Make a RELEASE file th
add_option(OPTION_LIST ENABLE_OPENH264 "Enable the use of OpenH264 codec" ${ENABLE_VIDEO})
add_option(OPTION_LIST ENABLE_SCREENSHARING "Enable screen sharing." ${ENABLE_VIDEO})
add_option(OPTION_LIST ENABLE_BUGSPLAT_SYMBOLS_UPLOAD "Generate and upload symbols to Bugsplat." OFF)
add_cache(OPTION_LIST BUGSPPLAT_CLIENT_ID "Client ID for Bugsplat." "")
add_cache(OPTION_LIST BUGSPPLAT_CLIENT_SECRET "Client Secret for Bugsplat." "")
# QtKeychain
add_option(OPTION_LIST LIBSECRET_SUPPORT "Build with libsecret support" OFF) # Need libsecret-devel
if(WIN32)
@ -226,8 +233,8 @@ if(LINPHONEAPP_BUILD_TYPE STREQUAL "Default")
endif()
if(NOT APPLE OR MONO_ARCH)
add_custom_target(linphone-deps)
if(NOT LINPHONE_QT_ONLY)
function(add_external)
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) # Prevent project from overriding the options we just set here
@ -235,6 +242,9 @@ if(NOT APPLE OR MONO_ARCH)
endfunction()
add_external()
endif()
if(TARGET Crashpad)
set(HAVE_CRASH_HANDLER 1)
endif()
function(add_linphone_app)
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) # Prevent project from overriding the options we just set here
if(UNIX)

View file

@ -96,15 +96,12 @@ else()
set(MSPLUGINS_DIR "${CMAKE_INSTALL_LIBDIR}/mediastreamer/plugins")
endif()
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake" "${CMAKE_CURRENT_BINARY_DIR}/config.h")
if(${Qt6_VERSION} VERSION_LESS "6.10.0")
message( FATAL_ERROR "Linphone requires Qt 6.10.0 or newer. Exiting CMake." )
endif()
qt6_standard_project_setup()
################################################################
# SOURCES
################################################################
@ -124,6 +121,7 @@ add_subdirectory(core)
set(LANGUAGES_DIRECTORY "data/languages")
set(I18N_FILENAME i18n.qrc)
set(LANGUAGES en fr de)
set(CMAKE_CPP_COMPILER gcc)
# Add languages support.
add_subdirectory("${LANGUAGES_DIRECTORY}" "data/languages")
@ -154,7 +152,7 @@ qt6_add_big_resources(_LINPHONEAPP_FONTS_FILES data/fonts.qrc)
list(APPEND _LINPHONEAPP_FONTS_FILES data/fonts.qrc)
set_property(SOURCE data/fonts.qrc PROPERTY SKIP_AUTORCC ON)
qt6_add_executable(Linphone
qt6_add_executable(${TARGET_NAME}
${_LINPHONEAPP_SOURCES}
${_LINPHONEAPP_FONTS_FILES}
${_APPDETAILS_RC_FILE}
@ -170,15 +168,19 @@ qt6_add_qml_module(Linphone
RESOURCES data/fonts.qrc
)
if (WIN32)
if(MSVC AND (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo"))
install(FILES "$<TARGET_PDB_FILE:${TARGET_NAME}>" DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
endif()
qt6_add_resources(Linphone "resources" PREFIX "/" FILES ${_LINPHONEAPP_RC_FILES})
set_property(TARGET Linphone PROPERTY POSITION_INDEPENDENT_CODE ON) #Need by Qt
################################################################
# CRASHPAD
################################################################
if (HAVE_CRASH_HANDLER)
add_dependencies(${TARGET_NAME} Crashpad)
target_link_libraries(${TARGET_NAME} PRIVATE Crashpad)
get_target_property(CRASHPAD_EXECUTABLE_NAME Crashpad CRASHPAD_EXECUTABLE_NAME)
endif()
################################################################
# TARGETS LINKS
################################################################
@ -223,3 +225,14 @@ foreach(T ${QT_PACKAGES})
endforeach()
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake" "${CMAKE_CURRENT_BINARY_DIR}/config.h")
if (WIN32)
if(MSVC AND (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo"))
install(FILES "$<TARGET_PDB_FILE:${TARGET_NAME}>" DESTINATION ${CMAKE_INSTALL_BINDIR})
foreach(T ${APP_TARGETS})
install(FILES "$<TARGET_PDB_FILE:${T}>" DESTINATION ${CMAKE_INSTALL_BINDIR})
endforeach ()
endif()
endif()

View file

@ -7,5 +7,6 @@ set(APPLICATION_LICENCE "GNU General Public License V3")
set(APPLICATION_LICENCE_URL "https://www.gnu.org/licenses/gpl-3.0.html")
set(APPLICATION_START_LICENCE "2010")
set(APPLICATION_SEMVER ${LINPHONEAPP_VERSION})
set(BUGSPLAT_DATABASE "Linphone")
set(EXECUTABLE_NAME ${LINPHONEAPP_EXECUTABLE_NAME})

View file

@ -39,3 +39,6 @@
#cmakedefine LINPHONEAPP_SHORT_VERSION "${LINPHONEAPP_SHORT_VERSION}"
#cmakedefine GIT_BRANCH_NAME "${GIT_BRANCH_NAME}"
#cmakedefine LINPHONESDK_VERSION "${LINPHONESDK_VERSION}"
#cmakedefine HAVE_CRASH_HANDLER "${HAVE_CRASH_HANDLER}"
#cmakedefine CRASHPAD_EXECUTABLE_NAME "${CRASHPAD_EXECUTABLE_NAME}"
#cmakedefine BUGSPLAT_DATABASE "${BUGSPLAT_DATABASE}"

View file

@ -101,6 +101,9 @@
#include "tool/accessibility/AccessibilityHelper.hpp"
#include "tool/accessibility/FocusHelper.hpp"
#include "tool/accessibility/KeyboardShortcuts.hpp"
#ifdef HAVE_CRASH_HANDLER
#include "tool/crash_reporter/CrashReporter.hpp"
#endif
#include "tool/native/DesktopTools.hpp"
#include "tool/providers/AvatarProvider.hpp"
#include "tool/providers/EmojiProvider.hpp"
@ -112,6 +115,7 @@
#include "tool/thread/Thread.hpp"
#include "tool/ui/DashRectangle.hpp"
#if defined(Q_OS_MACOS)
#include "core/event-count-notifier/EventCountNotifierMacOs.hpp"
#else
@ -291,6 +295,13 @@ App::App(int &argc, char *argv[])
QCoreApplication::setApplicationName(EXECUTABLE_NAME);
QApplication::setOrganizationDomain(EXECUTABLE_NAME);
QCoreApplication::setApplicationVersion(APPLICATION_SEMVER);
// CarshReporter must be call after app initialization like names.
#ifdef HAVE_CRASH_HANDLER
CrashReporter::start();
#else
lWarning() << "[Main] The application doesn't support the CrashReporter.";
#endif
// If not OpenGL, createRender is never call.
QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGL);
setWindowIcon(QIcon(Constants::WindowIconPath));
@ -491,7 +502,7 @@ App *App::getInstance() {
}
Thread *App::getLinphoneThread() {
return App::getInstance()->mLinphoneThread;
return App::getInstance() ? App::getInstance()->mLinphoneThread : nullptr;
}
Notifier *App::getNotifier() const {

View file

@ -139,6 +139,10 @@ static inline QString getAppPackagePluginsDirPath() {
return getAppPackageDir().absolutePath() + Constants::PathPlugins;
}
static inline QString getAppBinDirPath() {
return getAppPackageDir().absolutePath() + Constants::PathBin;
}
static inline QString getAppAssistantConfigDirPath() {
return getAppPackageDataDirPath() + Constants::PathAssistantConfig;
}
@ -283,6 +287,20 @@ QString Paths::getLogsDirPath() {
Constants::PathLogs);
}
QString Paths::getCrashpadDirPath() {
#ifdef HAVE_CRASH_HANDLER
return getWritableDirPath(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) +
Constants::PathCrashpad);
#else
return "";
#endif
}
QString Paths::getMetricsDirPath() {
return getWritableDirPath(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) +
Constants::PathMetrics);
}
QString Paths::getMessageHistoryFilePath() {
return getReadableFilePath(
getAppMessageHistoryFilePath()); // No need to ensure that the file exists as this DB is deprecated
@ -337,6 +355,14 @@ QString Paths::getZrtpSecretsFilePath() {
Constants::PathZrtpSecrets);
}
QString Paths::getCrashpadHandlerFilePath() {
#ifdef HAVE_CRASH_HANDLER
return getAppBinDirPath() + Constants::PathCrashpadHandler;
#else
return "";
#endif
}
// -----------------------------------------------------------------------------
void Paths::migrate() {

View file

@ -43,6 +43,8 @@ QString getFactoryConfigFilePath();
QString getFriendsListFilePath();
QString getLimeDatabasePath();
QString getLogsDirPath();
QString getCrashpadDirPath();
QString getMetricsDirPath();
QString getMessageHistoryFilePath();
QString getPackageDataDirPath();
QString getPackageMsPluginsDirPath();
@ -56,6 +58,7 @@ QString getToolsDirPath();
QString getUserCertificatesDirPath();
QString getZrtpDataFilePath();
QString getZrtpSecretsFilePath();
QString getCrashpadHandlerFilePath();
void migrate();
} // namespace Paths

View file

@ -97,6 +97,7 @@ SettingsCore::SettingsCore(QObject *parent) : QObject(parent) {
// Logs
mLogsEnabled = settingsModel->getLogsEnabled();
mFullLogsEnabled = settingsModel->getFullLogsEnabled();
mCrashReporterEnabled = settingsModel->getCrashReporterEnabled();
mLogsFolder = settingsModel->getLogsFolder();
mLogsEmail = settingsModel->getLogsEmail();
@ -189,6 +190,7 @@ SettingsCore::SettingsCore(const SettingsCore &settingsCore) {
// Logs
mLogsEnabled = settingsCore.mLogsEnabled;
mFullLogsEnabled = settingsCore.mFullLogsEnabled;
mCrashReporterEnabled = settingsCore.mCrashReporterEnabled;
mLogsFolder = settingsCore.mLogsFolder;
mLogsEmail = settingsCore.mLogsEmail;
@ -416,7 +418,10 @@ void SettingsCore::setSelf(QSharedPointer<SettingsCore> me) {
// Logs
mSettingsModelConnection->makeConnectToModel(&SettingsModel::logsEnabledChanged, [this](const bool status) {
mSettingsModelConnection->invokeToCore([this, status]() { setLogsEnabled(status); });
mSettingsModelConnection->invokeToCore([this, status]() {
setCrashReporterEnabled(status);
setLogsEnabled(status);
});
});
mSettingsModelConnection->makeConnectToModel(&SettingsModel::fullLogsEnabledChanged, [this](const bool status) {
@ -558,6 +563,7 @@ void SettingsCore::reset(const SettingsCore &settingsCore) {
// Logs
setLogsEnabled(settingsCore.mLogsEnabled);
setFullLogsEnabled(settingsCore.mFullLogsEnabled);
setCrashReporterEnabled(settingsCore.mCrashReporterEnabled);
setLogsFolder(settingsCore.mLogsFolder);
// DND
@ -1007,6 +1013,18 @@ void SettingsCore::setFullLogsEnabled(bool enabled) {
}
}
bool SettingsCore::getCrashReporterEnabled() const {
return mCrashReporterEnabled;
}
void SettingsCore::setCrashReporterEnabled(bool enabled) {
if (mCrashReporterEnabled != enabled) {
mCrashReporterEnabled = enabled;
emit crashReporterEnabledChanged();
setIsSaved(false);
}
}
void SettingsCore::setRingtone(QString path) {
if (mRingtonePath != path) {
mRingtonePath = path;
@ -1144,6 +1162,7 @@ void SettingsCore::writeIntoModel(std::shared_ptr<SettingsModel> model) const {
// Logs
model->setLogsEnabled(mLogsEnabled);
model->setFullLogsEnabled(mFullLogsEnabled);
model->setCrashReporterEnabled(mLogsEnabled);
// UI
model->setDisableChatFeature(mDisableChatFeature);
@ -1220,6 +1239,7 @@ void SettingsCore::writeFromModel(const std::shared_ptr<SettingsModel> &model) {
// Logs
mLogsEnabled = model->getLogsEnabled();
mFullLogsEnabled = model->getFullLogsEnabled();
mCrashReporterEnabled = model->getCrashReporterEnabled();
mLogsFolder = model->getLogsFolder();
mLogsEmail = model->getLogsEmail();

View file

@ -91,6 +91,7 @@ public:
Q_PROPERTY(bool logsEnabled READ getLogsEnabled WRITE setLogsEnabled NOTIFY logsEnabledChanged)
Q_PROPERTY(bool fullLogsEnabled READ getFullLogsEnabled WRITE setFullLogsEnabled NOTIFY fullLogsEnabledChanged)
Q_PROPERTY(bool crashReporterEnabled READ getCrashReporterEnabled WRITE setCrashReporterEnabled NOTIFY crashReporterEnabledChanged)
Q_PROPERTY(QString logsEmail READ getLogsEmail)
Q_PROPERTY(QString logsFolder READ getLogsFolder)
Q_PROPERTY(QString ringtoneName READ getRingtoneFileName NOTIFY ringtoneChanged)
@ -234,9 +235,10 @@ public:
bool getLogsEnabled() const;
void setLogsEnabled(bool enabled);
bool getFullLogsEnabled() const;
void setFullLogsEnabled(bool enabled);
bool getCrashReporterEnabled() const;
void setCrashReporterEnabled(bool enabled);
void setRingtone(QString path);
QString getRingtoneFileName() const;
@ -364,6 +366,7 @@ signals:
void logsEnabledChanged();
void fullLogsEnabledChanged();
void crashReporterEnabledChanged();
void logsUploadTerminated(bool status, QString url);
void logsFolderChanged(const QString &folder);
@ -439,6 +442,7 @@ private:
// Debug logs
bool mLogsEnabled;
bool mFullLogsEnabled;
bool mCrashReporterEnabled;
QString mLogsFolder;
QString mLogsEmail;

View file

@ -3,6 +3,8 @@
#include "core/App.hpp"
#include "core/logger/QtLogger.hpp"
#include "core/path/Paths.hpp"
#include <QLocale>
#include <QSurfaceFormat>
#include <QTranslator>
@ -22,12 +24,15 @@ FILE *gStream = NULL;
#define ACCESSBILITY_WORKAROUND
#include <QAccessible>
#include <QAccessibleEvent>
void DummyUpdateHandler(QAccessibleEvent *event) {
}
void DummyRootObjectHandler(QObject *) {
}
#endif
void cleanStream() {
#ifdef _WIN32
if (gStream) {
@ -39,6 +44,7 @@ void cleanStream() {
}
int main(int argc, char *argv[]) {
/*
#if defined _WIN32
// log in console only if launched from console
@ -48,6 +54,7 @@ int main(int argc, char *argv[]) {
}
#endif
*/
// Useful to share camera on Fullscreen (other context) or multiscreens
lDebug() << "[Main] Setting ShareOpenGLContexts";
QApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
@ -63,6 +70,7 @@ int main(int argc, char *argv[]) {
setlocale(LC_CTYPE, ".UTF8");
lDebug() << "[Main] Creating application";
auto app = QSharedPointer<App>::create(argc, argv);
#ifdef ACCESSBILITY_WORKAROUND
QAccessible::installUpdateHandler(DummyUpdateHandler);
QAccessible::installRootObjectHandler(DummyRootObjectHandler);

View file

@ -25,6 +25,9 @@
#include "model/tool/ToolModel.hpp"
// #include "model/tool/VfsUtils.hpp"
#include "tool/Utils.hpp"
#ifdef HAVE_CRASH_HANDLER
#include "tool/crash_reporter/CrashReporter.hpp"
#endif
// =============================================================================
@ -55,6 +58,7 @@ SettingsModel::SettingsModel() {
if (gstate == linphone::GlobalState::On) { // reached when misc|config-uri is set in config and app starts
// and after config is fetched.
notifyConfigReady();
}
});
QObject::connect(CoreModel::getInstance().get(), &CoreModel::configuringStatus, this,
@ -618,16 +622,32 @@ void SettingsModel::setFullLogsEnabled(bool status) {
emit fullLogsEnabledChanged(status);
}
bool SettingsModel::getCrashReporterEnabled() const {
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
return getCrashReporterEnabled(mConfig);
}
void SettingsModel::setCrashReporterEnabled(bool status) {
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
mConfig->setInt(AppSection, "send_logs_to_crashlytics", status);
#ifdef HAVE_CRASH_HANDLER
CrashReporter::enable(status);
#endif
emit crashReporterEnabledChanged(status);
}
bool SettingsModel::getLogsEnabled(const shared_ptr<linphone::Config> &config) {
mustBeInLinphoneThread(sLog().arg(Q_FUNC_INFO));
return config ? config->getInt(UiSection, "logs_enabled", false) : true;
}
bool SettingsModel::getFullLogsEnabled(const shared_ptr<linphone::Config> &config) {
mustBeInLinphoneThread(sLog().arg(Q_FUNC_INFO));
return config ? config->getInt(UiSection, "full_logs_enabled", false) : false;
}
bool SettingsModel::getCrashReporterEnabled(const shared_ptr<linphone::Config> &config) {
return config ? config->getInt(AppSection, "send_logs_to_crashlytics", true) : true;
}
QString SettingsModel::getLogsFolder() const {
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
return getLogsFolder(mConfig);
@ -686,6 +706,9 @@ QString SettingsModel::getLogsEmail() const {
return Utils::coreStringToAppString(mConfig->getString(UiSection, "logs_email", Constants::DefaultLogsEmail));
}
// =============================================================================
// Do not disturb
// =============================================================================

View file

@ -143,8 +143,12 @@ public:
bool getFullLogsEnabled() const;
void setFullLogsEnabled(bool status);
bool getCrashReporterEnabled() const;
void setCrashReporterEnabled(bool status);
static bool getLogsEnabled(const std::shared_ptr<linphone::Config> &config);
static bool getFullLogsEnabled(const std::shared_ptr<linphone::Config> &config);
static bool getCrashReporterEnabled(const std::shared_ptr<linphone::Config> &config);
QString getLogsFolder() const;
void setLogsFolder(const QString &folder);
@ -272,6 +276,7 @@ signals:
void logsEnabledChanged(bool status);
void fullLogsEnabledChanged(bool status);
void crashReporterEnabledChanged(bool status);
void dndChanged(bool value);

View file

@ -53,6 +53,10 @@ else ()
)
endif ()
if (HAVE_CRASH_HANDLER)
list(APPEND _LINPHONEAPP_SOURCES tool/crash_reporter/CrashReporter.cpp)
endif()
set(_LINPHONEAPP_SOURCES ${_LINPHONEAPP_SOURCES} PARENT_SCOPE)

View file

@ -60,6 +60,10 @@ constexpr char Constants::PathCodecs[];
constexpr char Constants::PathData[];
constexpr char Constants::PathTools[];
constexpr char Constants::PathLogs[];
#ifdef HAVE_CRASH_HANDLER
constexpr char Constants::PathCrashpad[];
constexpr char Constants::PathCrashpadHandler[];
#endif
#ifdef APPLE
constexpr char Constants::PathPlugins[];
#else

View file

@ -146,14 +146,21 @@ public:
static constexpr char PathTools[] = "/tools/";
static constexpr char PathLogs[] = "/logs/";
static constexpr char PathVCards[] = "/vcards/";
static constexpr char PathMetrics[] = "/metrics/";
#ifdef APPLE
static constexpr char PathPlugins[] = "/Plugins/";
#else
static constexpr char PathPlugins[] = "/plugins/";
#endif
static constexpr char PathPluginsApp[] = "app/";
static constexpr char PathBin[] = "/bin/";
static constexpr char PathSounds[] = "/sounds/linphone";
static constexpr char PathUserCertificates[] = "/usr-crt/";
#ifdef HAVE_CRASH_HANDLER
static constexpr char PathCrashpad[] = "/crashpad/";
static constexpr char PathCrashpadHandler[] = CRASHPAD_EXECUTABLE_NAME;
static constexpr char BugsplatUrl[] = "https://Linphone.bugsplat.com/post/bp/crash/crashpad.php";
#endif
static constexpr char PathCallHistoryList[] = "/call-history.db";
static constexpr char PathConfig[] = "/linphonerc";

View file

@ -245,6 +245,12 @@ public:
static QUrl getAppIcon(const QString &iconName);
static QUrl getRegistrationStateIcon(LinphoneEnums::RegistrationState state);
#ifdef Q_OS_WINDOWS
static inline std::wstring getNativeString(const QString &s){ return s.toStdWString(); }
#else
static std::string getNativeString(const QString &s){ return s.toStdString(); }
#endif
private:
DECLARE_ABSTRACT_OBJECT
};

View file

@ -0,0 +1,90 @@
/*
* Copyright (c) 2010-2026 Belledonne Communications SARL.
*
* This file is part of linphone-desktop
* (see https://www.linphone.org).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "CrashReporter.hpp"
#include "config.h"
#include "tool/Utils.hpp"
#include "tool/Constants.hpp"
#include "core/path/Paths.hpp"
#include "model/setting/SettingsModel.hpp"
#include "client/crash_report_database.h"
#include "client/settings.h"
#include <QSettings>
CrashReporter* CrashReporter::gHandler = nullptr;
CrashReporter::CrashReporter(QObject * parent): QObject(parent) {
mHandlerPath = base::FilePath(Utils::getNativeString(Paths::getCrashpadHandlerFilePath()));
mDatabasePath = base::FilePath(Utils::getNativeString(Paths::getCrashpadDirPath()));
mMetricsPath = base::FilePath(Utils::getNativeString(Paths::getMetricsDirPath()));
mBugsplatUrl = Constants::BugsplatUrl;
mAnnotations["format"] = "minidump"; // Required: Crashpad setting to save crash as a minidump
mAnnotations["database"] = BUGSPLAT_DATABASE; // Required: BugSplat database
mAnnotations["product"] = APPLICATION_NAME; // Required: BugSplat appName
mAnnotations["version"] = APPLICATION_SEMVER;
// annotations["key"] = "Sample key"; // Optional: BugSplat key field
// annotations["user"] = "fred@bugsplat.com"; // Optional: BugSplat user email
// annotations["list_annotations"] = "Sample comment"; // Optional: BugSplat crash description
// Disable crashpad rate limiting so that all crashes have dmp files
mArguments.push_back("--no-rate-limit");
auto config = linphone::Factory::get()->createConfig(Utils::appStringToCoreString(Paths::getConfigFilePath("", true)));
// Attachments to be uploaded alongside the crash - default bundle size limit is 20MB
// Crashpad doesn't manage folders. We have to guess the files to be uploaded.
QString logFiles = Paths::getLogsDirPath()+QDir::separator()+EXECUTABLE_NAME;
mAttachments.push_back(base::FilePath(Utils::getNativeString(logFiles+".log")));
mAttachments.push_back(base::FilePath(Utils::getNativeString(logFiles + "1.log")));
mAttachments.push_back(base::FilePath(Utils::getNativeString(logFiles + "2.log")));
}
void CrashReporter::start() {
auto config = linphone::Factory::get()->createConfig(Utils::appStringToCoreString(Paths::getConfigFilePath("", true)));
CrashReporter::enable(SettingsModel::getCrashReporterEnabled(config));
}
void CrashReporter::run() {
//crashpad::CrashpadClient *client = new crashpad::CrashpadClient();
bool status = mClient.StartHandler(mHandlerPath, mDatabasePath, mMetricsPath, mBugsplatUrl.toStdString(), mAnnotations.toStdMap(), mArguments, true, true, mAttachments);
if(!status){
lWarning() << "[CrashReporter] Failed to start Crashpad handler. Crashes will not be logged.";
} else {
lInfo() << "[CrashReporter] Started Crashpad handler. Database at " << Paths::getCrashpadDirPath();
}
}
void CrashReporter::enable(const bool& on) {
if(!gHandler) gHandler = new CrashReporter();
std::unique_ptr<crashpad::CrashReportDatabase> database = crashpad::CrashReportDatabase::Initialize(gHandler->mDatabasePath);
if (database == NULL) return;
crashpad::Settings *settings = database->GetSettings();
if (settings == NULL) return;
settings->SetUploadsEnabled(on);
if(on) gHandler->run();
else {
lInfo() << "[CrashReporter] Crashpad has been deactivated by user.";
}
}

View file

@ -0,0 +1,52 @@
/*
* Copyright (c) 2010-2026 Belledonne Communications SARL.
*
* This file is part of linphone-desktop
* (see https://www.linphone.org).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CRASH_REPORTER_H_
#define CRASH_REPORTER_H_
#include <QObject>
#include <QMap>
#include <QVector>
#include <string>
#include "client/crashpad_client.h"
// =============================================================================
class CrashReporter : public QObject{
public:
CrashReporter(QObject * parent = nullptr);
static void start();
static void enable(const bool& on);
void run();
crashpad::CrashpadClient mClient;
std::vector<base::FilePath> mAttachments;
QMap<std::string, std::string> mAnnotations;
std::vector<std::string> mArguments;
base::FilePath mHandlerPath;
base::FilePath mDatabasePath;
base::FilePath mMetricsPath;
base::FilePath mLogsPath;
QString mBugsplatUrl;
static CrashReporter* gHandler;
};
#endif

View file

@ -48,6 +48,7 @@ bool Thread::isInLinphoneThread() {
}
bool Thread::mustBeInLinphoneThread(const QString &context) {
if(!App::getInstance()) return true;
bool isLinphoneThread = isInLinphoneThread();
if (!isLinphoneThread) { // Bracket to easier debugging.
lCritical() << "[Thread] Not processing in Linphone thread from " << context;

View file

@ -34,6 +34,11 @@ For Desktop : you will need QT6 (_6.10.0 or newer_). `C++17` support is required
The following QT optional modules are required: qtmultimedia qtnetworkauth qtshadertools .
If you wan't to build with Crash handler, you need to install the following tools:
- clang
- curl dev (for C development headers) (ex: `sudo apt install libcurl4-openssl-dev`)
- httplib2 v0.22.0 (use `pip install httplib2==0.22.0` or `pip3 install httplib2==0.22.0`)
### Set your environment
1. Make sure you have all your build dependencies installed
@ -295,6 +300,7 @@ Also, more configurations are available in the docker-files folder of linphone-s
| ENABLE_UNIT_TESTS | Enable unit test of SDK. | NO |
| ENABLE_OPENLDAP | Build openLDAP external library. | YES |
| ENABLE_UPDATE_CHECK | Enable update check. | YES |
| ENABLE_CRASH_HANDLER | Enable crash handler. | YES |
| LINPHONE_SDK_MAKE_RELEASE_FILE_URL | Make a RELEASE file that work along check_version and use this URL | "" |

View file

@ -0,0 +1,154 @@
############################################################################
# Copyright (c) 2025 Belledonne Communications SARL.
#
# This file is part of Linphone.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
############################################################################
# This module will set the following variables in your project:
#
# Crashpad_FOUND - The crashpad library has been found
# Crashpad::Crashpad - Imported target to build against
# CRASHPAD_BIN_DIR - Directory where the crashpad_handler executable is found
# CRASHPAD_EXECUTABLE_NAME - Crash handler executable
# CRASHPAD_INCLUDE_DIR - Headers folder of Crashpad.
if(TARGET Crashpad)
get_target_property(CRASHPAD_BIN_DIR Crashpad CRASHPAD_BIN_DIR)
get_target_property(CRASHPAD_BUILD_DIR Crashpad CRASHPAD_BUILD_DIR)
get_target_property(CRASHPAD_EXECUTABLE_NAME Crashpad CRASHPAD_EXECUTABLE_NAME)
get_target_property(CRASHPAD_GEN_DIR Crashpad CRASHPAD_GEN_DIR)
get_target_property(CRASHPAD_INCLUDE_DIR Crashpad CRASHPAD_INCLUDE_DIR)
get_target_property(CRASHPAD_LIB_DIR Crashpad CRASHPAD_LIB_DIR)
get_target_property(CRASHPAD_SOURCE_DIR Crashpad CRASHPAD_SOURCE_DIR)
endif()
if(NOT CRASHPAD_BUILD_DIR)
set(CRASHPAD_BUILD_DIR ${CMAKE_BINARY_DIR}/external/google/crashpad/out)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CRASHPAD_BUILD_DIR ${CRASHPAD_BUILD_DIR}/debug)
else()
set(CRASHPAD_BUILD_DIR ${CRASHPAD_BUILD_DIR}/release)
endif()
endif()
if(NOT CRASHPAD_SOURCE_DIR)
set(CRASHPAD_SOURCE_DIR ${CMAKE_SOURCE_DIR}/external/google/crashpad)
endif()
if(NOT CRASHPAD_EXECUTABLE_NAME OR NOT CRASHPAD_BIN_DIR)
find_program(CRASHPAD_EXECUTABLE
NAMES crashpad_handler.exe crashpad_handler
HINTS
"${CRASHPAD_BUILD_DIR}"
"${CMAKE_PREFIX_PATH}"
)
get_filename_component(CRASHPAD_BIN_DIR ${CRASHPAD_EXECUTABLE} DIRECTORY)
get_filename_component(CRASHPAD_EXECUTABLE_NAME ${CRASHPAD_EXECUTABLE} NAME)
endif()
if(NOT CRASHPAD_INCLUDE_DIR)
find_path(CRASHPAD_INCLUDE_DIR
NAMES client/crashpad_client.h
HINTS
"${CRASHPAD_SOURCE_DIR}"
"${CMAKE_PREFIX_PATH}"
)
endif()
if(NOT CRASHPAD_LIB_DIR)
find_path(CRASHPAD_LIB_DIR
NAMES util/libutil.a util/util.lib
HINTS
"${CRASHPAD_BIN_DIR}/obj"
"${CMAKE_PREFIX_PATH}"
)
endif()
if(NOT CRASHPAD_GEN_DIR)
find_path(CRASHPAD_GEN_DIR
NAMES build/chromeos_buildflags.h
PATH_SUFFIXES gen
HINTS
"${CRASHPAD_BIN_DIR}"
"${CMAKE_PREFIX_PATH}"
)
endif()
if(APPLE)
find_path(CRASHPAD_OBJ_DIR
NAMES mig_output.child_portServer.o
PATH_SUFFIXES gen/util/mach
HINTS
"${CRASHPAD_OBJECT_DIR}"
"${CRASHPAD_LIB_DIR}"
"${CMAKE_PREFIX_PATH}"
)
set(CRASHPAD_APPLE_VARS CRASHPAD_OBJ_DIR CRASHPAD_GEN_DIR)
find_library(FWbsm bsm)
find_library(FWAppKit AppKit)
find_library(FWIOKit IOKit)
find_library(FWSecurity Security)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Crashpad DEFAULT_MSG
CRASHPAD_BIN_DIR CRASHPAD_INCLUDE_DIR CRASHPAD_LIB_DIR CRASHPAD_EXECUTABLE_NAME ${CRASHPAD_APPLE_VARS}
)
#[[
if(Crashpad_FOUND)
add_library(Crashpad::Crashpad UNKNOWN IMPORTED)
target_include_directories(Crashpad::Crashpad INTERFACE
"${CRASHPAD_INCLUDE_DIR}"
"${CRASHPAD_INCLUDE_DIR}/third_party/mini_chromium/mini_chromium"
"${CRASHPAD_GEN_DIR}")
if(WIN32)
target_link_libraries(Crashpad::Crashpad INTERFACE
"${CRASHPAD_LIB_DIR}/third_party/mini_chromium/mini_chromium/base/base.lib"
"${CRASHPAD_LIB_DIR}/util/util.lib"
"${CRASHPAD_LIB_DIR}/client/client.lib"
"${CRASHPAD_LIB_DIR}/client/common.lib"
advapi32)
set_target_properties(Crashpad::Crashpad PROPERTIES
IMPORTED_LOCATION "${CRASHPAD_LIB_DIR}/client/client.lib")
elseif(APPLE)
target_link_libraries(Crashpad::Crashpad INTERFACE
"${CRASHPAD_LIB_DIR}/third_party/mini_chromium/mini_chromium/base/libbase.a"
"${CRASHPAD_LIB_DIR}/util/libutil.a"
"${CRASHPAD_LIB_DIR}/client/libclient.a"
"${CRASHPAD_OBJ_DIR}/mig_output.child_portServer.o"
"${CRASHPAD_OBJ_DIR}/mig_output.child_portUser.o"
"${CRASHPAD_OBJ_DIR}/mig_output.excServer.o"
"${CRASHPAD_OBJ_DIR}/mig_output.excUser.o"
"${CRASHPAD_OBJ_DIR}/mig_output.mach_excServer.o"
"${CRASHPAD_OBJ_DIR}/mig_output.mach_excUser.o"
"${CRASHPAD_OBJ_DIR}/mig_output.notifyServer.o"
"${CRASHPAD_OBJ_DIR}/mig_output.notifyUser.o"
${FWbsm} ${FWAppKit} ${FWIOKit} ${FWSecurity})
set_target_properties(Crashpad::Crashpad PROPERTIES
IMPORTED_LOCATION "${CRASHPAD_LIB_DIR}/client/libclient.a")
elseif(UNIX)
target_link_libraries(Crashpad::Crashpad INTERFACE
"${CRASHPAD_LIB_DIR}/third_party/mini_chromium/mini_chromium/base/libbase.a"
"${CRASHPAD_LIB_DIR}/util/libutil.a"
"${CRASHPAD_LIB_DIR}/client/libclient.a")
set_target_properties(Crashpad::Crashpad PROPERTIES
IMPORTED_LOCATION "${CRASHPAD_LIB_DIR}/client/libclient.a")
endif()
endif()
]]#

View file

@ -25,10 +25,20 @@
# It is neccessary to use it because CPack doesn't take account of some install() (those that do the move)
cmake_policy(SET CMP0009 NEW)#Not following symlinks for file()
IF(POLICY CMP0012)
CMAKE_POLICY(SET CMP0012 NEW)#Allow if(ON)
ENDIF()
set(DO_SIGNING @LINPHONE_BUILDER_SIGNING_IDENTITY@)
set(DEPLOYQT_PROGRAM @DEPLOYQT_PROGRAM@)
function(remove_file expression)
file(GLOB_RECURSE UNWANTED_FILES ${expression})
foreach(F ${UNWANTED_FILES})
file(REMOVE ${F})
endforeach()
endfunction()
if(APPLE)
find_program(DSYMUTIL_PROGRAM dsymutil)
@ -61,8 +71,36 @@ if(APPLE)
execute_process(COMMAND codesign --force --deep --sign "-" "${CPACK_TEMPORARY_INSTALL_DIRECTORY}/@APPLICATION_NAME@.app" )#If not code signed, app can crash because of APPLE on "Code Signature Invalid" (spotted for ARM64)
endif()
elseif(WIN32)
message(STATUS "Execute : @DEPLOYQT_PROGRAM@ ${CPACK_TEMPORARY_INSTALL_DIRECTORY}/@CMAKE_INSTALL_BINDIR@/@EXECUTABLE_NAME@.exe --qmldir=@LINPHONE_QML_DIR@ --verbose=0 --no-compiler-runtime")
execute_process(COMMAND @DEPLOYQT_PROGRAM@ "${CPACK_TEMPORARY_INSTALL_DIRECTORY}/@CMAKE_INSTALL_BINDIR@/@EXECUTABLE_NAME@.exe" "--qmldir=@LINPHONE_QML_DIR@" "--verbose=0" "--no-compiler-runtime")
message(STATUS "Execute : @DEPLOYQT_PROGRAM@ ${CPACK_TEMPORARY_INSTALL_DIRECTORY}/@CMAKE_INSTALL_BINDIR@/@EXECUTABLE_NAME@.exe --qmldir=@LINPHONE_QML_DIR@ --verbose=0 --no-compiler-runtime --pdb")
execute_process(COMMAND @DEPLOYQT_PROGRAM@ "${CPACK_TEMPORARY_INSTALL_DIRECTORY}/@CMAKE_INSTALL_BINDIR@/@EXECUTABLE_NAME@.exe" "--qmldir=@LINPHONE_QML_DIR@" "--verbose=0" "--no-compiler-runtime" "--pdb")
# --plugindir "${CMAKE_CURRENT_BINARY_DIR}/winqt/plugins"
# --dir "${CMAKE_CURRENT_BINARY_DIR}/winqt/"
if(@ENABLE_BUGSPLAT_SYMBOLS_UPLOAD@)
message(STATUS "Uploading Bugsplat symbols from ${CPACK_TEMPORARY_INSTALL_DIRECTORY}")
execute_process(COMMAND "@CRASHPAD_SYMBOLS_UPLOADER@" -m -b @BUGSPLAT_DATABASE@ -a "@LINPHONEAPP_APPLICATION_NAME@" -v "@LINPHONEAPP_VERSION@" -f "**/*.{pdb,exe,dll}" -d "${CPACK_TEMPORARY_INSTALL_DIRECTORY}/@CMAKE_INSTALL_BINDIR@" --clientId "@BUGSPPLAT_CLIENT_ID@" --clientSecret "@BUGSPPLAT_CLIENT_SECRET@"
WORKING_DIRECTORY ${CPACK_TEMPORARY_INSTALL_DIRECTORY}
RESULT_VARIABLE CPACK_COMMAND_RESULT
COMMAND_ECHO NONE
)
if(CPACK_COMMAND_RESULT)
message(FATAL_ERROR "Failed to upload symbols! ${CPACK_COMMAND_RESULT}")
endif()
execute_process(COMMAND "@CRASHPAD_SYMBOLS_UPLOADER@" -m -b @BUGSPLAT_DATABASE@ -a "@LINPHONEAPP_APPLICATION_NAME@" -v "@LINPHONEAPP_VERSION@" -f "**/*.{pdb,exe,dll}" -d "${CPACK_TEMPORARY_INSTALL_DIRECTORY}/@CMAKE_INSTALL_LIBDIR@/mediastreamer/plugins" --clientId "@BUGSPPLAT_CLIENT_ID@" --clientSecret "@BUGSPPLAT_CLIENT_SECRET@"
WORKING_DIRECTORY ${CPACK_TEMPORARY_INSTALL_DIRECTORY}
RESULT_VARIABLE CPACK_COMMAND_RESULT
COMMAND_ECHO NONE
)
if(CPACK_COMMAND_RESULT)
message(FATAL_ERROR "Failed to upload symbols! ${CPACK_COMMAND_RESULT}")
endif()
endif()
#####################################################
# Clean all unwanted files to package.
#####################################################
# TODO: remove all pdb when CrashReporter is available. Symbols for crashing are in server so it is not needed for deployment.
# if debugging is needed, we could rebuild it and use pdb from local build instead of using official binaries.
#remove_file("${CPACK_TEMPORARY_INSTALL_DIRECTORY}/*/*.pdb")
remove_file("${CPACK_TEMPORARY_INSTALL_DIRECTORY}/*/Qt*.pdb")
remove_file("${CPACK_TEMPORARY_INSTALL_DIRECTORY}/*/*.cmake")
remove_file("${CPACK_TEMPORARY_INSTALL_DIRECTORY}/*/*.lib")
endif()

View file

@ -126,6 +126,8 @@ else
echo "-- Code Signing of AppImage"
# APPIMAGETOOL_SIGN_PASSPHRASE has to the parent environment (not here). Do not use export.
./${WORK_DIR}/AppBin/appimagetool-x86_64.AppImage --appimage-extract-and-run ${WORK_DIR}/AppDir --sign --sign-key $4
fi
echo "Move Appimages into ${BIN_SOURCE_DIR}/Packages/$2.AppImage"

View file

@ -23,20 +23,18 @@
cmake_minimum_required(VERSION 3.5)
set(TARGET_NAME Linphone)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/Modules")
if (GIT_EXECUTABLE AND NOT(LINPHONEAPP_VERSION))
execute_process(
COMMAND ${GIT_EXECUTABLE} describe --always
OUTPUT_VARIABLE LINPHONEAPP_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
)
if(NOT LINPHONEAPP_VERSION)
bc_compute_full_version(LINPHONEAPP_VERSION)
endif()
if (NOT(LINPHONEAPP_VERSION))
set(LINPHONEAPP_VERSION "6.1.0")
endif ()
include(${CMAKE_SOURCE_DIR}/Linphone/application_info.cmake)
set(LINPHONE_MAJOR_VERSION)
set(LINPHONE_MINOR_VERSION)
set(LINPHONE_MICRO_VERSION)
@ -161,6 +159,39 @@ function(deployqt_hack target)
endif()
endfunction()
################################################################
# CRASHPAD
################################################################
if(HAVE_CRASH_HANDLER)
get_target_property(CRASHPAD_BIN_DIR Crashpad CRASHPAD_BIN_DIR)
get_target_property(CRASHPAD_EXECUTABLE_NAME Crashpad CRASHPAD_EXECUTABLE_NAME)
install(FILES "${CRASHPAD_BIN_DIR}/${CRASHPAD_EXECUTABLE_NAME}" DESTINATION ${CMAKE_INSTALL_BINDIR} PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
if(ENABLE_BUGSPLAT_SYMBOLS_UPLOAD)
if(NOT LINPHONEAPP_APPLICATION_NAME)
message(FATAL_ERROR "Missing application details for Bugsplat. Please fill LINPHONEAPP_APPLICATION_NAME (${LINPHONEAPP_APPLICATION_NAME} - ${LINPHONEAPP_VERSION})")
elseif(NOT BUGSPLAT_DATABASE)
message(FATAL_ERROR "Missing database application details for Bugsplat. Please fill BUGSPLAT_DATABASE in application_info.cmake")
elseif(NOT BUGSPPLAT_CLIENT_ID OR NOT BUGSPPLAT_CLIENT_SECRET)
message(FATAL_ERROR "Missing identifications for Bugsplat. Please fill BUGSPPLAT_CLIENT_ID and BUGSPPLAT_CLIENT_SECRET to activate symbol uploading")
else()
message(STATUS "Preparing symbol uploader Bugsplat for ${LINPHONEAPP_APPLICATION_NAME} - ${LINPHONEAPP_VERSION}.")
if(WIN32)
set(CRASHPAD_SYMBOLS_UPLOADER "${CMAKE_BINARY_DIR}/symbol-upload-windows.exe")
set(CRASHPAD_SYMBOLS_UPLOADER_URL "https://github.com/BugSplat-Git/symbol-upload/releases/download/v10.2.4/symbol-upload-windows.exe")
else()
set(CRASHPAD_SYMBOLS_UPLOADER "${CMAKE_BINARY_DIR}/symbol-upload-linux")
set(CRASHPAD_SYMBOLS_UPLOADER_URL "https://github.com/BugSplat-Git/symbol-upload/releases/download/v10.2.4/symbol-upload-linux")
endif()
if(NOT EXISTS "${CRASHPAD_SYMBOLS_UPLOADER}")
file(DOWNLOAD ${CRASHPAD_SYMBOLS_UPLOADER_URL} ${CRASHPAD_SYMBOLS_UPLOADER})
file(CHMOD "${CRASHPAD_SYMBOLS_UPLOADER}" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
endif()
endif()
endif()
endif()
# ==============================================================================
# CPack.
# ==============================================================================
@ -214,13 +245,17 @@ if(${ENABLE_APP_PACKAGING})
set(DO_GENERATOR YES)
set(PACKAGE_EXT "exe")
set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${PACKAGE_VERSION}-${BIN_ARCH}")
set(CPACK_SOURCE_IGNORE_FILES "*Qt*.pdb;*.lib;*.cmake") #Doesn't seem to work but we let the option just in case.
find_program(NSIS_PROGRAM makensis)
if(NOT NSIS_PROGRAM)
message(STATUS "Installing windows tools for nsis")
execute_process(
COMMAND "${MSYS2_PROGRAM}" "-${MINGW_TYPE}" "-here" "-full-path" "-defterm" "-shell" "sh" "-l" "-c" "pacman -Sy ${MINGW_PACKAGE_PREFIX}nsis --noconfirm --needed"
)
if(ENABLE_WINDOWS_TOOLS_CHECK)
message(STATUS "Installing windows tools for nsis")
execute_process(
COMMAND "${MSYS2_PROGRAM}" "-${MINGW_TYPE}" "-here" "-full-path" "-defterm" "-shell" "sh" "-l" "-c" "pacman -Sy ${MINGW_PACKAGE_PREFIX}nsis --noconfirm --needed"
)
else()
message(FATAL_ERROR "`makensis` is needed for packaging. Please use pacman -Sy ${MINGW_PACKAGE_PREFIX}nsis to install it.")
endif()
endif()
set(PACKAGE_EXT "exe")
# Use magic `NSIS.template.in` template from the current source directory to force uninstallation
@ -307,4 +342,3 @@ if(${ENABLE_APP_PACKAGING})
endif()
include(CPack)
endif()

View file

@ -57,7 +57,7 @@ if (NOT "${CMAKE_INSTALL_PREFIX}" MATCHES .*/_CPack_Packages/.*)
if(DO_GENERATOR)
execute_process( COMMAND ${CMAKE_CPACK_COMMAND} -G @CPACK_GENERATOR@ -C @CMAKE_BUILD_TYPE@ RESULT_VARIABLE CPACK_COMMAND_RESULT)
if(CPACK_COMMAND_RESULT)
message(FATAL_ERROR "Failed to create @CPACK_GENERATOR@ package!")
message(FATAL_ERROR "Failed to create @CPACK_GENERATOR@ package! ${CPACK_COMMAND_RESULT}")
endif()
endif()
if(DO_APPIMAGE)
@ -69,6 +69,23 @@ if (NOT "${CMAKE_INSTALL_PREFIX}" MATCHES .*/_CPack_Packages/.*)
execute_process( COMMAND "@CMAKE_SOURCE_DIR@/cmake/install/create_appimage.sh" @EXECUTABLE_NAME@ "@CPACK_PACKAGE_FILE_NAME@${ARCH}" @QT_PATH@ @LINPHONE_BUILDER_SIGNING_IDENTITY@ RESULT_VARIABLE CPACK_COMMAND_RESULT WORKING_DIRECTORY "@CMAKE_INSTALL_PREFIX@/.." )
if(CPACK_COMMAND_RESULT)
message(FATAL_ERROR "Failed to create AppImage package with this command : '@CMAKE_CURRENT_SOURCE_DIR@/../../tools/create_appimage.sh @EXECUTABLE_NAME@ @QT_PATH@ @LINPHONEAPP_VERSION@' at @CMAKE_INSTALL_PREFIX@/..\nMaybe the .appimage already exists and is running. Please remove the file before packaging if it is the case.")
elseif(@ENABLE_BUGSPLAT_SYMBOLS_UPLOAD@)
execute_process(COMMAND "@CRASHPAD_SYMBOLS_UPLOADER@" -m -b @BUGSPLAT_DATABASE@ -a "@LINPHONEAPP_APPLICATION_NAME@" -v "@LINPHONEAPP_VERSION@" -f "@EXECUTABLE_NAME@" --clientId "@BUGSPPLAT_CLIENT_ID@" --clientSecret "@BUGSPPLAT_CLIENT_SECRET@"
WORKING_DIRECTORY @CMAKE_INSTALL_PREFIX@/../WORK/Packages/AppImageDir/AppDir/usr/bin/
RESULT_VARIABLE CPACK_COMMAND_RESULT
COMMAND_ECHO NONE
)
if(CPACK_COMMAND_RESULT)
message(FATAL_ERROR "Failed to upload symbols: '@CMAKE_CURRENT_SOURCE_DIR@/../../tools/create_appimage.sh @EXECUTABLE_NAME@ @QT_PATH@ @LINPHONEAPP_VERSION@' at @CMAKE_INSTALL_PREFIX@/..\nMaybe the .appimage already exists and is running. Please remove the file before packaging if it is the case.")
endif()
execute_process(COMMAND "@CRASHPAD_SYMBOLS_UPLOADER@" -m -b @BUGSPLAT_DATABASE@ -a "@LINPHONEAPP_APPLICATION_NAME@" -v "@LINPHONEAPP_VERSION@" -f "**/*.so{,.*}" --clientId "@BUGSPPLAT_CLIENT_ID@" --clientSecret "@BUGSPPLAT_CLIENT_SECRET@"
WORKING_DIRECTORY @CMAKE_INSTALL_PREFIX@/../WORK/Packages/AppImageDir/AppDir/usr/
RESULT_VARIABLE CPACK_COMMAND_RESULT
COMMAND_ECHO NONE
)
if(CPACK_COMMAND_RESULT)
message(FATAL_ERROR "Failed to upload symbols: '@CMAKE_CURRENT_SOURCE_DIR@/../../tools/create_appimage.sh @EXECUTABLE_NAME@ @QT_PATH@ @LINPHONEAPP_VERSION@' at @CMAKE_INSTALL_PREFIX@/..\nMaybe the .appimage already exists and is running. Please remove the file before packaging if it is the case.")
endif()
endif()
endif()
if (@PERFORM_SIGNING@)

View file

@ -59,6 +59,10 @@ RUN sudo apt-get install -y gnupg2
# Install configuration tools
RUN sudo apt-get install -y wget
# Install crashpad build tools
RUN sudo apt-get install -y libcurl4-openssl-dev
RUN sudo pip3 install httplib2==0.22.0
# Configure user bc
RUN useradd -ms /bin/bash bc && \
echo 'bc:cotcot' | chpasswd && \

View file

@ -3,4 +3,5 @@ add_subdirectory(linphone-sdk/)
if(ENABLE_QT_KEYCHAIN)
find_package(Qt6 REQUIRED COMPONENTS Test)
add_subdirectory(qtkeychain/)
endif()
endif()
add_subdirectory(google)

1
external/google/.gclient vendored Normal file
View file

@ -0,0 +1 @@
solutions = [{"name": "crashpad", "url": "https://gitlab.linphone.org/BC/public/external/crashpad", "managed": False}]

116
external/google/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,116 @@
set(DEPOT_TOOLS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/chromium-depot-tools")
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CRASHPAD_BIN_DIR "out/debug")
else()
set(CRASHPAD_BIN_DIR "out/release")
endif()
set(CRASHPAD_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/crashpad/${CRASHPAD_BIN_DIR})
if(WIN32)
set(GCLIENT_SCRIPT "${DEPOT_TOOLS_DIR}/gclient.bat")
set(GN_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/bc_gn.bat")
set(GN_COMMAND ${GN_SCRIPT} ${CRASHPAD_BUILD_DIR} ${CMAKE_BUILD_TYPE})
else()
set(GCLIENT_SCRIPT "${DEPOT_TOOLS_DIR}/gclient")
set(GN_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/bc_gn.sh")
set(GN_COMMAND ${GN_SCRIPT} ${CRASHPAD_BUILD_DIR} ${CMAKE_BUILD_TYPE})
endif()
message(STATUS "gn used ${GN_SCRIPT}")
if (ENABLE_CRASH_HANDLER AND WIN32)
##########################################
#Hack utils/Build.gn by adding cflags = ["-Wno-nontrivial-memcall"]
#because newer version of clang cannot build with this warning and it is not fixed by crashpad
message(STATUS "Syncing with gclient")
execute_process(
COMMAND "${GCLIENT_SCRIPT}" sync --nohooks --shallow
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE gclient_sync_result
OUTPUT_VARIABLE gclient_sync_output
ERROR_VARIABLE gclient_sync_error
COMMAND_ECHO STDOUT
)
if(gclient_sync_result)
message(FATAL_ERROR "Failed syncing with gclient: ${gclient_sync_result} ${gclient_sync_output} ${gclient_sync_error}")
endif()
message(STATUS "Generating build files for crashpad")
#We use GN_COMMAND because CMAKE mess up with quotes, spaces and arguments on Windows
execute_process(
COMMAND ${GN_COMMAND}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/crashpad"
RESULT_VARIABLE crashpad_gn_result
OUTPUT_VARIABLE crashpad_gn_output
ERROR_VARIABLE crashpad_gn_error
COMMAND_ECHO STDOUT
)
if(crashpad_gn_result)
message(FATAL_ERROR "Failed generate crashpad build files: ${crashpad_gn_result} ${crashpad_gn_output} ${crashpad_gn_error}")
endif()
message(STATUS "Crashpad build files generated")
set(TARGET_NAME Crashpad)
#NOTE: Order is important
if(WIN32)
set(CRASHPAD_OUTPUTS
"${CRASHPAD_BUILD_DIR}/obj/client/common.lib"
"${CRASHPAD_BUILD_DIR}/obj/client/client.lib"
"${CRASHPAD_BUILD_DIR}/obj/util/util.lib"
"${CRASHPAD_BUILD_DIR}/obj/third_party/mini_chromium/mini_chromium/base/base.lib"
)
elseif(APPLE)
set(CRASHPAD_OUTPUTS
"${CRASHPAD_BUILD_DIR}/obj/client/libcommon.a"
"${CRASHPAD_BUILD_DIR}/obj/client/libclient.a"
"${CRASHPAD_BUILD_DIR}/obj/util/libutil.a"
"${CRASHPAD_BUILD_DIR}/obj/util/libmig_output.a"
"${CRASHPAD_BUILD_DIR}/obj/third_party/mini_chromium/mini_chromium/base/libbase.a"
)
else()
set(CRASHPAD_OUTPUTS
"${CRASHPAD_BUILD_DIR}/obj/client/libcommon.a"
"${CRASHPAD_BUILD_DIR}/obj/client/libclient.a"
"${CRASHPAD_BUILD_DIR}/obj/util/libutil.a"
"${CRASHPAD_BUILD_DIR}/obj/third_party/mini_chromium/mini_chromium/base/libbase.a"
)
endif()
add_custom_command(
OUTPUT ${CRASHPAD_OUTPUTS}
COMMAND ninja -C .
WORKING_DIRECTORY "${CRASHPAD_BUILD_DIR}"
COMMENT "Crashpad build files generated"
)
add_custom_target(Crashpad_build DEPENDS ${CRASHPAD_OUTPUTS})
add_library(${TARGET_NAME} STATIC IMPORTED GLOBAL)
add_dependencies(${TARGET_NAME} Crashpad_build)
target_include_directories(${TARGET_NAME} INTERFACE
"${CMAKE_CURRENT_SOURCE_DIR}/crashpad"
"${CMAKE_CURRENT_SOURCE_DIR}/crashpad/third_party/mini_chromium/mini_chromium"
"${CRASHPAD_BUILD_DIR}/gen")
target_link_libraries(${TARGET_NAME} INTERFACE ${CRASHPAD_OUTPUTS})
set_target_properties(${TARGET_NAME} PROPERTIES CRASHPAD_EXECUTABLE_NAME "crashpad_handler${CMAKE_EXECUTABLE_SUFFIX}")
if(WIN32)
target_link_libraries(${TARGET_NAME} INTERFACE advapi32)
set_target_properties(${TARGET_NAME} PROPERTIES
IMPORTED_LOCATION "${CRASHPAD_BUILD_DIR}/obj/client/client.lib")
else()
set_target_properties(${TARGET_NAME} PROPERTIES
IMPORTED_LOCATION "${CRASHPAD_BUILD_DIR}/obj/client/libclient.a"
)
endif()
set_target_properties(${TARGET_NAME} PROPERTIES
CRASHPAD_BIN_DIR "${CRASHPAD_BUILD_DIR}"
CRASHPAD_BUILD_DIR "${CRASHPAD_BUILD_DIR}"
CRASHPAD_GEN_DIR "${CRASHPAD_BUILD_DIR}/gen"
CRASHPAD_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/crashpad"
CRASHPAD_LIB_DIR "${CRASHPAD_BUILD_DIR}/obj"
CRASHPAD_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/crashpad"
)
set(HAVE_CRASH_HANDLER 1)
endif()

6
external/google/bc_gn.bat vendored Normal file
View file

@ -0,0 +1,6 @@
if /i "%~2"=="Debug" (
.\..\chromium-depot-tools\gn.bat gen %1 --args="extra_cflags=\"/MDd -Wno-nontrivial-memcall\""
) else (
.\..\chromium-depot-tools\gn.bat gen %1 --args="extra_cflags=\"/MD -Wno-nontrivial-memcall\""
)

3
external/google/bc_gn.sh vendored Executable file
View file

@ -0,0 +1,3 @@
#!/bin/bash
./../chromium-depot-tools/gn gen $1 --args="extra_cflags=\"-Wno-nontrivial-memcall\""

@ -0,0 +1 @@
Subproject commit db99cc40f562179c59f12b10e8af2d8fe2770ad2

1
external/google/crashpad vendored Submodule

@ -0,0 +1 @@
Subproject commit 4effb3358160e5c9d699d08c81b9410edd7dedfd

1
external/google/gn vendored Submodule

@ -0,0 +1 @@
Subproject commit 6e0b557db44b3c164094e57687d20ba036a80667