mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-28 00:35:47 +00:00
Merge pull request #11158 from boykopovar/refactor/no-3rdparty-in-public-headers
refactor(libs): remove 3rdparty from public headers
This commit is contained in:
4 files changed
+115
-66
No files matched your search
@@ -3,16 +3,21 @@
|
||||
|
||||
#include "prx/libc/include/general/VabiMacros.hpp"
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_LIST_H
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace FreeType {
|
||||
|
||||
using GuestListRec = FT_ListRec;
|
||||
using GuestListNodeRec = FT_ListNodeRec;
|
||||
struct GuestListNodeRec {
|
||||
GuestListNodeRec* prev;
|
||||
GuestListNodeRec* next;
|
||||
void* data;
|
||||
};
|
||||
|
||||
struct GuestListRec {
|
||||
GuestListNodeRec* head;
|
||||
GuestListNodeRec* tail;
|
||||
};
|
||||
|
||||
struct GuestMemoryRec {
|
||||
void* user;
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#include <array>
|
||||
#include <stdexcept>
|
||||
#include <ft2build.h>
|
||||
#include FT_LIST_H
|
||||
|
||||
using namespace FreeType;
|
||||
|
||||
@@ -26,77 +28,89 @@ private:
|
||||
std::array<GuestArena::HostWrite, 5> writes;
|
||||
};
|
||||
|
||||
struct Iteration {
|
||||
GuestListIterator iterator;
|
||||
void* user;
|
||||
};
|
||||
|
||||
int Iterate(FT_ListNode node, void* user) {
|
||||
auto& call = *static_cast<Iteration*>(user);
|
||||
return call.iterator(node, call.user);
|
||||
}
|
||||
|
||||
struct Finalization {
|
||||
GuestMemoryRec* memory;
|
||||
GuestListDestructor destroy;
|
||||
void* user;
|
||||
};
|
||||
|
||||
void Destroy(FT_Memory memory, void* data, void*) {
|
||||
auto& call = *static_cast<Finalization*>(memory->user);
|
||||
call.destroy(call.memory, data, call.user);
|
||||
}
|
||||
|
||||
void FreeNode(FT_Memory memory, void* block) {
|
||||
auto& call = *static_cast<Finalization*>(memory->user);
|
||||
call.memory->free(call.memory, block);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
GuestListNodeRec* APS5_VABI FT_List_Find_nid_postfix(GuestListRec* list, void* data) {
|
||||
return FT_List_Find(list, data);
|
||||
if (!list) return nullptr;
|
||||
for (auto* node = list->head; node; node = node->next) {
|
||||
if (node->data == data) return node;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void APS5_VABI FT_List_Add_nid_postfix(GuestListRec* list, GuestListNodeRec* node) {
|
||||
if (!list || !node) return;
|
||||
const ListWrite write(list, {node, list->tail});
|
||||
FT_List_Add(list, node);
|
||||
auto* tail = list->tail;
|
||||
node->next = nullptr;
|
||||
node->prev = tail;
|
||||
if (tail) tail->next = node;
|
||||
else list->head = node;
|
||||
list->tail = node;
|
||||
}
|
||||
|
||||
void APS5_VABI FT_List_Insert_nid_postfix(GuestListRec* list, GuestListNodeRec* node) {
|
||||
if (!list || !node) return;
|
||||
const ListWrite write(list, {node, list->head});
|
||||
FT_List_Insert(list, node);
|
||||
auto* head = list->head;
|
||||
node->next = head;
|
||||
node->prev = nullptr;
|
||||
if (head) head->prev = node;
|
||||
else list->tail = node;
|
||||
list->head = node;
|
||||
}
|
||||
|
||||
void APS5_VABI FT_List_Remove_nid_postfix(GuestListRec* list, GuestListNodeRec* node) {
|
||||
if (!list || !node) return;
|
||||
const ListWrite write(list, {node->prev, node->next});
|
||||
FT_List_Remove(list, node);
|
||||
auto* previous = node->prev;
|
||||
auto* next = node->next;
|
||||
if (previous) previous->next = next;
|
||||
else list->head = next;
|
||||
if (next) next->prev = previous;
|
||||
else list->tail = previous;
|
||||
}
|
||||
|
||||
void APS5_VABI FT_List_Up_nid_postfix(GuestListRec* list, GuestListNodeRec* node) {
|
||||
if (!list || !node || !node->prev) return;
|
||||
const ListWrite write(list, {node, node->prev, node->next, list->head});
|
||||
FT_List_Up(list, node);
|
||||
auto* previous = node->prev;
|
||||
auto* next = node->next;
|
||||
previous->next = next;
|
||||
if (next) next->prev = previous;
|
||||
else list->tail = previous;
|
||||
node->prev = nullptr;
|
||||
node->next = list->head;
|
||||
list->head->prev = node;
|
||||
list->head = node;
|
||||
}
|
||||
|
||||
int APS5_VABI FT_List_Iterate_nid_postfix(GuestListRec* list, GuestListIterator iterator, void* user) {
|
||||
Iteration call{iterator, user};
|
||||
return FT_List_Iterate(list, iterator ? Iterate : nullptr, &call);
|
||||
if (!list || !iterator) return FT_Err_Invalid_Argument;
|
||||
auto* node = list->head;
|
||||
while (node) {
|
||||
auto* next = node->next;
|
||||
const int error = iterator(node, user);
|
||||
if (error) return error;
|
||||
node = next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void APS5_VABI FT_List_Finalize_nid_postfix(GuestListRec* list, GuestListDestructor destroy, GuestMemoryRec* memory, void* user) {
|
||||
if (!list || !memory) return;
|
||||
const ListWrite write(list);
|
||||
Finalization call{memory, destroy, user};
|
||||
FT_MemoryRec_ native{};
|
||||
native.user = &call;
|
||||
native.free = FreeNode;
|
||||
FT_List_Finalize(list, destroy ? Destroy : nullptr, &native, user);
|
||||
auto* node = list->head;
|
||||
while (node) {
|
||||
auto* next = node->next;
|
||||
if (destroy) destroy(memory, node->data, user);
|
||||
memory->free(memory, node);
|
||||
node = next;
|
||||
}
|
||||
list->head = nullptr;
|
||||
list->tail = nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,6 +7,9 @@
|
||||
#include <map>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
#include <type_traits>
|
||||
#include <ft2build.h>
|
||||
#include FT_LIST_H
|
||||
|
||||
using namespace FreeType;
|
||||
|
||||
@@ -20,9 +23,11 @@ static void Check(bool value, int line) {
|
||||
#define Require(value) Check((value), __LINE__)
|
||||
|
||||
constexpr std::size_t Count = 16;
|
||||
using Nodes = std::array<FT_ListNodeRec, Count>;
|
||||
template<typename TNode>
|
||||
using Nodes = std::array<TNode, Count>;
|
||||
|
||||
static int Index(FT_ListNode node, const Nodes& nodes) {
|
||||
template<typename TNode>
|
||||
static int Index(TNode* node, const Nodes<TNode>& nodes) {
|
||||
if (!node) return -1;
|
||||
for (std::size_t i = 0; i < nodes.size(); ++i) if (node == &nodes[i]) return static_cast<int>(i);
|
||||
Require(false);
|
||||
@@ -30,10 +35,10 @@ static int Index(FT_ListNode node, const Nodes& nodes) {
|
||||
}
|
||||
|
||||
struct Lists {
|
||||
FT_ListRec guest{};
|
||||
GuestListRec guest{};
|
||||
FT_ListRec native{};
|
||||
Nodes actual{};
|
||||
Nodes expected{};
|
||||
Nodes<GuestListNodeRec> actual{};
|
||||
Nodes<FT_ListNodeRec> expected{};
|
||||
std::array<int, 4> values{11, 22, 33, 44};
|
||||
|
||||
Lists() {
|
||||
@@ -114,9 +119,10 @@ static void Mutations() {
|
||||
std::printf("list mutations: 2048 states compared with native FreeType\n");
|
||||
}
|
||||
|
||||
template<typename TNode>
|
||||
struct Walk {
|
||||
FT_List list;
|
||||
Nodes* nodes;
|
||||
std::conditional_t<std::is_same_v<TNode, GuestListNodeRec>, GuestListRec, FT_ListRec>* list;
|
||||
Nodes<TNode>* nodes;
|
||||
bool guest;
|
||||
bool remove;
|
||||
std::size_t stop;
|
||||
@@ -124,12 +130,13 @@ struct Walk {
|
||||
std::vector<int> visits;
|
||||
};
|
||||
|
||||
static int Visit(FT_ListNode node, void* user, bool guest) {
|
||||
auto& state = *static_cast<Walk*>(user);
|
||||
template<typename TNode>
|
||||
static int Visit(TNode* node, void* user, bool guest) {
|
||||
auto& state = *static_cast<Walk<TNode>*>(user);
|
||||
Require(state.guest == guest);
|
||||
state.visits.push_back(Index(node, *state.nodes));
|
||||
if (state.remove) {
|
||||
if (guest) FT_List_Remove_nid_postfix(state.list, node);
|
||||
if constexpr (std::is_same_v<TNode, GuestListNodeRec>) FT_List_Remove_nid_postfix(state.list, node);
|
||||
else FT_List_Remove(state.list, node);
|
||||
node->prev = nullptr;
|
||||
node->next = nullptr;
|
||||
@@ -172,8 +179,9 @@ struct Event {
|
||||
bool operator==(const Event&) const = default;
|
||||
};
|
||||
|
||||
template<typename TList>
|
||||
struct Disposal {
|
||||
FT_List list;
|
||||
TList* list;
|
||||
FT_Memory native;
|
||||
GuestMemoryRec* guest;
|
||||
void* user;
|
||||
@@ -181,34 +189,36 @@ struct Disposal {
|
||||
std::vector<Event> events;
|
||||
};
|
||||
|
||||
static void Release(Disposal& state, void* block) {
|
||||
template<typename TList>
|
||||
static void Release(Disposal<TList>& state, void* block) {
|
||||
const auto found = state.live.find(block);
|
||||
Require(found != state.live.end());
|
||||
state.events.push_back({2, found->second, state.list->head == nullptr || state.list->tail == nullptr});
|
||||
state.live.erase(found);
|
||||
delete static_cast<FT_ListNode>(block);
|
||||
using Node = std::conditional_t<std::is_same_v<TList, GuestListRec>, GuestListNodeRec, FT_ListNodeRec>;
|
||||
delete static_cast<Node*>(block);
|
||||
}
|
||||
|
||||
static void NativeFree(FT_Memory memory, void* block) {
|
||||
auto& state = *static_cast<Disposal*>(memory->user);
|
||||
auto& state = *static_cast<Disposal<FT_ListRec>*>(memory->user);
|
||||
Require(state.native == memory);
|
||||
Release(state, block);
|
||||
}
|
||||
|
||||
static void APS5_VABI GuestFree(GuestMemoryRec* memory, void* block) {
|
||||
auto& state = *static_cast<Disposal*>(memory->user);
|
||||
auto& state = *static_cast<Disposal<GuestListRec>*>(memory->user);
|
||||
Require(state.guest == memory);
|
||||
Release(state, block);
|
||||
}
|
||||
|
||||
static void NativeDestroy(FT_Memory memory, void* data, void* user) {
|
||||
auto& state = *static_cast<Disposal*>(memory->user);
|
||||
auto& state = *static_cast<Disposal<FT_ListRec>*>(memory->user);
|
||||
Require(state.native == memory && state.user == user);
|
||||
state.events.push_back({1, data ? *static_cast<int*>(data) : -1, state.list->head == nullptr || state.list->tail == nullptr});
|
||||
}
|
||||
|
||||
static void APS5_VABI GuestDestroy(GuestMemoryRec* memory, void* data, void* user) {
|
||||
auto& state = *static_cast<Disposal*>(memory->user);
|
||||
auto& state = *static_cast<Disposal<GuestListRec>*>(memory->user);
|
||||
Require(state.guest == memory && state.user == user);
|
||||
state.events.push_back({1, data ? *static_cast<int*>(data) : -1, state.list->head == nullptr || state.list->tail == nullptr});
|
||||
}
|
||||
@@ -216,7 +226,8 @@ static void APS5_VABI GuestDestroy(GuestMemoryRec* memory, void* data, void* use
|
||||
static void FinalizationCases() {
|
||||
for (const bool destroy : {false, true}) {
|
||||
for (const unsigned count : {0u, 1u, 8u}) {
|
||||
FT_ListRec guestList{}, nativeList{};
|
||||
GuestListRec guestList{};
|
||||
FT_ListRec nativeList{};
|
||||
std::array<int, 8> ids{0, 1, 2, 3, 4, 5, 6, 7};
|
||||
int token = 9;
|
||||
Disposal guest{&guestList, nullptr, nullptr, &token, {}, {}};
|
||||
@@ -226,7 +237,7 @@ static void FinalizationCases() {
|
||||
guest.guest = &guestMemory;
|
||||
native.native = &nativeMemory;
|
||||
for (unsigned i = 0; i < count; ++i) {
|
||||
auto* a = new FT_ListNodeRec{};
|
||||
auto* a = new GuestListNodeRec{};
|
||||
auto* b = new FT_ListNodeRec{};
|
||||
a->data = b->data = i == 0 ? nullptr : &ids[i];
|
||||
guest.live.emplace(a, i);
|
||||
|
||||
@@ -5,6 +5,7 @@ import json
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
from functools import cache
|
||||
from pathlib import Path
|
||||
|
||||
@@ -171,12 +172,30 @@ def compile_headers(compiler, compiler_args, groups, workers=4):
|
||||
|
||||
def compile_one(group):
|
||||
includes = "".join(f'#include "{header.relative_to(LIBS).as_posix()}"\n' for header in group)
|
||||
result = subprocess.run([compiler, *compiler_args, "-std=c++20", *warnings, "-fsyntax-only", "-x", "c++", f"-I{LIBS}", f"-I{ROOT / '3rdparty/freetype/include'}", "-"], input=includes * 2, text=True, capture_output=True)
|
||||
if result.returncode:
|
||||
raise RuntimeError(f"Header compilation failed: {group}\n{result.stdout}{result.stderr}")
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
dependencies = Path(directory) / "headers.d"
|
||||
result = subprocess.run([compiler, *compiler_args, "-std=c++20", *warnings, "-fsyntax-only", "-MD", "-MF", str(dependencies), "-MT", "public_headers", "-x", "c++", f"-I{LIBS}", f"-I{ROOT / '3rdparty/freetype/include'}", "-"], input=includes * 2, text=True, capture_output=True)
|
||||
if result.returncode:
|
||||
raise RuntimeError(f"Header compilation failed: {group}\n{result.stdout}{result.stderr}")
|
||||
text = dependencies.read_text(encoding="utf-8").replace("\\\n", "")
|
||||
if not text.startswith("public_headers:"):
|
||||
raise RuntimeError(f"Invalid compiler dependency output: {dependencies}")
|
||||
names = re.findall(r"(?:\\[ \t]|[^\s])+", text.removeprefix("public_headers:"))
|
||||
paths = [Path(re.sub(r"\\([ \t#\\])", r"\1", name).replace("$$", "$")).resolve() for name in names]
|
||||
forbidden = [path for path in paths if path.is_relative_to((ROOT / "3rdparty").resolve())]
|
||||
if forbidden:
|
||||
raise RuntimeError(f"Public headers depend on 3rdparty: {group}\n" + "\n".join(map(str, forbidden)))
|
||||
|
||||
errors = []
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=workers) as pool:
|
||||
list(pool.map(compile_one, groups))
|
||||
futures = [(group, pool.submit(compile_one, group)) for group in groups]
|
||||
for group, future in futures:
|
||||
try:
|
||||
future.result()
|
||||
except Exception as error:
|
||||
errors.append(f"{group}: {error}")
|
||||
if errors:
|
||||
raise RuntimeError(f"{len(errors)} header compilation units failed:\n\n" + "\n\n".join(errors))
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
Reference in new issue
Block a user