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;