1
0
mirror of synced 2025-01-18 17:14:13 +01:00

build: Switch to GCC on MacOS (#552)

* build: Experimentally switch to gcc on macOS

* build: Corrected gcc paths

* build: Enable objective c support on macOS

* build: Enable ObjC and ObjC++ on macOS

* build: Add ObjC and ObjC++ flags

* build: Try compiling objc with clang

* build: Remove invalid flags again

* fix: Let's not include objc headers in C++ code

* sys: Move macos utils code to its own file

* fix: Missing unistd include on mac

* sys: Removed loader script stuff since it's currently unused and broken

* fix: Missing include

* fix: Another missing include

* fix: CFURLCreateWithBytes wants a pointer to mutable data

* fix: Try disabling name mangling of ObjC functions

* sys: Move macos utils declarations to its own header file

* fix: C Linkage

* fix: Move objc function prototypes to C++ headers

* fix: More missing includes

* fix: Warning error

* sys: Call ObjC with C ABI instead of trying to use C++

* build: Update libraries

* sys: Fixed build errors

* sys: No const correctness I guess

* sys: Fixed prototypes

* sys: This is C now

* sys: More nullptr -> NULL

* sys: Fix crash on exit

* sys: Try using proper std concepts instead of custom ones

* sys: Replaced another hex::is_signed

* build: Upgrade to gcc 12 and MacOS Monterey

* build: Fixed MacOS runner name

* build: Cache correct ccache folder on macOS
This commit is contained in:
WerWolv 2022-06-25 12:19:59 +02:00 committed by GitHub
parent 546d0a4922
commit 3471b314dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 201 additions and 579 deletions

View File

@ -7,7 +7,7 @@ on:
jobs:
codeql:
name: 🐛 CodeQL
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
permissions:
actions: read
contents: read
@ -41,7 +41,7 @@ jobs:
run: |
mkdir -p build
cd build
CC=gcc-11 CXX=g++-11 cmake \
CC=gcc-12 CXX=g++-12 cmake \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
-DCMAKE_INSTALL_PREFIX="$PWD/install" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \

View File

@ -106,8 +106,8 @@ jobs:
# MacOS build
macos:
runs-on: macos-11.0
name: 🍎 macOS 11.0
runs-on: macos-12
name: 🍎 macOS 12.0
steps:
- name: 🧰 Checkout
@ -122,8 +122,7 @@ jobs:
- name: 📜 Restore cache
uses: actions/cache@v3
with:
path: |
~/.ccache
path: ~/Library/Caches/ccache
key: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
restore-keys: ${{ runner.os }}-${{ secrets.CACHE_VERSION }}-build-${{ hashFiles('**/CMakeLists.txt') }}
@ -131,8 +130,10 @@ jobs:
run: |
mkdir -p build
cd build
CC=$(brew --prefix llvm)/bin/clang \
CXX=$(brew --prefix llvm)/bin/clang++ \
CC=$(brew --prefix gcc@12)/bin/gcc-12 \
CXX=$(brew --prefix gcc@12)/bin/g++-12 \
OBJC=$(brew --prefix llvm)/bin/clang \
OBJCXX=$(brew --prefix llvm)/bin/clang++ \
PKG_CONFIG_PATH="$(brew --prefix openssl)/lib/pkgconfig":"$(brew --prefix)/lib/pkgconfig" \
MACOSX_DEPLOYMENT_TARGET="10.15" \
cmake \
@ -141,6 +142,8 @@ jobs:
-DCREATE_PACKAGE=ON \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJC_COMPILER_LAUNCHER=ccache \
-DCMAKE_OBJCXX_COMPILER_LAUNCHER=ccache \
..
make -j4 package
@ -196,7 +199,7 @@ jobs:
run: |
mkdir -p build
cd build
CC=gcc-11 CXX=g++-11 cmake \
CC=gcc-12 CXX=g++-12 cmake \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
-DCMAKE_INSTALL_PREFIX="/usr" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \

View File

@ -9,7 +9,7 @@ on:
jobs:
tests:
name: 🧪 Unit Tests
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
permissions:
actions: read
contents: read
@ -38,7 +38,7 @@ jobs:
run: |
mkdir -p build
cd build
CC=gcc-11 CXX=g++-11 cmake \
CC=gcc-12 CXX=g++-12 cmake \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
-DCMAKE_INSTALL_PREFIX="$PWD/install" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \

View File

@ -77,6 +77,8 @@ macro(detectOS)
set(CMAKE_INSTALL_LIBDIR ".")
set(PLUGINS_INSTALL_LOCATION "plugins")
set(MAGIC_INSTALL_LOCATION "magic")
enable_language(OBJC)
enable_language(OBJCXX)
elseif (UNIX AND NOT APPLE)
add_compile_definitions(OS_LINUX)
set(CMAKE_INSTALL_BINDIR "bin")

3
dist/Brewfile vendored
View File

@ -7,6 +7,5 @@ brew "python3"
brew "freetype2"
brew "libmagic"
brew "pkg-config"
# TODO: Remove this when XCode version of clang will support the same level as LLVM 10
brew "llvm"
brew "gcc@12"

View File

@ -1,9 +1,5 @@
#!/usr/bin/env sh
echo "As of 2020-12, Debian stable does not include g++-10, needs debian testing or unstable."
# Tested on 2020-12-09 with Docker image bitnami/minideb:unstable
# Install pkgconf (adds minimum dependencies) only if the equivalent pkf-config is not already installed.
if ! which pkg-config
then
@ -12,8 +8,8 @@ fi
apt install -y \
build-essential \
gcc-11 \
g++-11 \
gcc-12 \
g++-12 \
lld \
${PKGCONF:-} \
cmake \
@ -25,7 +21,4 @@ apt install -y \
libmbedtls-dev \
python3-dev \
libfreetype-dev \
libgtk-3-dev \
echo "Please consider this before running cmake (useful on e.g. Ubuntu 20.04):"
echo "export CXX=g++-11"
libgtk-3-dev

@ -1 +1 @@
Subproject commit f14e88a72759f7121cb611abb7afa6d6a126c7cf
Subproject commit 12063078f081694442a274d0e925b2ab204752c4

@ -1 +1 @@
Subproject commit d399836b693feaab3b323acd4374c1371164c0eb
Subproject commit 3717689c374cd5e8645de258c09c15ebf7a8a91a

View File

@ -123,7 +123,6 @@ set(LIBIMHEX_SOURCES
source/helpers/patches.cpp
source/helpers/project_file_handler.cpp
source/helpers/encoding_file.cpp
source/helpers/loader_script_handler.cpp
source/helpers/logger.cpp
source/helpers/tar.cpp
@ -143,7 +142,9 @@ if (APPLE)
endif ()
endif ()
set(LIBIMHEX_SOURCES ${LIBIMHEX_SOURCES} source/helpers/fs_macos.mm)
set(LIBIMHEX_SOURCES ${LIBIMHEX_SOURCES}
source/helpers/fs_macos.m
source/helpers/utils_macos.m)
endif ()
add_compile_definitions(IMHEX_PROJECT_NAME="${PROJECT_NAME}")

View File

@ -156,7 +156,7 @@ namespace hex {
}
template<hex::derived_from<View> T, typename... Args>
template<std::derived_from<View> T, typename... Args>
void add(Args &&...args) {
return impl::add(new T(std::forward<Args>(args)...));
}
@ -234,7 +234,7 @@ namespace hex {
}
template<hex::derived_from<dp::Node> T, typename... Args>
template<std::derived_from<dp::Node> T, typename... Args>
void add(const std::string &unlocalizedCategory, const std::string &unlocalizedName, Args &&...args) {
add(impl::Entry { unlocalizedCategory.c_str(), unlocalizedName.c_str(), [=] {
auto node = new T(std::forward<Args>(args)...);
@ -326,7 +326,7 @@ namespace hex {
}
template<hex::derived_from<hex::prv::Provider> T>
template<std::derived_from<hex::prv::Provider> T>
void add(const std::string &unlocalizedName, bool addToList = true) {
(void)EventManager::subscribe<RequestCreateProvider>([expectedName = unlocalizedName](const std::string &name, hex::prv::Provider **provider) {
if (name != expectedName) return;
@ -415,7 +415,7 @@ namespace hex {
}
template<hex::derived_from<DataVisualizer> T, typename... Args>
template<std::derived_from<DataVisualizer> T, typename... Args>
void addDataVisualizer(const std::string &unlocalizedName, Args &&...args) {
return impl::addDataVisualizer(unlocalizedName, new T(std::forward<Args>(args)...));
}

View File

@ -127,7 +127,7 @@ namespace hex {
void add(prv::Provider *provider);
template<hex::derived_from<prv::Provider> T>
template<std::derived_from<prv::Provider> T>
void add(auto &&...args) {
add(new T(std::forward<decltype(args)>(args)...));
}

View File

@ -5,151 +5,7 @@
#include <type_traits>
#include <memory>
namespace hex {
template<typename>
struct is_integral_helper : public std::false_type { };
template<>
struct is_integral_helper<u8> : public std::true_type { };
template<>
struct is_integral_helper<i8> : public std::true_type { };
template<>
struct is_integral_helper<u16> : public std::true_type { };
template<>
struct is_integral_helper<i16> : public std::true_type { };
template<>
struct is_integral_helper<u32> : public std::true_type { };
template<>
struct is_integral_helper<i32> : public std::true_type { };
template<>
struct is_integral_helper<u64> : public std::true_type { };
template<>
struct is_integral_helper<i64> : public std::true_type { };
template<>
struct is_integral_helper<u128> : public std::true_type { };
template<>
struct is_integral_helper<i128> : public std::true_type { };
template<>
struct is_integral_helper<bool> : public std::true_type { };
template<>
struct is_integral_helper<char> : public std::true_type { };
template<>
struct is_integral_helper<char8_t> : public std::true_type { };
template<>
struct is_integral_helper<char16_t> : public std::true_type { };
template<>
struct is_integral_helper<char32_t> : public std::true_type { };
template<>
struct is_integral_helper<wchar_t> : public std::true_type { };
template<typename T>
struct is_integral : public is_integral_helper<std::remove_cvref_t<T>>::type { };
template<typename>
struct is_signed_helper : public std::false_type { };
template<>
struct is_signed_helper<i8> : public std::true_type { };
template<>
struct is_signed_helper<i16> : public std::true_type { };
template<>
struct is_signed_helper<i32> : public std::true_type { };
template<>
struct is_signed_helper<i64> : public std::true_type { };
template<>
struct is_signed_helper<i128> : public std::true_type { };
template<>
struct is_signed_helper<char> : public std::true_type { };
template<>
struct is_signed_helper<float> : public std::true_type { };
template<>
struct is_signed_helper<double> : public std::true_type { };
template<>
struct is_signed_helper<long double> : public std::true_type { };
template<typename T>
struct is_signed : public is_signed_helper<std::remove_cvref_t<T>>::type { };
template<typename>
struct is_floating_point_helper : public std::false_type { };
template<>
struct is_floating_point_helper<float> : public std::true_type { };
template<>
struct is_floating_point_helper<double> : public std::true_type { };
template<>
struct is_floating_point_helper<long double> : public std::true_type { };
template<typename T>
struct is_floating_point : public is_floating_point_helper<std::remove_cvref_t<T>>::type { };
}
#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION <= 12000
#if __has_include(<concepts>)
// Make sure we break when derived_from is implemented in libc++. Then we can fix a compatibility version above
#include <concepts>
#endif
// libcxx 12 still doesn't have many default concepts implemented, as a result we need to define it ourself using clang built-ins.
// [concept.derived] (patch from https://reviews.llvm.org/D74292)
namespace hex {
template<class _Dp, class _Bp>
concept derived_from =
__is_base_of(_Bp, _Dp) && __is_convertible_to(const volatile _Dp *, const volatile _Bp *);
}
#else
// Assume supported
#include <concepts>
namespace hex {
using std::derived_from;
}
#endif
// [concepts.arithmetic]
namespace hex {
template<class T>
concept integral = hex::is_integral<T>::value;
template<class T>
concept signed_integral = integral<T> && hex::is_signed<T>::value;
template<class T>
concept unsigned_integral = integral<T> && !signed_integral<T>;
template<class T>
concept floating_point = std::is_floating_point<T>::value;
}
#include <concepts>
namespace hex {
@ -159,11 +15,6 @@ namespace hex {
template<typename T, size_t Size>
concept has_size = sizeof(T) == Size;
}
namespace hex {
template<typename T>
class Cloneable {
public:

View File

@ -1,10 +0,0 @@
#pragma once
#if defined(OS_MACOS)
#include <hex/helpers/fs.hpp>
namespace hex {
std::string getMacExecutableDirectoryPath();
std::string getMacApplicationSupportDirectoryPath();
}
#endif

View File

@ -0,0 +1,12 @@
#pragma once
#if defined(OS_MACOS)
#include <hex/helpers/fs.hpp>
extern "C" char * getMacExecutableDirectoryPath();
extern "C" char * getMacApplicationSupportDirectoryPath();
extern "C" void macFree(void *ptr);
#endif

View File

@ -1,38 +0,0 @@
#pragma once
#include <string>
#include <string_view>
#include <hex/helpers/fs.hpp>
struct _object;
typedef struct _object PyObject;
namespace hex {
namespace prv {
class Provider;
}
class LoaderScript {
public:
LoaderScript() = delete;
static bool processFile(const std::fs::path &scriptPath);
static void setFilePath(const std::fs::path &filePath) { LoaderScript::s_filePath = filePath; }
static void setDataProvider(prv::Provider *provider) { LoaderScript::s_dataProvider = provider; }
private:
static inline std::fs::path s_filePath;
static inline prv::Provider *s_dataProvider;
static PyObject *Py_getFilePath(PyObject *self, PyObject *args);
static PyObject *Py_addPatch(PyObject *self, PyObject *args);
static PyObject *Py_addBookmark(PyObject *self, PyObject *args);
static PyObject *Py_addStruct(PyObject *self, PyObject *args);
static PyObject *Py_addUnion(PyObject *self, PyObject *args);
};
}

View File

@ -43,7 +43,7 @@ namespace hex {
std::string encodeByteString(const std::vector<u8> &bytes);
std::vector<u8> decodeByteString(const std::string &string);
[[nodiscard]] constexpr inline u64 extract(u8 from, u8 to, const hex::unsigned_integral auto &value) {
[[nodiscard]] constexpr inline u64 extract(u8 from, u8 to, const std::unsigned_integral auto &value) {
if (from < to) std::swap(from, to);
using ValueType = std::remove_cvref_t<decltype(value)>;
@ -72,7 +72,7 @@ namespace hex {
return (value ^ mask) - mask;
}
template<hex::integral T>
template<std::integral T>
constexpr inline T swapBitOrder(size_t numBits, T value) {
T result = 0x00;
@ -200,7 +200,7 @@ namespace hex {
return T(1) << bit_width(T(x - 1));
}
template<hex::integral T, hex::integral U>
template<std::integral T, std::integral U>
auto powi(T base, U exp) {
using ResultType = decltype(T{} * U{});
@ -264,7 +264,7 @@ namespace hex {
return result;
}
inline std::string toBinaryString(hex::unsigned_integral auto number) {
inline std::string toBinaryString(std::unsigned_integral auto number) {
if (number == 0) return "0";
std::string result;
@ -317,7 +317,7 @@ namespace hex {
return *value;
}
template<hex::integral T>
template<std::integral T>
T alignTo(T value, T alignment) {
T remainder = value % alignment;

View File

@ -0,0 +1,9 @@
#pragma once
#if defined(OS_MACOS)
#include <string>
extern "C" void openWebpageMacos(const char *url);
#endif

View File

@ -2,6 +2,7 @@
#include <hex/providers/provider.hpp>
#include <hex/helpers/utils.hpp>
#include <hex/helpers/concepts.hpp>
#include <mbedtls/version.h>
#include <mbedtls/base64.h>
@ -15,7 +16,6 @@
#include <array>
#include <span>
#include <concepts>
#include <functional>
#include <algorithm>
#include <cstddef>

View File

@ -1,7 +1,7 @@
#include <hex/helpers/fs.hpp>
#include <hex/api/content_registry.hpp>
#include <hex/helpers/fs_macos.h>
#include <hex/helpers/fs_macos.hpp>
#include <hex/helpers/file.hpp>
#include <hex/helpers/intrinsics.hpp>
@ -34,7 +34,15 @@ namespace hex::fs {
return exePath;
#elif defined(OS_MACOS)
return getMacExecutableDirectoryPath();
std::string result;
{
auto string = getMacExecutableDirectoryPath();
result = string;
macFree(string);
}
return result;
#else
return std::nullopt;
#endif
@ -183,25 +191,31 @@ namespace hex::fs {
}
#elif defined(OS_MACOS)
// Get path to special directories
const std::fs::path applicationSupportDir(getMacApplicationSupportDirectoryPath());
std::string applicationSupportDir;
{
auto string = getMacApplicationSupportDirectoryPath();
applicationSupportDir = string;
macFree(string);
}
const std::fs::path applicationSupportDirPath(applicationSupportDir);
std::vector<std::fs::path> paths = { applicationSupportDir };
std::vector<std::fs::path> paths = { applicationSupportDirPath };
if (exePath.has_value())
paths.push_back(exePath.value());
switch (path) {
case ImHexPath::Patterns:
result.push_back((applicationSupportDir / "patterns").string());
result.push_back((applicationSupportDirPath / "patterns").string());
break;
case ImHexPath::PatternsInclude:
result.push_back((applicationSupportDir / "includes").string());
result.push_back((applicationSupportDirPath / "includes").string());
break;
case ImHexPath::Magic:
result.push_back((applicationSupportDir / "magic").string());
result.push_back((applicationSupportDirPath / "magic").string());
break;
case ImHexPath::Python:
result.push_back((applicationSupportDir / "python").string());
result.push_back((applicationSupportDirPath / "python").string());
break;
case ImHexPath::Plugins:
std::transform(paths.begin(), paths.end(), std::back_inserter(result), [](auto &path) {
@ -209,22 +223,22 @@ namespace hex::fs {
});
break;
case ImHexPath::Yara:
result.push_back((applicationSupportDir / "yara").string());
result.push_back((applicationSupportDirPath / "yara").string());
break;
case ImHexPath::Config:
result.push_back((applicationSupportDir / "config").string());
result.push_back((applicationSupportDirPath / "config").string());
break;
case ImHexPath::Resources:
result.push_back((applicationSupportDir / "resources").string());
result.push_back((applicationSupportDirPath / "resources").string());
break;
case ImHexPath::Constants:
result.push_back((applicationSupportDir / "constants").string());
result.push_back((applicationSupportDirPath / "constants").string());
break;
case ImHexPath::Encodings:
result.push_back((applicationSupportDir / "encodings").string());
result.push_back((applicationSupportDirPath / "encodings").string());
break;
case ImHexPath::Logs:
result.push_back((applicationSupportDir / "logs").string());
result.push_back((applicationSupportDirPath / "logs").string());
break;
default:
hex::unreachable();

View File

@ -0,0 +1,44 @@
#if defined(OS_MACOS)
#include <string.h>
#include <stdlib.h>
#include <Foundation/Foundation.h>
char* getMacExecutableDirectoryPath() {
@autoreleasepool {
const char *pathString = [[[[[NSBundle mainBundle] executableURL] URLByDeletingLastPathComponent] path] UTF8String];
char *result = malloc(strlen(pathString) + 1);
strcpy(result, pathString);
return result;
}
}
char* getMacApplicationSupportDirectoryPath() {
@autoreleasepool {
NSError* error = nil;
NSURL* dirUrl = [[NSFileManager defaultManager] URLForDirectory:NSApplicationSupportDirectory
inDomain:NSUserDomainMask
appropriateForURL:nil
create:YES
error:&error];
if (error != nil) {
return NULL;
}
const char *pathString = [[[dirUrl URLByAppendingPathComponent:(@"imhex")] path] UTF8String];
char *result = malloc(strlen(pathString) + 1);
strcpy(result, pathString);
return result;
}
}
void macFree(void *ptr) {
free(ptr);
}
#endif

View File

@ -1,30 +0,0 @@
#if defined(OS_MACOS)
#include <hex/helpers/fs_macos.h>
#include <Foundation/Foundation.h>
namespace hex {
std::string getMacExecutableDirectoryPath() {
@autoreleasepool {
return {[[[[[NSBundle mainBundle] executableURL] URLByDeletingLastPathComponent] path] UTF8String]};
}
}
std::string getMacApplicationSupportDirectoryPath() {
@autoreleasepool {
NSError* error = nil;
NSURL* dirUrl = [[NSFileManager defaultManager] URLForDirectory:NSApplicationSupportDirectory
inDomain:NSUserDomainMask
appropriateForURL:nil
create:YES
error:&error];
if (error != nil) {
__builtin_unreachable();
}
return {[[[dirUrl URLByAppendingPathComponent:(@"imhex")] path] UTF8String]};
}
}
}
#endif

View File

@ -1,248 +0,0 @@
#include <hex/helpers/loader_script_handler.hpp>
#include <hex/helpers/utils.hpp>
#include <hex/helpers/fs.hpp>
#include <hex/helpers/file.hpp>
#include <hex/ui/view.hpp>
#include <hex/providers/provider.hpp>
#include <hex/helpers/intrinsics.hpp>
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <structmember.h>
#include <cstring>
#include <filesystem>
using namespace std::literals::string_literals;
namespace hex {
PyObject *LoaderScript::Py_getFilePath(PyObject *self, PyObject *args) {
hex::unused(self, args);
return PyUnicode_FromString(LoaderScript::s_filePath.string().c_str());
}
PyObject *LoaderScript::Py_addPatch(PyObject *self, PyObject *args) {
hex::unused(self);
u64 address;
u8 *patches;
Py_ssize_t count;
if (!PyArg_ParseTuple(args, "K|y#", &address, &patches, &count)) {
PyErr_BadArgument();
return nullptr;
}
if (patches == nullptr || count == 0) {
PyErr_SetString(PyExc_TypeError, "Invalid patch provided");
return nullptr;
}
if (address >= LoaderScript::s_dataProvider->getActualSize()) {
PyErr_SetString(PyExc_IndexError, "address out of range");
return nullptr;
}
LoaderScript::s_dataProvider->write(address, patches, count);
Py_RETURN_NONE;
}
PyObject *LoaderScript::Py_addBookmark(PyObject *self, PyObject *args) {
hex::unused(self);
u64 address;
size_t size;
char *name = nullptr;
char *comment = nullptr;
if (!PyArg_ParseTuple(args, "K|n|s|s", &address, &size, &name, &comment)) {
PyErr_BadArgument();
return nullptr;
}
if (name == nullptr || comment == nullptr) {
PyErr_SetString(PyExc_IndexError, "address out of range");
return nullptr;
}
ImHexApi::Bookmarks::add(address, size, name, comment);
Py_RETURN_NONE;
}
static PyObject *createStructureType(const std::string &keyword, PyObject *args) {
if (args == nullptr) {
PyErr_BadArgument();
return nullptr;
}
auto type = PyTuple_GetItem(args, 0);
if (type == nullptr) {
PyErr_BadArgument();
return nullptr;
}
auto instance = PyObject_CallObject(type, nullptr);
if (instance == nullptr) {
PyErr_BadArgument();
return nullptr;
}
ON_SCOPE_EXIT { Py_DECREF(instance); };
if (instance->ob_type->tp_base == nullptr || instance->ob_type->tp_base->tp_name != "ImHexType"s) {
PyErr_SetString(PyExc_TypeError, "class type must extend from ImHexType");
return nullptr;
}
auto dict = instance->ob_type->tp_dict;
if (dict == nullptr) {
PyErr_BadArgument();
return nullptr;
}
auto annotations = PyDict_GetItemString(dict, "__annotations__");
if (annotations == nullptr) {
PyErr_BadArgument();
return nullptr;
}
auto list = PyDict_Items(annotations);
if (list == nullptr) {
PyErr_BadArgument();
return nullptr;
}
ON_SCOPE_EXIT { Py_DECREF(list); };
std::string code = keyword + " " + instance->ob_type->tp_name + " {\n";
for (Py_ssize_t i = 0; i < PyList_Size(list); i++) {
auto item = PyList_GetItem(list, i);
if (item == nullptr) {
PyErr_SetString(PyExc_TypeError, "failed to get item from list");
return nullptr;
}
auto memberName = PyUnicode_AsUTF8(PyTuple_GetItem(item, 0));
if (memberName == nullptr) {
PyErr_SetString(PyExc_TypeError, "invalid member name");
return nullptr;
}
auto memberType = PyTuple_GetItem(item, 1);
if (!PyTuple_Check(memberType) || memberType == nullptr) {
PyErr_SetString(PyExc_TypeError, "member needs to have a annotation extending from ImHexType");
return nullptr;
}
// Array already is an object
if (memberType->ob_type->tp_name == "array"s) {
auto arrayType = PyObject_GetAttrString(memberType, "array_type");
if (arrayType == nullptr) {
PyErr_BadArgument();
return nullptr;
}
code += " "s + arrayType->ob_type->tp_name + " " + memberName;
auto arraySize = PyObject_GetAttrString(memberType, "size");
if (arraySize == nullptr) {
PyErr_BadArgument();
return nullptr;
}
if (PyUnicode_Check(arraySize))
code += "["s + PyUnicode_AsUTF8(arraySize) + "];\n";
else if (PyLong_Check(arraySize))
code += "["s + std::to_string(PyLong_AsLong(arraySize)) + "];\n";
} else {
auto memberTypeInstance = PyObject_CallObject(memberType, nullptr);
if (memberTypeInstance == nullptr || memberTypeInstance->ob_type->tp_base == nullptr || memberTypeInstance->ob_type->tp_base->tp_name != "ImHexType"s) {
PyErr_SetString(PyExc_TypeError, "member needs to have a annotation extending from ImHexType");
if (memberTypeInstance != nullptr)
Py_DECREF(memberTypeInstance);
return nullptr;
}
code += " "s + memberTypeInstance->ob_type->tp_name + " "s + memberName + ";\n";
Py_DECREF(memberTypeInstance);
}
}
code += "};\n";
EventManager::post<RequestSetPatternLanguageCode>(code);
Py_RETURN_NONE;
}
PyObject *LoaderScript::Py_addStruct(PyObject *self, PyObject *args) {
hex::unused(self);
return createStructureType("struct", args);
}
PyObject *LoaderScript::Py_addUnion(PyObject *self, PyObject *args) {
hex::unused(self);
return createStructureType("union", args);
}
bool LoaderScript::processFile(const std::fs::path &scriptPath) {
Py_SetProgramName(Py_DecodeLocale("ImHex", nullptr));
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Python)) {
if (fs::exists(std::fs::path(dir / "lib" / "python" PYTHON_VERSION_MAJOR_MINOR))) {
Py_SetPythonHome(Py_DecodeLocale(dir.string().c_str(), nullptr));
break;
}
}
PyImport_AppendInittab("_imhex", []() -> PyObject * {
static PyMethodDef ImHexMethods[] = {
{"get_file_path", &LoaderScript::Py_getFilePath, METH_NOARGS, "Returns the path of the file being loaded."},
{ "patch", &LoaderScript::Py_addPatch, METH_VARARGS, "Patches a region of memory" },
{ "add_bookmark", &LoaderScript::Py_addBookmark, METH_VARARGS, "Adds a bookmark" },
{ "add_struct", &LoaderScript::Py_addStruct, METH_VARARGS, "Adds a struct" },
{ "add_union", &LoaderScript::Py_addUnion, METH_VARARGS, "Adds a union" },
{ nullptr, nullptr, 0, nullptr }
};
static PyModuleDef ImHexModule = {
PyModuleDef_HEAD_INIT, "imhex", nullptr, -1, ImHexMethods, nullptr, nullptr, nullptr, nullptr
};
auto module = PyModule_Create(&ImHexModule);
if (module == nullptr)
return nullptr;
return module;
});
Py_Initialize();
{
auto sysPath = PySys_GetObject("path");
auto path = PyUnicode_FromString("lib");
PyList_Insert(sysPath, 0, path);
}
fs::File scriptFile(scriptPath, fs::File::Mode::Read);
PyRun_SimpleFile(scriptFile.getHandle(), scriptFile.getPath().string().c_str());
Py_Finalize();
return true;
}
}

View File

@ -2,8 +2,6 @@
#include <cstdio>
#include <codecvt>
#include <locale>
#include <filesystem>
#include <hex/api/imhex_api.hpp>
@ -18,13 +16,10 @@
#elif defined(OS_LINUX)
#include <unistd.h>
#elif defined(OS_MACOS)
#include <CoreFoundation/CFBundle.h>
#include <ApplicationServices/ApplicationServices.h>
#include <hex/helpers/utils_macos.hpp>
#include <unistd.h>
#endif
#include <hex/helpers/logger.hpp>
#include <hex/helpers/file.hpp>
namespace hex {
long double operator""_scaled(long double value) {
@ -252,13 +247,14 @@ namespace hex {
void runCommand(const std::string &command) {
#if defined(OS_WINDOWS)
#if defined(OS_WINDOWS)
auto result = system(hex::format("start {0}", command).c_str());
#elif defined(OS_MACOS)
#elif defined(OS_MACOS)
auto result = system(hex::format("open {0}", command).c_str());
#elif defined(OS_LINUX)
#elif defined(OS_LINUX)
auto result = system(hex::format("xdg-open {0}", command).c_str());
#endif
#endif
hex::unused(result);
}
@ -267,18 +263,16 @@ namespace hex {
if (url.find("://") == std::string::npos)
url = "https://" + url;
#if defined(OS_WINDOWS)
#if defined(OS_WINDOWS)
ShellExecute(nullptr, "open", url.c_str(), nullptr, nullptr, SW_SHOWNORMAL);
#elif defined(OS_MACOS)
CFURLRef urlRef = CFURLCreateWithBytes(nullptr, reinterpret_cast<u8 *>(url.data()), url.length(), kCFStringEncodingASCII, nullptr);
LSOpenCFURLRef(urlRef, nullptr);
CFRelease(urlRef);
#elif defined(OS_LINUX)
#elif defined(OS_MACOS)
openWebpageMacos(url.c_str());
#elif defined(OS_LINUX)
auto result = system(hex::format("xdg-open {0}", url).c_str());
hex::unused(result);
#else
#else
#warning "Unknown OS, can't open webpages"
#endif
#endif
}
std::string encodeByteString(const std::vector<u8> &bytes) {

View File

@ -0,0 +1,16 @@
#if defined(OS_MACOS)
#include <CoreFoundation/CFBundle.h>
#include <ApplicationServices/ApplicationServices.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
void openWebpageMacos(const char *url) {
CFURLRef urlRef = CFURLCreateWithBytes(NULL, (uint8_t*)(url), strlen(url), kCFStringEncodingASCII, NULL);
LSOpenCFURLRef(urlRef, NULL);
CFRelease(urlRef);
}
#endif

View File

@ -177,16 +177,23 @@ namespace hex::init {
ImHexApi::HexEditor::impl::getBackgroundHighlightingFunctions().clear();
ImHexApi::HexEditor::impl::getForegroundHighlightingFunctions().clear();
ImHexApi::HexEditor::impl::getTooltips().clear();
ImHexApi::HexEditor::impl::getTooltipFunctions().clear();
ContentRegistry::Settings::getEntries().clear();
ContentRegistry::Settings::getSettingsData().clear();
ContentRegistry::CommandPaletteCommands::getEntries().clear();
ContentRegistry::PatternLanguage::getFunctions().clear();
for (auto &[name, view] : ContentRegistry::Views::getEntries())
ContentRegistry::PatternLanguage::getFunctions().clear();
ContentRegistry::PatternLanguage::getPragmas().clear();
{
auto &views = ContentRegistry::Views::getEntries();
for (auto &[name, view] : views)
delete view;
ContentRegistry::Views::getEntries().clear();
views.clear();
}
ContentRegistry::Tools::getEntries().clear();
ContentRegistry::DataInspector::getEntries().clear();
@ -213,6 +220,13 @@ namespace hex::init {
ContentRegistry::DataFormatter::getEntries().clear();
ContentRegistry::FileHandler::getEntries().clear();
{
auto &visualizers = ContentRegistry::HexEditor::impl::getVisualizers();
for (auto &[name, visualizer] : visualizers)
delete visualizer;
visualizers.clear();
}
while (ImHexApi::Provider::isValid())
ImHexApi::Provider::remove(ImHexApi::Provider::get());
ContentRegistry::Provider::getEntries().clear();

View File

@ -22,7 +22,7 @@ namespace hex::plugin::builtin {
else static_assert(hex::always_false<T>::value, "Invalid data type!");
}
template<hex::integral T>
template<std::integral T>
class DataVisualizerHexadecimal : public hex::ContentRegistry::HexEditor::DataVisualizer {
public:
DataVisualizerHexadecimal() : DataVisualizer(ByteCount, CharCount) { }
@ -114,7 +114,7 @@ namespace hex::plugin::builtin {
}
};
template<hex::integral T>
template<std::integral T>
class DataVisualizerDecimal : public hex::ContentRegistry::HexEditor::DataVisualizer {
public:
DataVisualizerDecimal() : DataVisualizer(ByteCount, CharCount) { }
@ -123,7 +123,7 @@ namespace hex::plugin::builtin {
hex::unused(address, upperCase);
if (size == ByteCount) {
if (hex::is_signed<T>::value)
if (std::is_signed<T>::value)
ImGui::Text(getFormatString(), static_cast<i64>(*reinterpret_cast<const T*>(data)));
else
ImGui::Text(getFormatString(), static_cast<u64>(*reinterpret_cast<const T*>(data)));
@ -153,14 +153,14 @@ namespace hex::plugin::builtin {
constexpr static inline auto ByteCount = sizeof(T);
constexpr static inline auto CharCount = std::numeric_limits<T>::digits10 + 2;
const static inline auto FormatString = hex::format("%{}{}", CharCount, hex::is_signed<T>::value ? "lld" : "llu");
const static inline auto FormatString = hex::format("%{}{}", CharCount, std::is_signed<T>::value ? "lld" : "llu");
const char *getFormatString() {
return FormatString.c_str();
}
};
template<hex::floating_point T>
template<std::floating_point T>
class DataVisualizerFloatingPoint : public hex::ContentRegistry::HexEditor::DataVisualizer {
public:
DataVisualizerFloatingPoint() : DataVisualizer(ByteCount, CharCount) { }

View File

@ -199,11 +199,7 @@ namespace hex::plugin::builtin {
reader.seek(this->m_searchPosition.value_or(editor->getSelection().getEndAddress()));
constexpr static auto searchFunction = [](const auto &haystackBegin, const auto &haystackEnd, const auto &needleBegin, const auto &needleEnd) {
#if defined(OS_MACOS)
return std::search(haystackBegin, haystackEnd, needleBegin, needleEnd);
#else
return std::search(haystackBegin, haystackEnd, std::boyer_moore_horspool_searcher(needleBegin, needleEnd));
#endif
};
if (!backwards) {

View File

@ -117,11 +117,11 @@ namespace hex {
for (char *pos = prevPos; *pos != 0x00;) {
if (std::isdigit(*pos) || *pos == '.') {
auto number = [&] {
if constexpr (hex::floating_point<T>)
if constexpr (std::floating_point<T>)
return std::strtold(pos, &pos);
else if constexpr (hex::signed_integral<T>)
else if constexpr (std::signed_integral<T>)
return std::strtoll(pos, &pos, 10);
else if constexpr (hex::unsigned_integral<T>)
else if constexpr (std::unsigned_integral<T>)
return std::strtoull(pos, &pos, 10);
else
static_assert(hex::always_false<T>::value, "Can't parse literal of this type");
@ -440,7 +440,7 @@ namespace hex {
template<typename T>
void MathEvaluator<T>::registerStandardFunctions() {
if constexpr (hex::floating_point<T>) {
if constexpr (std::floating_point<T>) {
this->setFunction(
"sin", [](auto args) { return std::sin(args[0]); }, 1, 1);
this->setFunction(