crash: add build configuration and distributor information

Also adds distributor to --version and
build configuration to --version --verbose
This commit is contained in:
outfoxxed 2024-10-15 23:01:14 -07:00
parent 8e40112d14
commit 23f59ec4c3
Signed by: outfoxxed
GPG key ID: 4C88A185FB89301E
9 changed files with 155 additions and 81 deletions

View file

@ -33,7 +33,7 @@ body:
attributes: attributes:
label: Minidump label: Minidump
description: | description: |
Attach `minidump.dmp` here. If it is too big to upload, compress it. Attach `minidump.dmp.log` here. If it is too big to upload, compress it.
You may skip this step if quickshell crashed while processing a password You may skip this step if quickshell crashed while processing a password
or other sensitive information. If you skipped it write why instead. or other sensitive information. If you skipped it write why instead.
@ -44,7 +44,7 @@ body:
attributes: attributes:
label: Log file label: Log file
description: | description: |
Attach `log.qslog` here. If it is too big to upload, compress it. Attach `log.qslog.log` here. If it is too big to upload, compress it.
You can preview the log if you'd like using `quickshell read-log <path-to-log>`. You can preview the log if you'd like using `quickshell read-log <path-to-log>`.
validations: validations:
@ -70,3 +70,13 @@ body:
in the crash reporter. in the crash reporter.
2. Once it loads, type `bt -full` (then enter) 2. Once it loads, type `bt -full` (then enter)
3. Copy the output and attach it as a file or in a spoiler. 3. Copy the output and attach it as a file or in a spoiler.
- type: textarea
id: exe
attributes:
label: Executable
description: |
If the crash folder contains a executable.txt file, upload it here. If not you can ignore this field.
If it is too big to upload, compress it.
Note: executable.txt is the quickshell binary. It has a .txt extension due to github's limitations on
filetypes.

View file

@ -2,6 +2,29 @@
Instructions for building from source and distro packagers. We highly recommend Instructions for building from source and distro packagers. We highly recommend
distro packagers read through this page fully. distro packagers read through this page fully.
## Packaging
If you are packaging quickshell for official or unofficial distribution channels,
such as a distro package repository, user repository, or other shared build location,
please set the following CMake flags.
`-DDISTRIBUTOR="your distribution platform"`
Please make this descriptive enough to identify your specific package, for example:
- `Official Nix Flake`
- `AUR (quickshell-git)`
- `Nixpkgs`
- `Fedora COPR (errornointernet/quickshell)`
`-DDISTRIBUTOR_DEBUGINFO_AVAILABLE=YES/NO`
If we can retrieve binaries and debug information for the package without actually running your
distribution (e.g. from an website), and you would like to strip the binary, please set this to `YES`.
If we cannot retrieve debug information, please set this to `NO` and
**ensure you aren't distributing stripped (non debuggable) binaries**.
In both cases you should build with `-DCMAKE_BUILD_TYPE=RelWithDebInfo` (then split or keep the debuginfo).
## Dependencies ## Dependencies
Quickshell has a set of base dependencies you will always need, names vary by distro: Quickshell has a set of base dependencies you will always need, names vary by distro:
@ -18,12 +41,6 @@ At least Qt 6.6 is required.
All features are enabled by default and some have their own dependencies. All features are enabled by default and some have their own dependencies.
### QML Library
If you wish to use a linter or similar tools, you will need the QML Modules for it
to pick up on the types.
To disable: `-DINSTALL_QML_LIB=OFF`
### Crash Reporter ### Crash Reporter
The crash reporter catches crashes, restarts quickshell when it crashes, The crash reporter catches crashes, restarts quickshell when it crashes,
and collects useful crash information in one place. Leaving this enabled will and collects useful crash information in one place. Leaving this enabled will
@ -169,9 +186,6 @@ or quickshell will fail to build.
Additionally, note that clang builds much faster than gcc if you care. Additionally, note that clang builds much faster than gcc if you care.
You may disable debug information but it's only a couple megabytes and is extremely helpful
for helping us fix problems when they do arise.
#### Building #### Building
```sh ```sh
$ cmake --build build $ cmake --build build

View file

@ -5,58 +5,64 @@ set(QT_MIN_VERSION "6.6.0")
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
option(BUILD_TESTING "Build tests" OFF) set(QS_BUILD_OPTIONS "")
option(ASAN "Enable ASAN" OFF) # note: better output with gcc than clang
option(FRAME_POINTERS "Always keep frame pointers" ${ASAN})
option(INSTALL_QML_LIB "Installing the QML lib" ON) function(boption VAR NAME DEFAULT)
option(CRASH_REPORTER "Enable the crash reporter" ON) cmake_parse_arguments(PARSE_ARGV 3 arg "" "REQUIRES" "")
option(USE_JEMALLOC "Use jemalloc over the system malloc implementation" ON)
option(SOCKETS "Enable unix socket support" ON) option(${VAR} ${NAME} ${DEFAULT})
option(WAYLAND "Enable wayland support" ON)
option(WAYLAND_WLR_LAYERSHELL "Support the zwlr_layer_shell_v1 wayland protocol" ON) set(STATUS "${VAR}_status")
option(WAYLAND_SESSION_LOCK "Support the ext_session_lock_v1 wayland protocol" ON) set(EFFECTIVE "${VAR}_effective")
option(WAYLAND_TOPLEVEL_MANAGEMENT "Support the zwlr_foreign_toplevel_management_v1 wayland protocol" ON) set(${STATUS} ${${VAR}})
option(X11 "Enable X11 support" ON) set(${EFFECTIVE} ${${VAR}})
option(HYPRLAND "Support hyprland specific features" ON)
option(HYPRLAND_IPC "Hyprland IPC" ON) if (${${VAR}} AND DEFINED arg_REQUIRES)
option(HYPRLAND_GLOBAL_SHORTCUTS "Hyprland Global Shortcuts" ON) set(REQUIRED_EFFECTIVE "${arg_REQUIRES}_effective")
option(HYPRLAND_FOCUS_GRAB "Hyprland Focus Grabbing" ON) if (NOT ${${REQUIRED_EFFECTIVE}})
option(SERVICE_STATUS_NOTIFIER "StatusNotifierItem service" ON) set(${STATUS} "OFF (Requires ${arg_REQUIRES})")
option(SERVICE_PIPEWIRE "PipeWire service" ON) set(${EFFECTIVE} OFF)
option(SERVICE_MPRIS "Mpris service" ON) endif()
option(SERVICE_PAM "Pam service" ON) endif()
option(SERVICE_GREETD "Greet service" ON)
option(SERVICE_UPOWER "UPower service" ON) set(${EFFECTIVE} "${${EFFECTIVE}}" PARENT_SCOPE)
option(SERVICE_NOTIFICATIONS "Notification server" ON)
message(STATUS " ${NAME}: ${${STATUS}}")
string(APPEND QS_BUILD_OPTIONS "\\n ${NAME}: ${${STATUS}}")
set(QS_BUILD_OPTIONS "${QS_BUILD_OPTIONS}" PARENT_SCOPE)
endfunction()
set(DISTRIBUTOR "Unset" CACHE STRING "Distributor")
string(APPEND QS_BUILD_OPTIONS " Distributor: ${DISTRIBUTOR}")
message(STATUS "Quickshell configuration") message(STATUS "Quickshell configuration")
message(STATUS " QML lib installation: ${INSTALL_QML_LIB}") message(STATUS " Distributor: ${DISTRIBUTOR}")
message(STATUS " Crash reporter: ${CRASH_REPORTER}") boption(DISTRIBUTOR_DEBUGINFO_AVAILABLE "Distributor provided debuginfo" NO)
message(STATUS " Jemalloc: ${USE_JEMALLOC}") boption(NO_PCH "Disable precompild headers (dev)" OFF)
message(STATUS " Build tests: ${BUILD_TESTING}") boption(BUILD_TESTING "Build tests (dev)" OFF)
message(STATUS " Sockets: ${SOCKETS}") boption(ASAN "ASAN (dev)" OFF) # note: better output with gcc than clang
message(STATUS " Wayland: ${WAYLAND}") boption(FRAME_POINTERS "Keep Frame Pointers (dev)" ${ASAN})
if (WAYLAND)
message(STATUS " Wlroots Layershell: ${WAYLAND_WLR_LAYERSHELL}") boption(CRASH_REPORTER "Crash Handling" ON)
message(STATUS " Session Lock: ${WAYLAND_SESSION_LOCK}") boption(USE_JEMALLOC "Use jemalloc" ON)
message(STATUS " Toplevel Management: ${WAYLAND_TOPLEVEL_MANAGEMENT}") boption(SOCKETS "Unix Sockets" ON)
endif () boption(WAYLAND "Wayland" ON)
message(STATUS " X11: ${X11}") boption(WAYLAND_WLR_LAYERSHELL " Wlroots Layer-Shell" ON REQUIRES WAYLAND)
message(STATUS " Services") boption(WAYLAND_SESSION_LOCK " Session Lock" ON REQUIRES WAYLAND)
message(STATUS " StatusNotifier: ${SERVICE_STATUS_NOTIFIER}") boption(WAYLAND_TOPLEVEL_MANAGEMENT " Foreign Toplevel Management" ON REQUIRES WAYLAND)
message(STATUS " PipeWire: ${SERVICE_PIPEWIRE}") boption(HYPRLAND " Hyprland" ON REQUIRES WAYLAND)
message(STATUS " Mpris: ${SERVICE_MPRIS}") boption(HYPRLAND_IPC " Hyprland IPC" ON REQUIRES HYPRLAND)
message(STATUS " Pam: ${SERVICE_PAM}") boption(HYPRLAND_GLOBAL_SHORTCUTS " Hyprland Global Shortcuts" ON REQUIRES HYPRLAND)
message(STATUS " Greetd: ${SERVICE_GREETD}") boption(HYPRLAND_FOCUS_GRAB " Hyprland Focus Grabbing" ON REQUIRES HYPRLAND)
message(STATUS " UPower: ${SERVICE_UPOWER}") boption(X11 "X11" ON)
message(STATUS " Notifications: ${SERVICE_NOTIFICATIONS}") boption(SERVICE_STATUS_NOTIFIER "System Tray" ON)
message(STATUS " Hyprland: ${HYPRLAND}") boption(SERVICE_PIPEWIRE "PipeWire" ON)
if (HYPRLAND) boption(SERVICE_MPRIS "Mpris" ON)
message(STATUS " IPC: ${HYPRLAND_IPC}") boption(SERVICE_PAM "Pam" ON)
message(STATUS " Focus Grabbing: ${HYPRLAND_FOCUS_GRAB}") boption(SERVICE_GREETD "Greetd" ON)
message(STATUS " Global Shortcuts: ${HYPRLAND_GLOBAL_SHORTCUTS}") boption(SERVICE_UPOWER "UPower" ON)
endif() boption(SERVICE_NOTIFICATIONS "Notifications" ON)
if (NOT DEFINED GIT_REVISION) if (NOT DEFINED GIT_REVISION)
execute_process( execute_process(
@ -157,13 +163,11 @@ if (USE_JEMALLOC)
target_link_libraries(quickshell PRIVATE ${JEMALLOC_LIBRARIES}) target_link_libraries(quickshell PRIVATE ${JEMALLOC_LIBRARIES})
endif() endif()
if (INSTALL_QML_LIB) install(
install( DIRECTORY ${CMAKE_BINARY_DIR}/qml_modules/
DIRECTORY ${CMAKE_BINARY_DIR}/qml_modules/ DESTINATION ${CMAKE_INSTALL_LIBDIR}/qt-6/qml
DESTINATION ${CMAKE_INSTALL_LIBDIR}/qt-6/qml FILES_MATCHING PATTERN "*"
FILES_MATCHING PATTERN "*" )
)
endif()
install(CODE " install(CODE "
execute_process( execute_process(

View file

@ -37,7 +37,6 @@
withPipewire ? true, withPipewire ? true,
withPam ? true, withPam ? true,
withHyprland ? true, withHyprland ? true,
withQMLLib ? true,
}: buildStdenv.mkDerivation { }: buildStdenv.mkDerivation {
pname = "quickshell${lib.optionalString debug "-debug"}"; pname = "quickshell${lib.optionalString debug "-debug"}";
version = "0.1.0"; version = "0.1.0";
@ -71,6 +70,8 @@
cmakeBuildType = if debug then "Debug" else "RelWithDebInfo"; cmakeBuildType = if debug then "Debug" else "RelWithDebInfo";
cmakeFlags = [ cmakeFlags = [
(lib.cmakeFeature "DISTRIBUTOR" "Official-Nix-Flake")
(lib.cmakeBool "DISTRIBUTOR_DEBUGINFO_AVAILABLE" true)
(lib.cmakeFeature "GIT_REVISION" gitRev) (lib.cmakeFeature "GIT_REVISION" gitRev)
(lib.cmakeBool "CRASH_REPORTER" withCrashReporter) (lib.cmakeBool "CRASH_REPORTER" withCrashReporter)
(lib.cmakeBool "USE_JEMALLOC" withJemalloc) (lib.cmakeBool "USE_JEMALLOC" withJemalloc)
@ -78,7 +79,6 @@
(lib.cmakeBool "SERVICE_PIPEWIRE" withPipewire) (lib.cmakeBool "SERVICE_PIPEWIRE" withPipewire)
(lib.cmakeBool "SERVICE_PAM" withPam) (lib.cmakeBool "SERVICE_PAM" withPam)
(lib.cmakeBool "HYPRLAND" withHyprland) (lib.cmakeBool "HYPRLAND" withHyprland)
(lib.cmakeBool "INSTALL_QML_LIB" withQMLLib)
]; ];
# How to get debuginfo in gdb from a release build: # How to get debuginfo in gdb from a release build:

View file

@ -52,8 +52,16 @@ else()
set(CRASH_REPORTER_DEF 0) set(CRASH_REPORTER_DEF 0)
endif() endif()
if (DISTRIBUTOR_DEBUGINFO_AVAILABLE)
set(DEBUGINFO_AVAILABLE 1)
else()
set(DEBUGINFO_AVAILABLE 0)
endif()
add_library(quickshell-build INTERFACE) add_library(quickshell-build INTERFACE)
configure_file(build.hpp.in build.hpp)
configure_file(build.hpp.in build.hpp @ONLY ESCAPE_QUOTES)
target_include_directories(quickshell-build INTERFACE ${CMAKE_CURRENT_BINARY_DIR}) target_include_directories(quickshell-build INTERFACE ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(quickshell-core PRIVATE quickshell-build) target_link_libraries(quickshell-core PRIVATE quickshell-build)

View file

@ -2,5 +2,11 @@
// NOLINTBEGIN // NOLINTBEGIN
#define GIT_REVISION "@GIT_REVISION@" #define GIT_REVISION "@GIT_REVISION@"
#define DISTRIBUTOR "@DISTRIBUTOR@"
#define DISTRIBUTOR_DEBUGINFO_AVAILABLE @DEBUGINFO_AVAILABLE@
#define CRASH_REPORTER @CRASH_REPORTER_DEF@ #define CRASH_REPORTER @CRASH_REPORTER_DEF@
#define BUILD_TYPE "@CMAKE_BUILD_TYPE@"
#define COMPILER "@CMAKE_CXX_COMPILER_ID@ (@CMAKE_CXX_COMPILER_VERSION@)"
#define COMPILE_FLAGS "@CMAKE_CXX_FLAGS@"
#define BUILD_CONFIGURATION "@QS_BUILD_OPTIONS@"
// NOLINTEND // NOLINTEND

View file

@ -13,6 +13,7 @@
#include <CLI/Validators.hpp> #include <CLI/Validators.hpp>
#include <fcntl.h> #include <fcntl.h>
#include <qapplication.h> #include <qapplication.h>
#include <qconfig.h>
#include <qcontainerfwd.h> #include <qcontainerfwd.h>
#include <qcoreapplication.h> #include <qcoreapplication.h>
#include <qcryptographichash.h> #include <qcryptographichash.h>
@ -36,6 +37,7 @@
#include <qstring.h> #include <qstring.h>
#include <qtenvironmentvariables.h> #include <qtenvironmentvariables.h>
#include <qtextstream.h> #include <qtextstream.h>
#include <qtversion.h>
#include <unistd.h> #include <unistd.h>
#include "../io/ipccomm.hpp" #include "../io/ipccomm.hpp"
@ -425,7 +427,21 @@ int runCommand(int argc, char** argv, QCoreApplication* coreApplication) {
} }
if (state.misc.printVersion) { if (state.misc.printVersion) {
qCInfo(logBare).noquote() << "quickshell pre-release, revision" << GIT_REVISION; qCInfo(logBare).noquote().nospace() << "quickshell pre-release, revision " << GIT_REVISION
<< ", distributed by: " << DISTRIBUTOR;
if (state.log.verbosity > 1) {
qCInfo(logBare).noquote() << "\nBuildtime Qt Version:" << QT_VERSION_STR;
qCInfo(logBare).noquote() << "Runtime Qt Version:" << qVersion();
qCInfo(logBare).noquote() << "Compiler:" << COMPILER;
qCInfo(logBare).noquote() << "Compile Flags:" << COMPILE_FLAGS;
}
if (state.log.verbosity > 0) {
qCInfo(logBare).noquote() << "\nBuild Type:" << BUILD_TYPE;
qCInfo(logBare).noquote() << "Build configuration:";
qCInfo(logBare).noquote().nospace() << BUILD_CONFIGURATION;
}
} else if (*state.subcommand.log) { } else if (*state.subcommand.log) {
return readLogFile(state); return readLogFile(state);
} else if (*state.subcommand.list) { } else if (*state.subcommand.list) {

View file

@ -54,7 +54,7 @@ CrashReporterGui::CrashReporterGui(QString reportFolder, int pid)
mainLayout->addWidget(new ReportLabel( mainLayout->addWidget(new ReportLabel(
"Github:", "Github:",
"https://github.com/outfoxxed/quickshell/issues/new?template=crash.yml", "https://github.com/quickshell-mirror/quickshell/issues/new?template=crash.yml",
this this
)); ));

View file

@ -11,6 +11,8 @@
#include <qloggingcategory.h> #include <qloggingcategory.h>
#include <qtenvironmentvariables.h> #include <qtenvironmentvariables.h>
#include <qtextstream.h> #include <qtextstream.h>
#include <qtversion.h>
#include <qversiontagging.h>
#include <sys/sendfile.h> #include <sys/sendfile.h>
#include <sys/types.h> #include <sys/types.h>
@ -111,39 +113,53 @@ void recordCrashInfo(const QDir& crashDir, const InstanceInfo& instance) {
auto logFd = qEnvironmentVariable("__QUICKSHELL_CRASH_LOG_FD").toInt(); auto logFd = qEnvironmentVariable("__QUICKSHELL_CRASH_LOG_FD").toInt();
qCDebug(logCrashReporter) << "Saving minidump from fd" << dumpFd; qCDebug(logCrashReporter) << "Saving minidump from fd" << dumpFd;
auto dumpDupStatus = tryDup(dumpFd, crashDir.filePath("minidump.dmp")); auto dumpDupStatus = tryDup(dumpFd, crashDir.filePath("minidump.dmp.log"));
if (dumpDupStatus != 0) { if (dumpDupStatus != 0) {
qCCritical(logCrashReporter) << "Failed to write minidump:" << dumpDupStatus; qCCritical(logCrashReporter) << "Failed to write minidump:" << dumpDupStatus;
} }
qCDebug(logCrashReporter) << "Saving log from fd" << logFd; qCDebug(logCrashReporter) << "Saving log from fd" << logFd;
auto logDupStatus = tryDup(logFd, crashDir.filePath("log.qslog")); auto logDupStatus = tryDup(logFd, crashDir.filePath("log.qslog.log"));
if (logDupStatus != 0) { if (logDupStatus != 0) {
qCCritical(logCrashReporter) << "Failed to save log:" << logDupStatus; qCCritical(logCrashReporter) << "Failed to save log:" << logDupStatus;
} }
auto copyBinStatus = 0;
if (!DISTRIBUTOR_DEBUGINFO_AVAILABLE) {
qCDebug(logCrashReporter) << "Copying binary to crash folder";
if (!QFile(QCoreApplication::applicationFilePath()).copy(crashDir.filePath("executable.txt"))) {
copyBinStatus = 1;
qCCritical(logCrashReporter) << "Failed to copy binary.";
}
}
{ {
auto extraInfoFile = QFile(crashDir.filePath("info.txt")); auto extraInfoFile = QFile(crashDir.filePath("info.txt"));
if (!extraInfoFile.open(QFile::WriteOnly)) { if (!extraInfoFile.open(QFile::WriteOnly)) {
qCCritical(logCrashReporter) << "Failed to open crash info file for writing."; qCCritical(logCrashReporter) << "Failed to open crash info file for writing.";
} else { } else {
auto stream = QTextStream(&extraInfoFile); auto stream = QTextStream(&extraInfoFile);
stream << "===== Quickshell Crash =====\n"; stream << "===== Build Information =====\n";
stream << "Git Revision: " << GIT_REVISION << '\n'; stream << "Git Revision: " << GIT_REVISION << '\n';
stream << "Buildtime Qt Version: " << QT_VERSION_STR << "\n";
stream << "Build Type: " << BUILD_TYPE << '\n';
stream << "Compiler: " << COMPILER << '\n';
stream << "Complie Flags: " << COMPILE_FLAGS << "\n\n";
stream << "Build configuration:\n" << BUILD_CONFIGURATION << "\n";
stream << "\n===== Runtime Information =====\n";
stream << "Runtime Qt Version: " << qVersion() << '\n';
stream << "Crashed process ID: " << crashProc << '\n'; stream << "Crashed process ID: " << crashProc << '\n';
stream << "Run ID: " << instance.instanceId << '\n'; stream << "Run ID: " << instance.instanceId << '\n';
stream << "\n===== Shell Information =====\n";
stream << "Shell ID: " << instance.shellId << '\n'; stream << "Shell ID: " << instance.shellId << '\n';
stream << "Config Path: " << instance.configPath << '\n'; stream << "Config Path: " << instance.configPath << '\n';
stream << "\n===== Report Integrity =====\n"; stream << "\n===== Report Integrity =====\n";
stream << "Minidump save status: " << dumpDupStatus << '\n'; stream << "Minidump save status: " << dumpDupStatus << '\n';
stream << "Log save status: " << logDupStatus << '\n'; stream << "Log save status: " << logDupStatus << '\n';
stream << "Binary copy status: " << copyBinStatus << '\n';
stream << "\n===== System Information =====\n"; stream << "\n===== System Information =====\n\n";
stream << "Qt Version: " << QT_VERSION_STR << "\n\n";
stream << "/etc/os-release:"; stream << "/etc/os-release:";
auto osReleaseFile = QFile("/etc/os-release"); auto osReleaseFile = QFile("/etc/os-release");
if (osReleaseFile.open(QFile::ReadOnly)) { if (osReleaseFile.open(QFile::ReadOnly)) {
@ -156,7 +172,7 @@ void recordCrashInfo(const QDir& crashDir, const InstanceInfo& instance) {
stream << "/etc/lsb-release:"; stream << "/etc/lsb-release:";
auto lsbReleaseFile = QFile("/etc/lsb-release"); auto lsbReleaseFile = QFile("/etc/lsb-release");
if (lsbReleaseFile.open(QFile::ReadOnly)) { if (lsbReleaseFile.open(QFile::ReadOnly)) {
stream << '\n' << lsbReleaseFile.readAll() << '\n'; stream << '\n' << lsbReleaseFile.readAll();
lsbReleaseFile.close(); lsbReleaseFile.close();
} else { } else {
stream << "FAILED TO OPEN\n"; stream << "FAILED TO OPEN\n";