From 5b5c35a5efaedf46310b266c0c0e0889e3da3274 Mon Sep 17 00:00:00 2001 From: ouczbs Date: Sat, 27 Jul 2024 14:24:46 +0800 Subject: [PATCH] serde refl rebuild --- .../engine/core/include/archive/json.h | 7 +- .../engine/core/include/archive/json/serde.h | 65 +++--- .../core/include/archive/json/serde.inl | 49 +++-- .../core/include/archive/json/serialize.h | 9 +- .../core/include/archive/json/serialize.inl | 7 +- .../engine/core/include/archive/type.h | 0 .../include/module/{moudle.h => module.h} | 17 +- .../core/include/module/module_manager.h | 2 +- engine/modules/engine/core/xmake.lua | 3 + .../zlib/include/{macro.h => enum_macro.h} | 0 engine/modules/engine/zlib/include/pmr/name.h | 75 +++---- .../modules/engine/zlib/include/pmr/name.inl | 10 +- .../engine/zlib/include/refl/detail/any.inl | 2 +- .../engine/zlib/include/refl/detail/field.h | 3 + .../engine/zlib/include/refl/detail/meta.h | 44 +++++ .../engine/zlib/include/refl/detail/meta.inl | 1 + .../engine/zlib/include/refl/detail/type.h | 14 ++ .../zlib/include/refl/detail/uclass.inl | 25 ++- .../modules/engine/zlib/include/refl/macro.h | 39 ++++ engine/modules/engine/zlib/include/refl/pch.h | 4 +- .../render/vulkan/include/vulkan/module.h | 2 +- engine/modules/render/vulkan/vulkan.plugin | 1 + engine/modules/render/vulkan/xmake.lua | 3 +- engine/tools/make_plugin/src/macro_parse.cpp | 94 +++++++++ engine/tools/make_plugin/src/macro_parse.h | 17 ++ engine/tools/make_plugin/src/main.cpp | 187 +++++------------- engine/tools/make_plugin/xmake.lua | 9 +- .../{rule_plugin => }/modules/find_sdk.lua | 17 +- engine/xmake/rule_gen/make_gen.lua | 66 +++++++ engine/xmake/rule_gen/xmake.lua | 19 ++ engine/xmake/rule_plugin/make_plugin.lua | 28 +-- engine/xmake/rule_plugin/xmake.lua | 1 + engine/xmake/rule_tool/xmake.lua | 5 + 33 files changed, 551 insertions(+), 274 deletions(-) create mode 100644 engine/modules/engine/core/include/archive/type.h rename engine/modules/engine/core/include/module/{moudle.h => module.h} (85%) rename engine/modules/engine/zlib/include/{macro.h => enum_macro.h} (100%) create mode 100644 engine/modules/engine/zlib/include/refl/detail/meta.h create mode 100644 engine/modules/engine/zlib/include/refl/detail/meta.inl create mode 100644 engine/modules/engine/zlib/include/refl/macro.h create mode 100644 engine/modules/render/vulkan/vulkan.plugin create mode 100644 engine/tools/make_plugin/src/macro_parse.cpp create mode 100644 engine/tools/make_plugin/src/macro_parse.h rename engine/xmake/{rule_plugin => }/modules/find_sdk.lua (60%) create mode 100644 engine/xmake/rule_gen/make_gen.lua create mode 100644 engine/xmake/rule_gen/xmake.lua create mode 100644 engine/xmake/rule_tool/xmake.lua diff --git a/engine/modules/engine/core/include/archive/json.h b/engine/modules/engine/core/include/archive/json.h index 8f611e5..1d9be85 100644 --- a/engine/modules/engine/core/include/archive/json.h +++ b/engine/modules/engine/core/include/archive/json.h @@ -4,6 +4,7 @@ #include "json/serde.inl" namespace api { using meta::result; + using std::string_view; enum class SerializeError : char { EMPTY, @@ -11,11 +12,13 @@ namespace api { }; template inline bool JsonDeserialize(string_view text, T* obj) { + if (text.empty()) return false; yyjson_alc alc = JsonAllocatorAdapter(); yyjson_doc* doc = yyjson_read_opts((char*)text.data(), text.size(), YYJSON_READ_INSITU, &alc, nullptr); + if (!doc) return false; yyjson_val* root = yyjson_doc_get_root(doc); if constexpr (has_json_specialization_v) { - return JsonSerde::Read(root, obj); + return gen::JsonSerde::Read(root, obj); } else { return JsonArchive::Deserialize(root, obj); @@ -35,7 +38,7 @@ namespace api { inline string_view JsonSerialize(const T& t) { yyjson_alc alc = JsonAllocatorAdapter(); yyjson_mut_doc* doc = yyjson_mut_doc_new(&alc); - yyjson_mut_val* root = JsonSerde::Write(doc, Any{t}); + yyjson_mut_val* root = gen::JsonSerde::Write(doc, &t); yyjson_mut_doc_set_root(doc, root); size_t len; const char* json_str = yyjson_mut_write_opts(doc, 0, &alc, &len, NULL); diff --git a/engine/modules/engine/core/include/archive/json/serde.h b/engine/modules/engine/core/include/archive/json/serde.h index a3f5012..2a40e84 100644 --- a/engine/modules/engine/core/include/archive/json/serde.h +++ b/engine/modules/engine/core/include/archive/json/serde.h @@ -1,57 +1,58 @@ #pragma once +#include "../type.h" #include "refl/pch.h" -#include -#include -namespace api { - namespace archive { - template - concept is_string_v = requires(T t) { - { static_cast(t) } -> std::convertible_to; - }; - } - using std::string_view; - using refl::Any; - using refl::UClass; - using refl::type_name; - using refl::TypeInfo; +namespace gen { template - struct JsonSerde { - inline static bool Read(yyjson_val* val, Any any) { + struct Meta {}; + template + concept is_string_v = requires(T t) { + { static_cast(t) } -> std::convertible_to; + }; + template + concept is_serde_v = std::is_same_v || std::is_integral_v || std::is_floating_point_v || is_string_v || std::is_enum_v; + template + struct JsonSerde {}; + template + struct JsonSerde>>{ + inline static bool Read(yyjson_val* val, const void* ptr) { if constexpr (std::is_same_v) { - *any.CastTo() = (T)yyjson_get_bool(val); + *(T*)(ptr) = (T)yyjson_get_bool(val); } else if constexpr (std::is_integral_v) { - *any.CastTo() = (T)yyjson_get_uint(val); + *(T*)(ptr) = (T)yyjson_get_uint(val); + } + else if constexpr (std::is_enum_v) { + *(T*)(ptr) = (T)yyjson_get_uint(val); } else if constexpr (std::is_floating_point_v) { - *any.CastTo() = (T)yyjson_get_real(val); + *(T*)(ptr) = (T)yyjson_get_real(val); } - else if constexpr (archive::is_string_v) { - *any.CastTo() = yyjson_get_str(val); + else if constexpr (is_string_v) { + *(T*)(ptr) = yyjson_get_str(val); } else { - throw std::runtime_error(std::format("unknown json read type {}", type_name().View())); - return false; + static_assert(false, "unknown json read type"); } return true; } - inline static yyjson_mut_val* Write(yyjson_mut_doc* doc, Any any) { + inline static yyjson_mut_val* Write(yyjson_mut_doc* doc, const void* ptr) { if constexpr (std::is_same_v) { - return yyjson_mut_bool(doc, *any.CastTo()); + return yyjson_mut_bool(doc, *(T*)(ptr)); } else if constexpr (std::is_integral_v) { - return yyjson_mut_uint(doc, *any.CastTo()); + return yyjson_mut_uint(doc, *(T*)(ptr)); + } + else if constexpr (std::is_enum_v) { + return yyjson_mut_uint(doc, (std::underlying_type_t)*(T*)(ptr)); } else if constexpr (std::is_floating_point_v) { - return yyjson_mut_real(doc, *any.CastTo()); + return yyjson_mut_real(doc, *(T*)(ptr)); } - else if constexpr (archive::is_string_v) { - auto c = (any.CastTo())->data(); - return yyjson_mut_str(doc, ""); + else if constexpr (is_string_v) { + return yyjson_mut_str(doc, ((T*)ptr)->data()); } else { - throw std::runtime_error(std::format("unknown json write type {}", type_name().View())); - return {}; + static_assert(false, "unknown json write type"); } } }; diff --git a/engine/modules/engine/core/include/archive/json/serde.inl b/engine/modules/engine/core/include/archive/json/serde.inl index 6eccbe4..271f891 100644 --- a/engine/modules/engine/core/include/archive/json/serde.inl +++ b/engine/modules/engine/core/include/archive/json/serde.inl @@ -1,4 +1,38 @@ #include "serde.h" +namespace gen { +#ifdef API_DEBUG + template + inline bool JsonRead(yyjson_val* node, const T& t) { + if (!node) return false; + return JsonSerde::Read(node, &t); + } + template + inline yyjson_mut_val* JsonWrite(yyjson_mut_doc* doc, const T& t) { + return JsonSerde::Write(doc, &t); + } +#else +#define JsonRead(node, t) if(node)JsonSerde::Read(node, &t) +#define JsonWrite(doc, t) JsonSerde::Write(doc, &t) +#endif + template + struct JsonSerde>> { + inline static bool Read(yyjson_val* val, const void* ptr) { + T& v = *(T*)ptr; + for_each_field([=](std::string_view name, auto&& value) { + JsonRead(yyjson_obj_get(val, name.data()), value); + }, v); + return true; + } + inline static yyjson_mut_val* Write(yyjson_mut_doc* doc, const void* ptr) { + T& v = *(T*)ptr; + yyjson_mut_val* obj = yyjson_mut_obj(doc); + for_each_field([=](std::string_view name, auto&& value) { + yyjson_mut_obj_add_val(doc, obj, name.data(), JsonWrite(doc, value)); + }, v); + return obj; + } + }; +} namespace api { namespace detail { // 辅助结构体,用于检查特化版本 @@ -6,21 +40,8 @@ namespace api { struct has_json_specialization : std::false_type {}; // 特化辅助结构体,匹配特化版本 template - struct has_json_specialization::Read) >> : std::true_type {}; + struct has_json_specialization::Read)>> : std::true_type {}; } template concept has_json_specialization_v = detail::has_json_specialization::value; - -#ifdef API_DEBUG - template - inline bool JsonRead(yyjson_val* node, const T& t) { - return JsonSerde::Read(node, t); - } - template - inline yyjson_mut_val* JsonWrite(yyjson_mut_doc* doc, const T& t) { - return JsonSerde::Write(doc, t); - } -#else -#define JsonRead(node, t) JsonSerde::Read(node, t) -#endif } \ No newline at end of file diff --git a/engine/modules/engine/core/include/archive/json/serialize.h b/engine/modules/engine/core/include/archive/json/serialize.h index a993f6c..da39d95 100644 --- a/engine/modules/engine/core/include/archive/json/serialize.h +++ b/engine/modules/engine/core/include/archive/json/serialize.h @@ -2,12 +2,15 @@ #include "yyjson.h" #include "serde.h" namespace api { + using refl::Any; + using refl::UClass; + using refl::TypeInfo; struct JsonVTable { - bool(*Read)(yyjson_val*, Any) = nullptr; - yyjson_mut_val*(*Write)(yyjson_mut_doc*, Any) = nullptr; + bool(*Read)(yyjson_val*, const void*) = nullptr; + yyjson_mut_val*(*Write)(yyjson_mut_doc*, const void*) = nullptr; template static JsonVTable Make() { - return { &JsonSerde::Read, &JsonSerde::Write }; + return { &gen::JsonSerde::Read, &gen::JsonSerde::Write }; } }; using JsonFuncTable = std::pmr::unordered_map; diff --git a/engine/modules/engine/core/include/archive/json/serialize.inl b/engine/modules/engine/core/include/archive/json/serialize.inl index 9d3a12a..b1fa1f6 100644 --- a/engine/modules/engine/core/include/archive/json/serialize.inl +++ b/engine/modules/engine/core/include/archive/json/serialize.inl @@ -2,7 +2,7 @@ #include "serde.h" namespace api { // 定义 yyjson_alc 适配器类 - yyjson_alc JsonAllocatorAdapter(std::pmr::memory_resource* mr = &FramePool) { + inline yyjson_alc JsonAllocatorAdapter(std::pmr::memory_resource* mr = &FramePool) { // 初始化 yyjson_alc 结构体 yyjson_alc alc; alc.malloc = [](void* ctx, size_t size) -> void* { @@ -30,6 +30,7 @@ namespace api { inline JsonFuncTable JsonArchive::BuildFuncTable() { JsonFuncTable funcTable{ &MemPool }; + using std::string_view; #define RegisterAny(T) funcTable.emplace(&TypeInfo::StaticClass,JsonVTable::Make()) #include "../register.inl" #undef RegisterAny @@ -47,7 +48,7 @@ namespace api { } auto it = FuncTable.find(any.cls); if (it != FuncTable.end()) { - return it->second.Write(doc, any); + return it->second.Write(doc, any.ptr); } return {}; } @@ -58,7 +59,7 @@ namespace api { } auto it = FuncTable.find(any.cls); if (it != FuncTable.end()) { - return it->second.Read(res, any); + return it->second.Read(res, any.ptr); } return false; } diff --git a/engine/modules/engine/core/include/archive/type.h b/engine/modules/engine/core/include/archive/type.h new file mode 100644 index 0000000..e69de29 diff --git a/engine/modules/engine/core/include/module/moudle.h b/engine/modules/engine/core/include/module/module.h similarity index 85% rename from engine/modules/engine/core/include/module/moudle.h rename to engine/modules/engine/core/include/module/module.h index df056bc..d662de7 100644 --- a/engine/modules/engine/core/include/module/moudle.h +++ b/engine/modules/engine/core/include/module/module.h @@ -1,7 +1,8 @@ #pragma once #include "pmr/name.h" -#include "macro.h" +#include "enum_macro.h" #include "os/shared_library.h" +#include "refl/pch.h" namespace api { using pmr::Name; enum class EModuleFlag : uint32_t { @@ -9,14 +10,23 @@ namespace api { }; ENABLE_BITMASK_OPERATORS(EModuleFlag); struct ModuleInfo { - EModuleFlag flag; + UPROPERTY() + EModuleFlag flag{0}; + UPROPERTY() Name name; //!< name of the plugin + UPROPERTY() Name prettyname; //!< formatted name of the plugin + UPROPERTY() Name core_version; //!< version of the engine + UPROPERTY() Name version; // !< version of the plugin + UPROPERTY() Name linking; // !< linking of the plugin + UPROPERTY() Name license; //!< license of the plugin + UPROPERTY() Name url; //!< url of the plugin + UPROPERTY() Name copyright; //!< copyright of the plugin public: bool IsReload() { @@ -55,4 +65,5 @@ namespace api { std::vector mSubSystems; }; } -#include "module.inl" \ No newline at end of file +#include "module.inl" +#include "module_gen.inl" \ No newline at end of file diff --git a/engine/modules/engine/core/include/module/module_manager.h b/engine/modules/engine/core/include/module/module_manager.h index 3a0c291..9b866de 100644 --- a/engine/modules/engine/core/include/module/module_manager.h +++ b/engine/modules/engine/core/include/module/module_manager.h @@ -1,5 +1,5 @@ #pragma once -#include "moudle.h" +#include "module.h" namespace api { template> using table = std::pmr::unordered_map; diff --git a/engine/modules/engine/core/xmake.lua b/engine/modules/engine/core/xmake.lua index 8a55dee..ac1989f 100644 --- a/engine/modules/engine/core/xmake.lua +++ b/engine/modules/engine/core/xmake.lua @@ -1,4 +1,7 @@ static_component("core","engine") + add_rules("c++.codegen",{ + files = {"include/module/module.h"} + }) add_includedirs("include", "include/3rdparty", {public = true}) add_headerfiles("include/**.h","include/**.inl") add_files("src/**.cpp") diff --git a/engine/modules/engine/zlib/include/macro.h b/engine/modules/engine/zlib/include/enum_macro.h similarity index 100% rename from engine/modules/engine/zlib/include/macro.h rename to engine/modules/engine/zlib/include/enum_macro.h diff --git a/engine/modules/engine/zlib/include/pmr/name.h b/engine/modules/engine/zlib/include/pmr/name.h index 1eb180a..decd39a 100644 --- a/engine/modules/engine/zlib/include/pmr/name.h +++ b/engine/modules/engine/zlib/include/pmr/name.h @@ -3,53 +3,53 @@ #include namespace pmr { + static consteval inline size_t InvalidValue() noexcept { return static_cast(-1); } constexpr inline size_t string_hash(std::string_view str) noexcept; - class NameID { - public: - static consteval size_t InvalidValue() noexcept { return static_cast(-1); } - - constexpr NameID() noexcept : hash{ InvalidValue() } {} - explicit constexpr NameID(size_t value) noexcept : hash{ value } {} - constexpr NameID(std::string_view str) noexcept : hash{ string_hash(str) } {} - template - constexpr NameID(const char(&str)[N]) noexcept : hash{ string_hash(str) } {} - - constexpr size_t GetValue() const noexcept { return hash; } - - constexpr bool Valid() const noexcept { return hash != InvalidValue(); } - - constexpr bool Is(std::string_view str) const noexcept { return hash == NameID{ str }.GetValue(); } - - explicit constexpr operator bool() const noexcept { return Valid(); } - - constexpr std::strong_ordering operator<=>(const NameID& rhs) const noexcept = default; - std::string ToString() const; - const std::pmr::string& ToStringRef() const; - operator std::string() const { return ToString(); } - private: - size_t hash; - }; struct Name { + private: size_t hash; #ifdef API_DEBUG std::string_view value; #endif // API_DEBUG public: - Name():hash(NameID::InvalidValue()) {}; - Name(const char* str)noexcept; + Name():hash(InvalidValue()) {}; template - constexpr Name(const char(&str)[N]) noexcept; + Name(const char(&str)[N]) noexcept; + Name(const char* str)noexcept; Name(const std::string& str)noexcept; Name(std::string_view str)noexcept; auto operator<=>(const Name& other) const noexcept { return hash <=> other.hash; }; - bool operator==(const Name& other) const { - return hash == other.hash; - } - constexpr size_t GetValue() const noexcept { return hash; } + bool operator==(const Name& other) const {return hash == other.hash;} + const char* data()const { return ToStringView().data(); } + constexpr size_t Hash() const noexcept { return hash; } std::string ToString() const; const std::string_view ToStringView() const; operator std::string() const { return ToString(); } }; + class CName { + private: + size_t hash; + std::string_view value; + public: + constexpr CName() noexcept : hash{ InvalidValue() } {} + constexpr CName(std::string_view str) noexcept : hash{ string_hash(str) } ,value(str) {} + template + constexpr CName(const char(&str)[N]) noexcept : hash{ string_hash(str) }, value(str) {} + const char* data()const { return Value().data(); } + constexpr size_t Hash() const noexcept { return hash; } + constexpr std::string_view Value() const noexcept { return value; } + constexpr bool Valid() const noexcept { return hash != InvalidValue(); } + + explicit constexpr operator bool() const noexcept { return Valid(); } + + constexpr auto operator<=>(const CName& rhs) const noexcept { return hash <=> rhs.hash; }; + bool operator==(const CName& other) const { return hash == other.hash; } + std::string ToString() const { return std::string(value); }; + operator std::string() const { return ToString(); } + }; + bool operator==(const CName& cname, const Name& name) { + return cname.Hash() == name.Hash(); + } constexpr inline size_t string_hash(std::string_view str) noexcept { constexpr size_t fnv_offset_basis = 0xcbf29ce484222325; @@ -66,22 +66,23 @@ namespace pmr return hash; } + consteval static CName FName(std::string_view view) { return CName{ view }; }; } namespace std { template<> - struct hash<::pmr::NameID> + struct hash<::pmr::CName> { - size_t operator()(const ::pmr::NameID& ID) const noexcept + size_t operator()(const ::pmr::CName& name) const noexcept { - return ID.GetValue(); + return name.Hash(); } }; template<> struct hash<::pmr::Name> { - size_t operator()(const ::pmr::Name& ID) const noexcept + size_t operator()(const ::pmr::Name& name) const noexcept { - return ID.GetValue(); + return name.Hash(); } }; } diff --git a/engine/modules/engine/zlib/include/pmr/name.inl b/engine/modules/engine/zlib/include/pmr/name.inl index 22f9a41..3ee21ed 100644 --- a/engine/modules/engine/zlib/include/pmr/name.inl +++ b/engine/modules/engine/zlib/include/pmr/name.inl @@ -32,14 +32,6 @@ namespace pmr { } return it->second; } - inline std::string NameID::ToString() const - { - return std::string(NameTable::Find(hash)); - } - inline const std::pmr::string& NameID::ToStringRef() const - { - return NameTable::Find(hash); - } #ifdef API_DEBUG #define MAKE_NAME_PAIR(hash, str) value = NameTable::MakePair(hash, str) #define NAME_TO_STRING value @@ -60,7 +52,7 @@ namespace pmr { MAKE_NAME_PAIR(hash, str); } template - inline constexpr Name::Name(const char(&str)[N]) noexcept : hash(string_hash(str)) + inline Name::Name(const char(&str)[N]) noexcept : hash(string_hash(str)) { MAKE_NAME_PAIR(hash, str); } diff --git a/engine/modules/engine/zlib/include/refl/detail/any.inl b/engine/modules/engine/zlib/include/refl/detail/any.inl index 6977bd4..78f9b53 100644 --- a/engine/modules/engine/zlib/include/refl/detail/any.inl +++ b/engine/modules/engine/zlib/include/refl/detail/any.inl @@ -1,7 +1,7 @@ #include "any.h" #include "uclass.h" namespace refl{ - bool Any::Check(const UClass* parent)const + inline bool Any::Check(const UClass* parent)const { if (cls == parent) { return true; diff --git a/engine/modules/engine/zlib/include/refl/detail/field.h b/engine/modules/engine/zlib/include/refl/detail/field.h index 0c26189..4edc5f8 100644 --- a/engine/modules/engine/zlib/include/refl/detail/field.h +++ b/engine/modules/engine/zlib/include/refl/detail/field.h @@ -4,6 +4,9 @@ #include namespace refl { using pmr::Name; + using pmr::CName; + using pmr::FName; + using pmr::string_hash; using std::span; using Offset = uint32_t; using Method = void*; diff --git a/engine/modules/engine/zlib/include/refl/detail/meta.h b/engine/modules/engine/zlib/include/refl/detail/meta.h new file mode 100644 index 0000000..69539e2 --- /dev/null +++ b/engine/modules/engine/zlib/include/refl/detail/meta.h @@ -0,0 +1,44 @@ +#pragma once +#include "field.h" +namespace gen { + using pmr::CName; + using pmr::FName; + using pmr::string_hash; + template + struct MetaImpl {}; + template + struct Property { + std::string_view name; + T ptr; + constexpr Property(T ptr, std::string_view name) noexcept:name(name), ptr(ptr) {} + }; + template + consteval Property FProperty(T ptr, std::string_view name) { return { ptr, name }; } + + // 遍历所有字段值 + template + inline void for_each_field(Func&& func, T& obj) { + constexpr auto props = MetaImpl::Fields(); + std::apply([&](auto... field) { + ((func(field.name, obj.*(field.ptr))), ...); + }, props); + } +} +namespace refl { + struct MetaHelp{ + template + static FieldPtr CtorField(T(*ptr)(Args...), const MethodData& data = {}); + + template + static FieldPtr MemberField(T Obj::* ptr, CName name, const MemberData& data = {}); + + template + static FieldPtr MethodField(R(*ptr)(Args...), CName name, const MethodData& data = {}); + + template + static FieldPtr MethodField(R(T::* ptr)(Args...), CName name, const MethodData& data = {}); + + template + static FieldPtr MethodField(R(T::* ptr)(Args...)const, CName name, const MethodData& data = {}); + }; +} \ No newline at end of file diff --git a/engine/modules/engine/zlib/include/refl/detail/meta.inl b/engine/modules/engine/zlib/include/refl/detail/meta.inl new file mode 100644 index 0000000..7a188e0 --- /dev/null +++ b/engine/modules/engine/zlib/include/refl/detail/meta.inl @@ -0,0 +1 @@ +#include "meta.h" \ No newline at end of file diff --git a/engine/modules/engine/zlib/include/refl/detail/type.h b/engine/modules/engine/zlib/include/refl/detail/type.h index 3dd95bc..17abd97 100644 --- a/engine/modules/engine/zlib/include/refl/detail/type.h +++ b/engine/modules/engine/zlib/include/refl/detail/type.h @@ -95,6 +95,20 @@ namespace refl { using args_type_t = detail::args_type>::type; }; namespace refl { + template + struct Meta {}; + + template + concept is_meta_v = requires { typename Meta::Impl; }; + + template + concept has_parent_v = requires { typename Meta::Parent; }; + + template + using meta_t = Meta::Impl; + template + using parent_t = typename Meta::Parent; + //类型接口 template struct TypeInfoImpl; diff --git a/engine/modules/engine/zlib/include/refl/detail/uclass.inl b/engine/modules/engine/zlib/include/refl/detail/uclass.inl index 9907b62..52cbe76 100644 --- a/engine/modules/engine/zlib/include/refl/detail/uclass.inl +++ b/engine/modules/engine/zlib/include/refl/detail/uclass.inl @@ -1,8 +1,9 @@ #include "uclass.h" #include "name.h" +#include "type.h" namespace refl{ template - concept is_metas_v = false;//requires(const Name & name) { MetaImpl::MyMetas::GetMeta(name); }; + concept is_metas_v = requires(const Name & name) { Meta::GetMeta(name); }; template class UClass_Auto : public UClass { public: @@ -29,13 +30,29 @@ namespace refl{ } } }; - template<> - struct TypeInfoImpl { - inline static UClass StaticClass{ type_name().View(), 0 }; + template + class UClass_Meta : public UClass { + using FieldsType = decltype(MetaImpl::MakeFields()); + FieldsType Fields{ MetaImpl::MakeFields() }; + UClass_Meta() : UClass(type_name().View(), sizeof(T)) { + if constexpr (has_parent_v) { + parent = &TypeInfo>::StaticClass; + } + + } }; template struct TypeInfoImpl { using MyUClass = UClass_Auto; inline static MyUClass StaticClass{}; }; + template<> + struct TypeInfoImpl { + inline static UClass StaticClass{ type_name().View(), 0 }; + }; + template + struct TypeInfoImpl { + using MyUClass = UClass_Meta>; + inline static MyUClass StaticClass{}; + }; } \ No newline at end of file diff --git a/engine/modules/engine/zlib/include/refl/macro.h b/engine/modules/engine/zlib/include/refl/macro.h new file mode 100644 index 0000000..9b805dd --- /dev/null +++ b/engine/modules/engine/zlib/include/refl/macro.h @@ -0,0 +1,39 @@ +#pragma once +#if !defined(__cppast) +#define __cppast(...) +#endif +#define __Meta(...) __cppast(Meta=__VA_ARGS__) +#define UPROPERTY(...) __Meta(__VA_ARGS__) +#define UFUNCTION(...) __Meta(__VA_ARGS__) + +#define __vkMeta(...) __cppast(vkMeta=__VA_ARGS__) +#define UPROPERTY_vk(...) __vkMeta(__VA_ARGS__) +#define UFUNCTION_vk(...) __vkMeta(__VA_ARGS__) + +#define __dxMeta(...) __cppast(dxMeta=__VA_ARGS__) +#define UPROPERTY_dx(...) __dxMeta(__VA_ARGS__) +#define UFUNCTION_dx(...) __dxMeta(__VA_ARGS__) + +// 辅助宏,用于实际拼接 +#define CONCATENATE(arg1, arg2) CONCATENATE_IMPL(arg1, arg2) +#define CONCATENATE_IMPL(arg1, arg2) arg1##arg2 +#define MY_UNIQUE_NAME(base) CONCATENATE(base, __LINE__) + +#define USING_CTOR_NAME MY_UNIQUE_NAME(__Ctor) +#define USING_FUNC_NAME MY_UNIQUE_NAME(__Func) + +#define USING_OVERLOAD_CTOR(Class, ...) using USING_CTOR_NAME = Class(*)(__VA_ARGS__); +#define USING_OVERLOAD_FUNC(R, ...) using USING_FUNC_NAME = R(*)(__VA_ARGS__); +#define USING_OVERLOAD_CLASS_FUNC(R, Class, ...) using USING_FUNC_NAME = R(Class::*)(__VA_ARGS__); + +#define REGISTER_META_TABLE(Class) refl::UClass::MetaTable.emplace(type_name().View(), &refl::TypeInfo::StaticClass); + +#define GENERATED_BODY() template \ +friend class gen::MetaImpl; +/* +struct vec3{ + USING_OVERLOAD_CTOR(vec3) + UFUNCTION({},ref = USING_CTOR_NAME) + vec3(){} +} +*/ \ No newline at end of file diff --git a/engine/modules/engine/zlib/include/refl/pch.h b/engine/modules/engine/zlib/include/refl/pch.h index f2d3617..b20f32b 100644 --- a/engine/modules/engine/zlib/include/refl/pch.h +++ b/engine/modules/engine/zlib/include/refl/pch.h @@ -1,4 +1,6 @@ #pragma once #include "detail/name.inl" #include "detail/any.inl" -#include "detail/uclass.inl" \ No newline at end of file +#include "detail/meta.inl" +#include "detail/uclass.inl" +#include "macro.h" \ No newline at end of file diff --git a/engine/modules/render/vulkan/include/vulkan/module.h b/engine/modules/render/vulkan/include/vulkan/module.h index 3f97789..9d8c244 100644 --- a/engine/modules/render/vulkan/include/vulkan/module.h +++ b/engine/modules/render/vulkan/include/vulkan/module.h @@ -1,4 +1,4 @@ -#include "module/moudle.h" +#include "module/module.h" #include "asset/asset.h" class VulkanModule : public api::IDynamicModule { diff --git a/engine/modules/render/vulkan/vulkan.plugin b/engine/modules/render/vulkan/vulkan.plugin new file mode 100644 index 0000000..56b5a13 --- /dev/null +++ b/engine/modules/render/vulkan/vulkan.plugin @@ -0,0 +1 @@ +{"flag":0,"name":"vulkan"} \ No newline at end of file diff --git a/engine/modules/render/vulkan/xmake.lua b/engine/modules/render/vulkan/xmake.lua index b4f74f3..8fa13fd 100644 --- a/engine/modules/render/vulkan/xmake.lua +++ b/engine/modules/render/vulkan/xmake.lua @@ -2,5 +2,4 @@ shared_component("vulkan","engine") add_includedirs("include/vulkan") add_headerfiles("include/**.h") add_files("src/**.cpp") - add_rules("engine.plugin", {file = "include/vulkan/module.h"}) - --add_deps("core", "asset", {public = true}) \ No newline at end of file + add_rules("engine.plugin", {file = "include/vulkan/module.h"}) \ No newline at end of file diff --git a/engine/tools/make_plugin/src/macro_parse.cpp b/engine/tools/make_plugin/src/macro_parse.cpp new file mode 100644 index 0000000..983bc15 --- /dev/null +++ b/engine/tools/make_plugin/src/macro_parse.cpp @@ -0,0 +1,94 @@ +#include "macro_parse.h" +#include +#include +#include +#include +#include +std::string_view module_macro[] = { MODULE_DEPENDENCY , IMPLEMENT_DYNAMIC_MODULE , IMPLEMENT_STATIC_MODULE }; +pmr::vector parseArgs(std::string_view& str) { + pmr::vector args(&pool); + std::stack stack; + enum EParseState { + EEmpty, + EBody, + }; + EParseState state = EEmpty; + int n = 0; + char segment[1024]; + for (char c : str) { + switch (state) + { + case EEmpty: + { + if (c == ' ' || c == '\t') + break; + state = EBody; + if (c == '(' && stack.empty()) { + stack.push(c); + break; + } + } + case EBody: + { + if (c == '(' || c == '{' || c == '[' || (c == '"' && stack.top() != '"')) { + stack.push(c); + } + else { + char t = stack.top(); + if ((t == '(' && c == ')') || (t == '[' && c == ']') || (t == '{' && c == '}') || (t == '"' && c == '"')) { + stack.pop(); + } + } + if (stack.empty()) { + std::string_view view(segment, n); + args.push_back(pmr::string(view, &pool)); + return args; + } + if (c == ',' && stack.size() == 1) { + std::string_view view(segment, n); + args.push_back(pmr::string(view, &pool)); + n = 0; + state = EEmpty; + } + else { + segment[n++] = c; + } + break; + } + default: + break; + } + } + return args; +} +std::optional parseLine(std::string_view line) { + for (auto macro : module_macro) { + size_t pos = line.find(macro); + if (pos != std::string_view::npos) { + line = line.substr(pos + macro.size()); + MacroData md{ parseArgs(line) }; + md.macro = macro.data(); + //std::cout << line << std::endl; + return md; + } + } + return std::optional{}; +} +// 读取文件并返回每一行内容 +pmr::vector readMacroFile(const char* file_path) { + pmr::vector lines(&pool); + std::ifstream file(file_path); + if (!file.is_open()) { + //std::cerr << "Failed to open file: " << file_path << std::endl; + return lines; + } + std::string line; + while (std::getline(file, line)) { + std::string_view line_view(line); + if (auto md = parseLine(line_view)) { + lines.push_back(md.value()); + } + } + file.close(); + return lines; +} diff --git a/engine/tools/make_plugin/src/macro_parse.h b/engine/tools/make_plugin/src/macro_parse.h new file mode 100644 index 0000000..ae26821 --- /dev/null +++ b/engine/tools/make_plugin/src/macro_parse.h @@ -0,0 +1,17 @@ +#include +namespace pmr { + using std::pmr::monotonic_buffer_resource; + using std::pmr::vector; + using std::pmr::string; +} +inline pmr::monotonic_buffer_resource pool; +inline const char* MODULE_DEPENDENCY = "MODULE_DEPENDENCY"; +inline const char* IMPLEMENT_DYNAMIC_MODULE = "IMPLEMENT_DYNAMIC_MODULE"; +inline const char* IMPLEMENT_STATIC_MODULE = "IMPLEMENT_STATIC_MODULE"; +struct MacroData { + const char* macro{ nullptr }; + pmr::vector args; + MacroData() :args(&pool) {} + MacroData(const pmr::vector& args) :args(args) {} +}; +pmr::vector readMacroFile(const char* file_path); \ No newline at end of file diff --git a/engine/tools/make_plugin/src/main.cpp b/engine/tools/make_plugin/src/main.cpp index d42e072..1b361a1 100644 --- a/engine/tools/make_plugin/src/main.cpp +++ b/engine/tools/make_plugin/src/main.cpp @@ -1,113 +1,19 @@ -#include -#include -#include -#include -#include -#include -#include -#include +#include "macro_parse.h" #include "archive/json.h" -namespace pmr { - using std::pmr::monotonic_buffer_resource; - using std::pmr::vector; - using std::pmr::string; -} -pmr::monotonic_buffer_resource pool; -const char* MODULE_DEPENDENCY = "MODULE_DEPENDENCY"; -const char* IMPLEMENT_DYNAMIC_MODULE = "IMPLEMENT_DYNAMIC_MODULE"; -const char* IMPLEMENT_STATIC_MODULE = "IMPLEMENT_STATIC_MODULE"; -std::string_view module_macro[] = { MODULE_DEPENDENCY , IMPLEMENT_DYNAMIC_MODULE , IMPLEMENT_STATIC_MODULE }; -struct MacroData{ - const char* macro{nullptr}; - pmr::vector args; - MacroData() :args(&pool) {} - MacroData(const pmr::vector& args):args(args) {} -}; -pmr::vector parseArgs(std::string_view& str) { - pmr::vector args(&pool); - std::stack stack; - enum EParseState { - EEmpty, - EBody, - }; - EParseState state = EEmpty; - int n = 0; - char segment[1024]; - for (char c : str) { - switch (state) - { - case EEmpty: - { - if (c == ' ' || c == '\t') - break; - state = EBody; - if (c == '(' && stack.empty()) { - stack.push(c); - break; - } - } - case EBody: - { - if (c == '(' || c == '{' || c == '[' || (c == '"' && stack.top() != '"')) { - stack.push(c); - }else{ - char t = stack.top(); - if ((t == '(' && c == ')') || (t == '[' && c == ']') || (t == '{' && c == '}') || (t == '"' && c == '"')) { - stack.pop(); - } - } - if (stack.empty()) { - std::string_view view(segment, n); - args.push_back(pmr::string(view, &pool)); - return args; - } - if (c == ',' && stack.size() == 1) { - std::string_view view(segment, n); - args.push_back(pmr::string(view, &pool)); - n = 0; - state = EEmpty; - } - else { - segment[n++] = c; - } - break; - } - default: - break; - } - } - return args; -} -std::optional parseLine(std::string_view line) { - for (auto macro : module_macro) { - size_t pos = line.find(macro); - if (pos != std::string_view::npos) { - line = line.substr(pos + macro.size()); - MacroData md{ parseArgs(line) }; - md.macro = macro.data(); - std::cout << line << std::endl; - return md; - } - } - return std::optional{}; -} -// 读取文件并返回每一行内容 -pmr::vector readFile(const char* file_path) { - pmr::vector lines(&pool); - std::ifstream file(file_path); +#include "module/module.h" +#include +#include +#include +std::string_view readFile(const char* file_path) { + std::ifstream file(file_path, std::ios::ate); if (!file.is_open()) { - //std::cerr << "Failed to open file: " << file_path << std::endl; - return lines; + return ""; } - std::string line; - while (std::getline(file, line)) { - std::string_view line_view(line); - if (auto md = parseLine(line_view)) { - lines.push_back(md.value()); - } - } - file.close(); - return lines; + size_t size = file.tellg(); + file.seekg(0); + char* ptr = new(FramePool)char[size]; + file.read(ptr, size); + return std::string_view(ptr, size); } void writeFile(const char* file_path, std::string_view data) { std::ofstream file(file_path, 0); @@ -134,43 +40,40 @@ void genLua(const char* file_path, const pmr::vector& mdList) { oss << '}'; writeFile(file_path, oss.str()); } -namespace api { - struct Guid { - int a; - float b; - }; - template<> - struct JsonSerde { - inline static bool Read(yyjson_val* node, Any any) { - Guid& v = *any.CastTo(); - JsonRead(yyjson_obj_get(node, "a"), v.a); - JsonRead(yyjson_obj_get(node, "b"), v.b); - return true; - } - inline static yyjson_mut_val* Write(yyjson_mut_doc* doc, Any any) { - Guid& v = *any.CastTo(); - auto obj = yyjson_mut_obj(doc); - yyjson_mut_obj_add_val(doc, obj, "a", JsonWrite(doc, v.a)); - yyjson_mut_obj_add_val(doc, obj, "b", JsonWrite(doc, v.b)); - return obj; - } - }; -} void genPlugin(const char* file_path, const pmr::vector& mdList) { - api::Guid guid; - guid.a = 1243; - std::string_view data = api::JsonSerialize(guid); - auto res = api::JsonDeserialize(data); - if (res) { - api::Guid g2 = res.value(); - int a = g2.a; - int b = g2.b; + std::string_view text = readFile(file_path); + api::ModuleInfo info; + api::JsonDeserialize(text, &info); + bool bchange = false; + for (auto& md : mdList) { + if (md.macro == IMPLEMENT_DYNAMIC_MODULE || md.macro == IMPLEMENT_STATIC_MODULE) { + api::Name name = md.args[1].c_str(); + bchange = info.name != name; + info.name = name; + } + else if (md.macro == MODULE_DEPENDENCY) { + for (auto& args : md.args) { + if (args[0] != '{') { + + } + } + } + } + if (bchange) { + writeFile(file_path, api::JsonSerialize(info)); } } -int main() { - const char* file_path = R"(F:\engine\zengine\engine\modules\render\vulkan\include\vulkan\module.h)"; - auto mdList = readFile(file_path); - genLua(R"(F:\engine\zengine\build\.gens\vulkan\windows\xmake.lua)", mdList); - genPlugin(R"(F:\engine\zengine\build\.gens\vulkan\windows\xmake.lua)", mdList); +int main(int argc, char* argv[]) { + if (argc < 6) { + return -1; + } + std::string project_dir = argv[1]; + std::string lua_file = project_dir + "\\" + argv[2]; + std::string script_dir = argv[3]; + std::string module_file = script_dir + "\\" + argv[4]; + std::string plugin_file = script_dir + "\\" + argv[5]; + auto mdList = readMacroFile(module_file.c_str()); + genLua(lua_file.c_str(), mdList); + genPlugin(plugin_file.c_str(), mdList); return 0; } \ No newline at end of file diff --git a/engine/tools/make_plugin/xmake.lua b/engine/tools/make_plugin/xmake.lua index c9e7da4..eb23143 100644 --- a/engine/tools/make_plugin/xmake.lua +++ b/engine/tools/make_plugin/xmake.lua @@ -1,3 +1,8 @@ tool_target("make_plugin") - add_files("src/main.cpp") - add_deps("core") \ No newline at end of file + add_includedirs("src") + add_files("src/*.cpp") + add_headerfiles("src/*.h") + add_rules("engine.tool") + add_deps("core") + set_runargs([[F:\engine\zengine]], [[build\.gens\vulkan\windows\xmake.lua]], + [[F:\engine\zengine\engine\modules\render\vulkan]], [[include/vulkan/module.h]], [[vulkan.plugin]]) \ No newline at end of file diff --git a/engine/xmake/rule_plugin/modules/find_sdk.lua b/engine/xmake/modules/find_sdk.lua similarity index 60% rename from engine/xmake/rule_plugin/modules/find_sdk.lua rename to engine/xmake/modules/find_sdk.lua index d944fe6..18780ed 100644 --- a/engine/xmake/rule_plugin/modules/find_sdk.lua +++ b/engine/xmake/modules/find_sdk.lua @@ -1,12 +1,21 @@ +function find_exe_dir() + local os_name = os.host() + local arch_name = os.arch() + local mode_name = is_mode("debug") and "debug" or "release" + + -- 构建生成目录路径 + return path.join(os.projectdir(), "build", os_name, arch_name, mode_name) +end function find_my_program(name, sdkdir, use_next) import("lib.detect.find_file") import("lib.detect.find_program") import("lib.detect.find_tool") local sdkdir = sdkdir or path.join(os.projectdir(), "tools") - local tool = find_tool(name, {pathes = {sdkdir, "/usr/local/bin"}}) - local prog = tool and tool.program or find_program(name, {pathes = {sdkdir, "/usr/local/bin"}}) - prog = prog or find_file(name, {sdkdir}) + local exedir = find_exe_dir() + local tool = find_tool(name, {pathes = {sdkdir, exedir, "/usr/local/bin"}}) + local prog = tool and tool.program or find_program(name, {pathes = {sdkdir,exedir, "/usr/local/bin"}}) + prog = prog or find_file(name, {sdkdir, exedir}) if (prog == nil) then if os.host() ~= "windows" then local outdata, errdata = os.iorun("which " .. name) @@ -21,7 +30,7 @@ function find_my_program(name, sdkdir, use_next) if not use_next then return find_my_program(name, path.join(sdkdir, name), true) end - print(name .. "_f not found! under " .. sdkdir) + print(name .. " not found! under " .. sdkdir, exedir) return end return {program = prog, sdkdir = sdkdir} diff --git a/engine/xmake/rule_gen/make_gen.lua b/engine/xmake/rule_gen/make_gen.lua new file mode 100644 index 0000000..bea4e1a --- /dev/null +++ b/engine/xmake/rule_gen/make_gen.lua @@ -0,0 +1,66 @@ +import("core.project.depend") +local genList = {} +function cmd_compile(genfile, sourcefile, template, macro, define) + if genList[genfile] then + return + end + import("find_sdk") + local meta = find_sdk.find_my_program("refl") + template = template or path.join(meta.sdkdir, "template") + if not macro then --优先使用库定义 + macro = path.join(os.projectdir(), "engine/modules/engine/zlib/include/refl/macro.h") + if not os.exists(macro) then + macro = path.join(os.curdir(), "macro.h") + end + end + argv = {"build", sourcefile, "-o", genfile, "-t", template, "-m", macro} + if define then + table.insert(argv, "-d") + table.insert(argv, define) + end + genList[genfile] = true + print("cmd_meta_compile", genfile) + os.execv(meta.program, argv) + return argv +end + +function _listen_gen_file(target, batch, template, macro, define) + genfile, sourcefile = batch[1], batch[2] + local dependfile = target:dependfile(genfile) + depend.on_changed( + function() + cmd_compile(batch[1], batch[2], template, macro, define) + end, + {dependfile = dependfile, files = sourcefile} + ) +end +function gen(target) + local gen_batch = target:data("codegen.batch") + if not gen_batch then + return + end + local template = target:extraconf("rules", "c++.codegen", "template") + local macro = target:extraconf("rules", "c++.codegen", "macro") + local define = target:extraconf("rules", "c++.codegen", "define") + for _, batch in ipairs(gen_batch) do + if batch[2] then + _listen_gen_file(target, batch, template, macro, define) + end + end +end + +function main(target, headerfiles) + local sourcedir = path.join(target:autogendir({root = true}), target:plat(), "inl") + if not os.isdir(sourcedir) then + os.mkdir(sourcedir) + end + target:add("includedirs", sourcedir, {public = true}) + local gen_batch = {} + for idx, headerfile in pairs(headerfiles) do + -- batch + sourcefile = path.join(sourcedir, path.basename(headerfile) .. "_gen.inl") + table.insert(gen_batch, {sourcefile, headerfile}) + end + -- save unit batch + target:data_set("codegen.batch", gen_batch) +end diff --git a/engine/xmake/rule_gen/xmake.lua b/engine/xmake/rule_gen/xmake.lua new file mode 100644 index 0000000..c8200c4 --- /dev/null +++ b/engine/xmake/rule_gen/xmake.lua @@ -0,0 +1,19 @@ +rule("c++.codegen") + set_extensions(".inl") + after_load(function (target) + if not is_mode("debug") then return end + import("make_gen") + local headerfiles = {} + local files = target:extraconf("rules", "c++.codegen", "files") + for _, file in ipairs(files) do + local p = path.join(target:scriptdir(), file) + for __, filepath in ipairs(os.files(p)) do + table.insert(headerfiles, filepath) + end + end + make_gen(target, headerfiles) + end) + on_config(function (target) + if not is_mode("debug") then return end + import("make_gen").gen(target) + end) \ No newline at end of file diff --git a/engine/xmake/rule_plugin/make_plugin.lua b/engine/xmake/rule_plugin/make_plugin.lua index 7bff865..fce107a 100644 --- a/engine/xmake/rule_plugin/make_plugin.lua +++ b/engine/xmake/rule_plugin/make_plugin.lua @@ -1,28 +1,30 @@ import("core.project.depend") function cmd_compile(target, genfile, file) - local res = [[ - { - {"core", { public = true}}, - {"asset", { public = true}}, - } - ]] - io.writefile(genfile, res) - local dependency = io.load(genfile) - for k,v in ipairs(dependency) do - --target:add("deps", v[1], v[2]) - end + import("find_sdk") + print("find make_plugin", is_mode("debug")) + local plugin = find_sdk.find_my_program("make_plugin") + if not plugin then return end + print("cmd_compile plugin", genfile, file) + argv = { os.projectdir() , genfile, target:scriptdir(), file, target:name() .. ".plugin"} + os.execv(plugin.program, argv) end function main(target, file) local sourcedir = path.join(target:autogendir({root = true}), target:plat()) if not os.isdir(sourcedir) then os.mkdir(sourcedir) end - local genfile = sourcedir .. "\\xmake.lua" + local genfile = path.join(sourcedir,"xmake.lua") local dependfile = target:dependfile(genfile) depend.on_changed( function() cmd_compile(target, genfile, file) end, - {dependfile = dependfile, files = {file}} + {dependfile = dependfile, files = {path.join(target:scriptdir(), file)}} ) + if os.exists(genfile) then + local dependency = io.load(genfile) + for k,v in ipairs(dependency) do + target:add("deps", v[1], v[2]) + end + end end \ No newline at end of file diff --git a/engine/xmake/rule_plugin/xmake.lua b/engine/xmake/rule_plugin/xmake.lua index df2523d..14e593c 100644 --- a/engine/xmake/rule_plugin/xmake.lua +++ b/engine/xmake/rule_plugin/xmake.lua @@ -1,6 +1,7 @@ rule("engine.plugin") set_extensions(".h") on_load(function (target) + if not is_mode("debug") then return end import("make_plugin") local file = target:extraconf("rules", "engine.plugin", "file") make_plugin(target, file or "module.h") diff --git a/engine/xmake/rule_tool/xmake.lua b/engine/xmake/rule_tool/xmake.lua new file mode 100644 index 0000000..32c6e7b --- /dev/null +++ b/engine/xmake/rule_tool/xmake.lua @@ -0,0 +1,5 @@ +rule("engine.tool") + -- after_build(function (target) + -- -- do nothing + -- --print("after_install", target:targetfile()) + -- end) \ No newline at end of file