diff --git a/cmake/macros/GenerateQrc.cmake b/cmake/macros/GenerateQrc.cmake index 0283b3ea9b..9bf530b2a2 100644 --- a/cmake/macros/GenerateQrc.cmake +++ b/cmake/macros/GenerateQrc.cmake @@ -12,9 +12,14 @@ function(GENERATE_QRC) foreach(GLOB ${GENERATE_QRC_GLOBS}) file(GLOB_RECURSE FOUND_FILES RELATIVE ${GENERATE_QRC_PATH} ${GLOB}) foreach(FILENAME ${FOUND_FILES}) + if (${FILENAME} MATCHES "^\\.\\.") + continue() + endif() + list(APPEND ALL_FILES "${GENERATE_QRC_PATH}/${FILENAME}") set(QRC_CONTENTS "${QRC_CONTENTS}${GENERATE_QRC_PATH}/${FILENAME}\n") endforeach() endforeach() - + + set(GENERATE_QRC_DEPENDS ${ALL_FILES} PARENT_SCOPE) configure_file("${HF_CMAKE_DIR}/templates/resources.qrc.in" ${GENERATE_QRC_OUTPUT}) endfunction() diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 1ad3aefa3f..ce5685bc9f 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -11,8 +11,21 @@ function(JOIN VALUES GLUE OUTPUT) set (${OUTPUT} "${_TMP_STR}" PARENT_SCOPE) endfunction() -set(INTERFACE_QML_QRC ${CMAKE_CURRENT_BINARY_DIR}/qml.qrc) -generate_qrc(OUTPUT ${INTERFACE_QML_QRC} PATH ${CMAKE_CURRENT_SOURCE_DIR}/resources GLOBS *.qml *.qss *.js *.html *.ttf *.gif *.svg *.png *.jpg) +set(RESOURCES_QRC ${CMAKE_CURRENT_BINARY_DIR}/resources.qrc) +set(RESOURCES_RCC ${CMAKE_CURRENT_BINARY_DIR}/resources.rcc) +generate_qrc(OUTPUT ${RESOURCES_QRC} PATH ${CMAKE_CURRENT_SOURCE_DIR}/resources GLOBS *) + +add_custom_command( + OUTPUT ${RESOURCES_RCC} + COMMAND "${QT_DIR}/bin/rcc" + ARGS ${RESOURCES_QRC} -binary -o ${RESOURCES_RCC} + MAIN_DEPENDENCY ${RESOURCES_QRC} + DEPENDS ${GENERATE_QRC_DEPENDS} +) + +list(APPEND GENERATE_QRC_DEPENDS ${RESOURCES_RCC}) +add_custom_target(resources ALL DEPENDS ${GENERATE_QRC_DEPENDS}) + # set a default root dir for each of our optional externals if it was not passed set(OPTIONAL_EXTERNALS "LeapMotion") @@ -71,16 +84,6 @@ qt5_wrap_ui(QT_UI_HEADERS "${QT_UI_FILES}") # add them to the interface source files set(INTERFACE_SRCS ${INTERFACE_SRCS} "${QT_UI_HEADERS}" "${QT_RESOURCES}") -list(APPEND INTERFACE_SRCS ${INTERFACE_QML_QRC}) - -if (UNIX) - install( - DIRECTORY "${CMAKE_SOURCE_DIR}/interface/resources/qml" - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/resources - COMPONENT ${CLIENT_COMPONENT} - ) -endif() - # translation disabled until we strip out the line numbers # set(QM ${TARGET_NAME}_en.qm) # set(TS ${TARGET_NAME}_en.ts) @@ -160,6 +163,8 @@ else () add_executable(${TARGET_NAME} ${INTERFACE_SRCS} ${QM}) endif () +add_dependencies(${TARGET_NAME} resources) + if (WIN32) # These are external plugins, but we need to do the 'add dependency' here so that their # binary directories get added to the fixup path @@ -235,7 +240,7 @@ foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) if (NOT APPLE OR NOT ${${EXTERNAL}_UPPERCASE} MATCHES "SIXENSE") target_link_libraries(${TARGET_NAME} ${${${EXTERNAL}_UPPERCASE}_LIBRARIES}) elseif (APPLE AND NOT INSTALLER_BUILD) - add_definitions(-DSIXENSE_LIB_FILENAME=\"${${${EXTERNAL}_UPPERCASE}_LIBRARY_RELEASE}\") + #add_definitions(-DSIXENSE_LIB_FILENAME=\"${${${EXTERNAL}_UPPERCASE}_LIBRARY_RELEASE}\") endif () endif () endforeach() @@ -294,12 +299,12 @@ if (APPLE) # call the fixup_interface macro to add required bundling commands for installation fixup_interface() -else (APPLE) +else() # copy the resources files beside the executable add_custom_command(TARGET ${TARGET_NAME} POST_BUILD - COMMAND "${CMAKE_COMMAND}" -E copy_directory - "${PROJECT_SOURCE_DIR}/resources" - "$/resources" + COMMAND "${CMAKE_COMMAND}" -E copy_if_different + "${RESOURCES_RCC}" + "$" COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_SOURCE_DIR}/scripts" "$/scripts" @@ -325,7 +330,7 @@ else (APPLE) optional_win_executable_signing() endif() -endif (APPLE) +endif() if (SCRIPTS_INSTALL_DIR) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index caa1af0485..5823a4928a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -804,6 +805,18 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo _sampleSound(nullptr) { + + { +#if defined(Q_OS_ANDROID) + const QString resourcesBinaryFile = "assets:resources.rcc"; +#else + const QString resourcesBinaryFile = QFileInfo(argv[0]).absolutePath() + "/resources.rcc"; +#endif + if (!QResource::registerResource(resourcesBinaryFile)) { + throw std::runtime_error("Unable to load primary resources"); + } + } + auto steamClient = PluginManager::getInstance()->getSteamClientPlugin(); setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning())); setProperty(hifi::properties::CRASHED, _previousSessionCrashed); diff --git a/libraries/shared/src/PathUtils.cpp b/libraries/shared/src/PathUtils.cpp index 22e11464bd..dc1bd198d9 100644 --- a/libraries/shared/src/PathUtils.cpp +++ b/libraries/shared/src/PathUtils.cpp @@ -11,17 +11,20 @@ #include "PathUtils.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include // std::once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "shared/GlobalAppProperties.h" #include "SharedUtil.h" @@ -29,16 +32,10 @@ // Example: ... QString TEMP_DIR_FORMAT { "%1-%2-%3" }; -const QString& PathUtils::resourcesPath() { -#ifdef Q_OS_MAC - static const QString staticResourcePath = QCoreApplication::applicationDirPath() + "/../Resources/"; -#elif defined (ANDROID) - static const QString staticResourcePath = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/resources/"; -#else - static const QString staticResourcePath = QCoreApplication::applicationDirPath() + "/resources/"; +#if !defined(Q_OS_ANDROID) && defined(DEV_BUILD) +static const QString USE_SOURCE_TREE_RESOURCES_FLAG("HIFI_USE_SOURCE_TREE_RESOURCES"); +static bool USE_SOURCE_TREE_RESOURCES = QProcessEnvironment::systemEnvironment().contains(USE_SOURCE_TREE_RESOURCES_FLAG); #endif - return staticResourcePath; -} #ifdef DEV_BUILD const QString& PathUtils::projectRootPath() { @@ -52,15 +49,28 @@ const QString& PathUtils::projectRootPath() { } #endif -const QString& PathUtils::qmlBasePath() { -#ifdef Q_OS_ANDROID - static const QString staticResourcePath = "qrc:///qml/"; -#elif defined (DEV_BUILD) - static const QString staticResourcePath = QUrl::fromLocalFile(projectRootPath() + "/interface/resources/qml/").toString(); -#else - static const QString staticResourcePath = "qrc:///qml/"; +const QString& PathUtils::resourcesPath() { +#if !defined(Q_OS_ANDROID) && defined(DEV_BUILD) + // For dev builds, load + if (USE_SOURCE_TREE_RESOURCES) { + static const QString staticResourcePath = projectRootPath() + "/interface/resources/"; + return staticResourcePath; + } #endif + static const QString staticResourcePath = ":/"; + return staticResourcePath; +} +// FIXME rename to qmlBaseUrl +const QString& PathUtils::qmlBasePath() { +#if !defined(Q_OS_ANDROID) && defined(DEV_BUILD) + // For dev builds, load + if (USE_SOURCE_TREE_RESOURCES) { + static const QString staticResourcePath = QUrl::fromLocalFile(projectRootPath() + "/interface/resources/qml").toString(); + return staticResourcePath; + } +#endif + static const QString staticResourcePath = "qrc:///qml/"; return staticResourcePath; } diff --git a/libraries/shared/src/shared/Storage.cpp b/libraries/shared/src/shared/Storage.cpp index 7e9f86b049..b98df8406e 100644 --- a/libraries/shared/src/shared/Storage.cpp +++ b/libraries/shared/src/shared/Storage.cpp @@ -79,12 +79,14 @@ FileStorage::FileStorage(const QString& filename) : _file(filename) { } if (opened) { - _mapped = _file.map(0, _file.size()); - if (_mapped) { - _valid = true; - } else { - qCWarning(storagelogging) << "Failed to map file " << filename; - } + _size = _file.size(); + _mapped = _file.map(0, _size); + if (!_mapped) { + qCDebug(storagelogging) << "Failed to map file, falling back to memory storage " << filename; + _fallback = _file.readAll(); + _mapped = (uint8_t*)_fallback.data(); + } + _valid = true; } else { qCWarning(storagelogging) << "Failed to open file " << filename; } @@ -92,7 +94,9 @@ FileStorage::FileStorage(const QString& filename) : _file(filename) { FileStorage::~FileStorage() { if (_mapped) { - _file.unmap(_mapped); + if (_fallback.isEmpty()) { + _file.unmap(_mapped); + } _mapped = nullptr; } if (_file.isOpen()) { diff --git a/libraries/shared/src/shared/Storage.h b/libraries/shared/src/shared/Storage.h index d7946738cf..0e5032bb62 100644 --- a/libraries/shared/src/shared/Storage.h +++ b/libraries/shared/src/shared/Storage.h @@ -61,10 +61,12 @@ namespace storage { const uint8_t* data() const override { return _mapped; } uint8_t* mutableData() override { return _hasWriteAccess ? _mapped : nullptr; } - size_t size() const override { return _file.size(); } + size_t size() const override { return _size; } operator bool() const override { return _valid; } private: - + // For compressed QRC files we can't map the file object, so we need to read it into memory + QByteArray _fallback; + size_t _size { 0 }; bool _valid { false }; bool _hasWriteAccess { false }; QFile _file;