sys/build: Properly support per-system metadata file paths (#181)

* sys: Move away from metadata paths next to executable in the application

Build system doesn't properly install / pack stuff yet

* build: Updated README to contain better install instructions

* sys: Search for imhex resource files in ~/Application Support

* sys: MAX_PATH -> PATH_MAX

* sys: Seach for imhex resource files in Application Support using NSFileManager (#180)

* sys: Allow for multiple file search paths

Also use install prefix instead of just /usr on Linux

* build: Fixed IMHEX_INSTALL_PREFIX macro definition

* build: Fix duplicate switch entry on Linux

* docs: Updated readme to properly reflect new paths and dependencies

* sys: Install files in their proper paths on linux (#183)

* Install files in their proper paths on linux

* Only create user directories

* Follow the XDG specification on linux

XDG specification specifies how to find config and data directories on
linux systems. Specifically, it says this:

- Data should be written to $XDG_DATA_HOME
- Config should be written to $XDG_CONFIG_HOME
- Data should be read from $XDG_DATA_HOME:$XDG_DATA_DIRS
- Config should be read from $XDG_CONFIG_HOME:$XDG_CONFIG_DIRS

The default values are this:

- XDG_DATA_HOME: $HOME/.local/share
- XDG_CONFIG_HOME: $HOME/.config
- XDG_DATA_DIRS: /usr/share:/usr/local/share
- XDG_CONFIG_DIRS: /etc/xdg

Platforms with non-standard filesystems (like NixOS) will correctly set
up those environment variables, allowing softwares to work unmodified.

In order to make integration as simple as possible, we use a simple
header-only dependency called XDGPP which does all the hard work for us
to find the default directories.

* Look for plugins in all Plugin Paths

If the plugin folder was missing from one of the PluginPaths, we would
immediately stop loading plugins. We now keep looking even if one of the
path is missing.

Co-authored-by: Nichole Mattera <me@nicholemattera.com>
Co-authored-by: Robin Lambertz <unfiltered@roblab.la>
This commit is contained in:
WerWolv
2021-03-01 08:56:49 +01:00
committed by GitHub
parent c26bea06d6
commit 3e6865ffa9
16 changed files with 365 additions and 91 deletions

View File

@@ -6,7 +6,7 @@ set(CMAKE_CXX_STANDARD 20)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../external/ImGui ${CMAKE_CURRENT_BINARY_DIR}/external/ImGui)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../external/nlohmann_json ${CMAKE_CURRENT_BINARY_DIR}/external/nlohmann_json)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../external/nativefiledialog ${CMAKE_CURRENT_BINARY_DIR}/external/nativefiledialog)
set(XDGPP_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/../../external/xdgpp")
if (WIN32)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++ -static-libgcc -Wl,-Bstatic,--whole-archive -lwinpthread -Wl,--no-whole-archive")
@@ -16,34 +16,53 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
set(CMAKE_SHARED_LIBRARY_PREFIX "")
add_library(libimhex SHARED
source/api/event.cpp
source/api/imhex_api.cpp
source/api/content_registry.cpp
set(LIBIMHEX_SOURCES
source/api/event.cpp
source/api/imhex_api.cpp
source/api/content_registry.cpp
source/helpers/utils.cpp
source/helpers/shared_data.cpp
source/helpers/crypto.cpp
source/helpers/lang.cpp
source/helpers/utils.cpp
source/helpers/shared_data.cpp
source/helpers/crypto.cpp
source/helpers/lang.cpp
source/lang/pattern_language.cpp
source/lang/preprocessor.cpp
source/lang/lexer.cpp
source/lang/parser.cpp
source/lang/validator.cpp
source/lang/evaluator.cpp
source/lang/builtin_functions.cpp
source/lang/pattern_language.cpp
source/lang/preprocessor.cpp
source/lang/lexer.cpp
source/lang/parser.cpp
source/lang/validator.cpp
source/lang/evaluator.cpp
source/lang/builtin_functions.cpp
source/providers/provider.cpp
source/providers/provider.cpp
source/views/view.cpp
)
source/views/view.cpp
)
target_include_directories(libimhex PUBLIC include ${MBEDTLS_INCLUDE_DIR})
if (APPLE)
set(OSX_11_0_SDK_PATH /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.0.sdk)
if (NOT CMAKE_OSX_SYSROOT)
if (IS_DIRECTORY ${OSX_11_0_SDK_PATH})
set(CMAKE_OSX_SYSROOT ${OSX_11_0_SDK_PATH})
else ()
message(WARNING "CMAKE_OSX_SYSROOT not set and macOS 10.9 SDK not found! Using default one.")
endif ()
endif ()
set(CMAKE_OSX_DEPLOYMENT_TARGET 11.0)
set(LIBIMHEX_SOURCES ${LIBIMHEX_SOURCES} source/helpers/utils_mac.mm)
endif ()
add_library(libimhex SHARED ${LIBIMHEX_SOURCES})
target_include_directories(libimhex PUBLIC include ${MBEDTLS_INCLUDE_DIR} ${XDGPP_INCLUDE_DIRS})
target_link_directories(libimhex PUBLIC ${MBEDTLS_LIBRARY_DIR})
if (WIN32)
target_link_libraries(libimhex PUBLIC imgui nlohmann_json libmbedcrypto.a nfd)
else ()
elseif (APPLE)
find_library(FOUNDATION NAMES Foundation)
target_link_libraries(libimhex PUBLIC imgui nlohmann_json mbedcrypto ${FOUNDATION} nfd)
else()
target_link_libraries(libimhex PUBLIC imgui nlohmann_json mbedcrypto nfd)
endif ()

View File

@@ -224,10 +224,23 @@ namespace hex {
trimRight(s);
}
enum class ImHexPath {
Patterns,
PatternsInclude,
Magic,
Python,
Plugins,
Yara,
Config,
Resources
};
std::vector<std::string> getPath(ImHexPath path);
#define SCOPE_EXIT(func) ScopeExit TOKEN_CONCAT(scopeGuard, __COUNTER__)([&] { func })
class ScopeExit {
public:
ScopeExit(std::function<void()> func) : m_func(func) {}
ScopeExit(const std::function<void()> &func) : m_func(func) {}
~ScopeExit() { if (this->m_func != nullptr) this->m_func(); }
void release() {

View File

@@ -0,0 +1,9 @@
#pragma once
#if defined(OS_MACOS)
#include <hex/helpers/utils.hpp>
namespace hex {
std::string getPathForMac(ImHexPath path);
}
#endif

View File

@@ -10,15 +10,25 @@ namespace hex {
/* Settings */
void ContentRegistry::Settings::load() {
std::ifstream settingsFile(std::filesystem::path((SharedData::mainArgv)[0]).parent_path() / "settings.json");
for (const auto &dir : hex::getPath(ImHexPath::Config)) {
std::ifstream settingsFile(dir + "/settings.json");
if (settingsFile.good())
settingsFile >> getSettingsData();
if (settingsFile.good()) {
settingsFile >> getSettingsData();
break;
}
}
}
void ContentRegistry::Settings::store() {
std::ofstream settingsFile(std::filesystem::path((SharedData::mainArgv)[0]).parent_path() / "settings.json", std::ios::trunc);
settingsFile << getSettingsData();
for (const auto &dir : hex::getPath(ImHexPath::Config)) {
std::ofstream settingsFile(dir + "/settings.json", std::ios::trunc);
if (settingsFile.good()) {
settingsFile << getSettingsData();
break;
}
}
}
void ContentRegistry::Settings::add(std::string_view unlocalizedCategory, std::string_view unlocalizedName, s64 defaultValue, const std::function<bool(std::string_view, nlohmann::json&)> &callback) {

View File

@@ -3,6 +3,15 @@
#include <cstdio>
#include <codecvt>
#include <locale>
#include <filesystem>
#if defined(OS_WINDOWS)
#include <windows.h>
#elif defined(OS_MACOS)
#include <hex/helpers/utils_mac.h>
#elif defined(OS_LINUX)
#include <xdg.hpp>
#endif
namespace hex {
@@ -169,4 +178,78 @@ namespace hex {
}
std::vector<std::string> getPath(ImHexPath path) {
#if defined(OS_WINDOWS)
std::string exePath(MAX_PATH, '\0');
GetModuleFileName(nullptr, exePath.data(), exePath.length());
auto parentDir = std::filesystem::path(exePath).parent_path();
switch (path) {
case ImHexPath::Patterns:
return { (parentDir / "patterns").string() };
case ImHexPath::PatternsInclude:
return { (parentDir / "includes").string() };
case ImHexPath::Magic:
return { (parentDir / "magic").string() };
case ImHexPath::Python:
return { parentDir.string() };
case ImHexPath::Plugins:
return { (parentDir / "plugins").string() };
case ImHexPath::Yara:
return { (parentDir / "yara").string() };
case ImHexPath::Config:
return { (parentDir / "config").string() };
case ImHexPath::Resources:
return { (parentDir / "resources").string() };
default: __builtin_unreachable();
}
#elif defined(OS_MACOS)
return { getPathForMac(path) };
#else
std::vector<std::filesystem::path> configDirs = xdg::ConfigDirs();
std::vector<std::filesystem::path> dataDirs = xdg::DataDirs();
configDirs.insert(configDirs.begin(), xdg::ConfigHomeDir());
dataDirs.insert(dataDirs.begin(), xdg::DataHomeDir());
std::vector<std::string> result;
switch (path) {
case ImHexPath::Patterns:
std::transform(dataDirs.begin(), dataDirs.end(), std::back_inserter(result),
[](auto p) { return (p / "imhex" / "patterns").string(); });
return result;
case ImHexPath::PatternsInclude:
std::transform(dataDirs.begin(), dataDirs.end(), std::back_inserter(result),
[](auto p) { return (p / "imhex" / "includes").string(); });
return result;
case ImHexPath::Magic:
std::transform(dataDirs.begin(), dataDirs.end(), std::back_inserter(result),
[](auto p) { return (p / "imhex" / "magic").string(); });
return result;
case ImHexPath::Python:
std::transform(dataDirs.begin(), dataDirs.end(), std::back_inserter(result),
[](auto p) { return (p / "imhex").string(); });
return result;
case ImHexPath::Plugins:
std::transform(dataDirs.begin(), dataDirs.end(), std::back_inserter(result),
[](auto p) { return (p / "imhex" / "plugins").string(); });
return result;
case ImHexPath::Yara:
std::transform(dataDirs.begin(), dataDirs.end(), std::back_inserter(result),
[](auto p) { return (p / "imhex" / "yara").string(); });
return result;
case ImHexPath::Config:
std::transform(configDirs.begin(), configDirs.end(), std::back_inserter(result),
[](auto p) { return (p / "imhex").string(); });
return result;
case ImHexPath::Resources:
std::transform(dataDirs.begin(), dataDirs.end(), std::back_inserter(result),
[](auto p) { return (p / "imhex" / "resources").string(); });
return result;
default: __builtin_unreachable();
}
#endif
}
}

View File

@@ -0,0 +1,56 @@
#if defined(OS_MACOS)
#include <hex/helpers/utils_mac.h>
#include <Foundation/Foundation.h>
namespace hex {
std::string getPathForMac(ImHexPath path) {
@autoreleasepool {
NSError * error = nil;
NSURL * appSupportDir = [[NSFileManager defaultManager] URLForDirectory:NSApplicationSupportDirectory
inDomain:NSUserDomainMask
appropriateForURL:nil
create:YES
error:&error];
if (error != nil) {
__builtin_unreachable();
}
NSURL * result = nil;
switch (path) {
case ImHexPath::Patterns:
result = [appSupportDir URLByAppendingPathComponent:@"/imhex/patterns"];
break;
case ImHexPath::PatternsInclude:
result = [appSupportDir URLByAppendingPathComponent:@"/imhex/patterns"];
break;
case ImHexPath::Magic:
result = [appSupportDir URLByAppendingPathComponent:@"/imhex/magic"];
break;
case ImHexPath::Python:
result = [appSupportDir URLByAppendingPathComponent:@"/imhex"];
break;
case ImHexPath::Plugins:
result = [appSupportDir URLByAppendingPathComponent:@"/imhex/plugins"];
break;
case ImHexPath::Yara:
result = [appSupportDir URLByAppendingPathComponent:@"/imhex/yara"];
break;
case ImHexPath::Config:
result = [appSupportDir URLByAppendingPathComponent:@"/imhex/config"];
break;
case ImHexPath::Resources:
result = [appSupportDir URLByAppendingPathComponent:@"/imhex/resources"];
break;
}
if (result == nil) {
__builtin_unreachable();
}
return std::string([[result path] UTF8String]);
}
}
}
#endif

View File

@@ -1,5 +1,7 @@
#include <hex/lang/preprocessor.hpp>
#include <filesystem>
namespace hex::lang {
Preprocessor::Preprocessor() {
@@ -47,8 +49,15 @@ namespace hex::lang {
}
offset += 1;
if (includeFile[0] != '/')
includeFile = "include/" + includeFile;
if (includeFile[0] != '/') {
std::string tempPath = includeFile;
for (const auto &dir : hex::getPath(ImHexPath::PatternsInclude)) {
tempPath = hex::format("%s/%s", dir.c_str(), includeFile.c_str());
if (std::filesystem::exists(includeFile))
break;
}
includeFile = tempPath;
}
FILE *file = fopen(includeFile.c_str(), "r");
if (file == nullptr)