From 057c151fe8592ec5f160ae5f7891c1f1b5c998dc Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Fri, 13 Nov 2020 19:04:17 -0800 Subject: [PATCH] build-system: start adding a headless build Right now this doesn't do a thing, but it gives us a nice target that has far fewer dependencies and should contain enough parts to download stuff from a divecomputer and then sync that with cloud storage. Signed-off-by: Dirk Hohndel --- CMakeLists.txt | 34 +++++++-- core/divefilter.cpp | 4 +- core/qthelper.cpp | 2 + core/subsurfacestartup.c | 4 ++ subsurface-downloader-main.cpp | 124 +++++++++++++++++++++++++++++++++ 5 files changed, 162 insertions(+), 6 deletions(-) create mode 100644 subsurface-downloader-main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 478bf305d..d48617afa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,8 +52,8 @@ option(FTDISUPPORT "enable support for libftdi based serial" OFF) # Options regarding What should we build on subsurface option(MAKE_TESTS "Make the tests" ON) -SET(SUBSURFACE_TARGET_EXECUTABLE "DesktopExecutable" CACHE STRING "The type of application, DesktopExecutable or MobileExecutable") -LIST(APPEND SUBSURFACE_ACCEPTED_EXECUTABLES "DesktopExecutable" "MobileExecutable") +SET(SUBSURFACE_TARGET_EXECUTABLE "DesktopExecutable" CACHE STRING "The type of application, DesktopExecutable, MobileExecutable, or DownloaderExecutable") +LIST(APPEND SUBSURFACE_ACCEPTED_EXECUTABLES "DesktopExecutable" "MobileExecutable" "DownloaderExecutable") SET_PROPERTY(CACHE SUBSURFACE_TARGET_EXECUTABLE PROPERTY STRINGS ${SUBSURFACE_ACCEPTED_EXECUTABLES}) #verify if Platform is correct and warn on wxit with example. @@ -199,6 +199,11 @@ elseif (SUBSURFACE_TARGET_EXECUTABLE MATCHES "MobileExecutable") message(STATUS "Building Subsurface-mobile requires BT support") set(BTSUPPORT ON) +elseif (SUBSURFACE_TARGET_EXECUTABLE MATCHES "DownloaderExecutable") + set(SUBSURFACE_TARGET subsurface-downloader) + set(BTSUPPORT ON) + add_definitions(-DSUBSURFACE_DOWNLOADER) + message(STATUS "building the embedded Subsurface-downloader app") endif() if(ANDROID) @@ -269,13 +274,17 @@ endif() set(QT_FIND_COMPONENTS Core Concurrent Widgets Network Svg Positioning Quick Location ${QT_EXTRA_COMPONENTS}) if (SUBSURFACE_TARGET_EXECUTABLE MATCHES "DesktopExecutable") find_package(Qt5 5.9.1 REQUIRED COMPONENTS ${QT_FIND_COMPONENTS} LinguistTools Test QuickTest) -else() +elseif (SUBSURFACE_TARGET_EXECUTABLE MATCHES "MobileExecutable") # Kirigami 5.62 and newer require at least Qt 5.12 if(ANDROID) find_package(Qt5 5.12 REQUIRED COMPONENTS ${QT_FIND_COMPONENTS} LinguistTools) else() find_package(Qt5 5.12 REQUIRED COMPONENTS ${QT_FIND_COMPONENTS} LinguistTools Test QuickTest) endif() +elseif (SUBSURFACE_TARGET_EXECUTABLE MATCHES "DownloaderExecutable") + # let's pick a version that's not ancient + find_package(Qt5 5.12 REQUIRED COMPONENTS ${QT_FIND_COMPONENTS}) + set(MAKE_TESTS OFF) endif() foreach(_QT_COMPONENT ${QT_FIND_COMPONENTS}) list(APPEND QT_LIBRARIES Qt5::${_QT_COMPONENT}) @@ -286,7 +295,9 @@ endif() #set up the subsurface_link_libraries variable set(SUBSURFACE_LINK_LIBRARIES ${SUBSURFACE_LINK_LIBRARIES} ${LIBDIVECOMPUTER_LIBRARIES} ${LIBGIT2_LIBRARIES} ${LIBUSB_LIBRARIES} ${LIBMTP_LIBRARIES}) -qt5_add_resources(SUBSURFACE_RESOURCES subsurface.qrc map-widget/qml/map-widget.qrc) +if (NOT SUBSURFACE_TARGET_EXECUTABLE MATCHES "DownloaderExecutable") + qt5_add_resources(SUBSURFACE_RESOURCES subsurface.qrc map-widget/qml/map-widget.qrc) +endif() # hack to build successfully on LGTM if(DEFINED ENV{LGTM_SRC}) @@ -294,13 +305,17 @@ if(DEFINED ENV{LGTM_SRC}) endif() # include translations +if (NOT SUBSURFACE_TARGET_EXECUTABLE MATCHES "DownloaderExecutable") add_subdirectory(translations) +endif() add_subdirectory(core) add_subdirectory(qt-models) add_subdirectory(commands) +if (NOT SUBSURFACE_TARGET_EXECUTABLE MATCHES "DownloaderExecutable") add_subdirectory(profile-widget) add_subdirectory(map-widget) add_subdirectory(mobile-widgets) +endif() add_subdirectory(backend-shared) if (SUBSURFACE_TARGET_EXECUTABLE MATCHES "DesktopExecutable") @@ -370,6 +385,17 @@ elseif (SUBSURFACE_TARGET_EXECUTABLE MATCHES "DesktopExecutable") add_dependencies(subsurface_profile subsurface_generated_ui) add_dependencies(subsurface_models_desktop subsurface_generated_ui) add_dependencies(subsurface_generated_ui version) +elseif (SUBSURFACE_TARGET_EXECUTABLE MATCHES "DownloaderExecutable") + set(DOWNLOADER_APP + subsurface-downloader-main.cpp + ) + source_group("Downloader App" FILES ${DOWNLOADER_APP}) + add_executable(${SUBSURFACE_TARGET} MACOSX_BUNDLE WIN32 ${SUBSURFACE_PKG} ${DOWNLOADER_APP} ${SUBSURFACE_RESOURCES}) + target_link_libraries( + ${SUBSURFACE_TARGET} + subsurface_corelib + ${SUBSURFACE_LINK_LIBRARIES} + ) endif() add_dependencies(subsurface_corelib version) diff --git a/core/divefilter.cpp b/core/divefilter.cpp index 23d023b9d..0aa78e53b 100644 --- a/core/divefilter.cpp +++ b/core/divefilter.cpp @@ -5,7 +5,7 @@ #include "gettextfromc.h" #include "qthelper.h" #include "subsurface-qt/divelistnotifier.h" -#ifndef SUBSURFACE_MOBILE +#if !defined(SUBSURFACE_MOBILE) && !defined(SUBSURFACE_DOWNLOADER) #include "desktop-widgets/mapwidget.h" #include "desktop-widgets/mainwindow.h" #include "desktop-widgets/divelistview.h" @@ -103,7 +103,7 @@ bool DiveFilter::showDive(const struct dive *d) const [d] (const filter_constraint &c) { return filter_constraint_match_dive(c, d); }); } -#ifndef SUBSURFACE_MOBILE +#if !defined(SUBSURFACE_MOBILE) && !defined(SUBSURFACE_DOWNLOADER) void DiveFilter::startFilterDiveSites(QVector ds) { if (++diveSiteRefCount > 1) { diff --git a/core/qthelper.cpp b/core/qthelper.cpp index fd19e78a3..2e74c5625 100644 --- a/core/qthelper.cpp +++ b/core/qthelper.cpp @@ -419,6 +419,8 @@ QString getUserAgent() // replace all other ':' with ' ' so that this is easy to parse #ifdef SUBSURFACE_MOBILE QString userAgent = QString("Subsurface-mobile:%1(%2):").arg(subsurface_mobile_version()).arg(subsurface_canonical_version()); +#elif SUBSURFACE_DOWNLOADER + QString userAgent = QString("Subsurface-downloader:%1:").arg(subsurface_canonical_version()); #else QString userAgent = QString("Subsurface:%1:").arg(subsurface_canonical_version()); #endif diff --git a/core/subsurfacestartup.c b/core/subsurfacestartup.c index bdb908ea5..c12357cbc 100644 --- a/core/subsurfacestartup.c +++ b/core/subsurfacestartup.c @@ -132,7 +132,11 @@ void print_version() static bool version_printed = false; if (version_printed) return; +#if defined(SUBSURFACE_DOWNLOADER) + printf("Subsurface-downloader v%s,\n", subsurface_git_version()); +#else printf("Subsurface v%s,\n", subsurface_git_version()); +#endif printf("built with libdivecomputer v%s\n", dc_version(NULL)); print_qt_versions(); int git_maj, git_min, git_rev; diff --git a/subsurface-downloader-main.cpp b/subsurface-downloader-main.cpp new file mode 100644 index 000000000..8a3231ce5 --- /dev/null +++ b/subsurface-downloader-main.cpp @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0 +/* main.c */ +#include "core/downloadfromdcthread.h" // for fill_computer_list +#include "core/errorhelper.h" +#include "core/parse.h" +#include "core/qthelper.h" +#include "core/subsurfacestartup.h" +#include "core/settings/qPref.h" +#include "core/tag.h" +#include "core/dive.h" + +#include +#include +#include +#include + +static bool filesOnCommandLine = false; +static void messageHandler(QtMsgType type, const QMessageLogContext &ctx, const QString &msg); + +int main(int argc, char **argv) +{ + qInstallMessageHandler(messageHandler); + // we always run this in verbose mode as there is no UI + verbose = 1; + + // now let's say Hi + print_version(); + + // supporting BT makes sense when used with an iPhone and an rfcomm BT device? + QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true")); + + int i; + bool no_filenames = true; + std::unique_ptr app(new QApplication(argc, argv)); + QStringList files; + QStringList importedFiles; + QStringList arguments = QCoreApplication::arguments(); + + const char *default_directory = system_default_directory(); + const char *default_filename = system_default_filename(); + subsurface_mkdir(default_directory); + + if (subsurface_user_is_root() && !force_root) { + printf("You are running Subsurface as root. This is not recommended.\n"); + printf("If you insist to do so, run with option --allow_run_as_root.\n"); + exit(0); + } + git_libgit2_init(); + setup_system_prefs(); + copy_prefs(&default_prefs, &prefs); + + // now handle the arguments + for (i = 1; i < arguments.length(); i++) { + QString a = arguments.at(i); + if (a.isEmpty()) + continue; + if (a.at(0) == '-') { + parse_argument(qPrintable(a)); + continue; + } + if (imported) { + importedFiles.push_back(a); + } else { + no_filenames = false; + files.push_back(a); + } + } + fill_computer_list(); + parse_xml_init(); + taglist_init_global(); + + if (no_filenames) { + if (prefs.default_file_behavior == LOCAL_DEFAULT_FILE) { + QString defaultFile(prefs.default_filename); + if (!defaultFile.isEmpty()) + files.push_back(QString(prefs.default_filename)); + } else if (prefs.default_file_behavior == CLOUD_DEFAULT_FILE) { + QString cloudURL; + if (getCloudURL(cloudURL) == 0) + files.push_back(cloudURL); + } + } + filesOnCommandLine = !files.isEmpty() || !importedFiles.isEmpty(); + if (!files.isEmpty()) + qDebug() << "loading dive data from" << files; + print_files(); + if (!quit) { + // do something + ; + } + taglist_free(g_tag_list); + parse_xml_exit(); + free((void *)default_directory); + free((void *)default_filename); + + // Sync struct preferences to disk + qPref::sync(); + + free_prefs(); + return 0; +} + +// install this message handler primarily so that the Windows build can log to files +void messageHandler(QtMsgType type, const QMessageLogContext &, const QString &msg) +{ + QByteArray localMsg = msg.toUtf8(); + switch (type) { + case QtDebugMsg: + fprintf(stdout, "%s\n", localMsg.constData()); + break; + case QtInfoMsg: + fprintf(stdout, "%s\n", localMsg.constData()); + break; + case QtWarningMsg: + fprintf(stderr, "%s\n", localMsg.constData()); + break; + case QtCriticalMsg: + fprintf(stderr, "%s\n", localMsg.constData()); + break; + case QtFatalMsg: + fprintf(stderr, "%s\n", localMsg.constData()); + abort(); + } +}