serde refl rebuild
This commit is contained in:
parent
0a5cb27b27
commit
5b5c35a5ef
@ -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<typename T>
|
||||
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<T>) {
|
||||
return JsonSerde<T>::Read(root, obj);
|
||||
return gen::JsonSerde<T>::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<T>::Write(doc, Any{t});
|
||||
yyjson_mut_val* root = gen::JsonSerde<T>::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);
|
||||
|
||||
@ -1,57 +1,58 @@
|
||||
#pragma once
|
||||
#include "../type.h"
|
||||
#include "refl/pch.h"
|
||||
#include <format>
|
||||
#include <string_view>
|
||||
namespace api {
|
||||
namespace archive {
|
||||
template<typename T>
|
||||
concept is_string_v = requires(T t) {
|
||||
{ static_cast<std::string>(t) } -> std::convertible_to<std::string>;
|
||||
};
|
||||
}
|
||||
using std::string_view;
|
||||
using refl::Any;
|
||||
using refl::UClass;
|
||||
using refl::type_name;
|
||||
using refl::TypeInfo;
|
||||
namespace gen {
|
||||
template<typename T>
|
||||
struct JsonSerde {
|
||||
inline static bool Read(yyjson_val* val, Any any) {
|
||||
struct Meta {};
|
||||
template<typename T>
|
||||
concept is_string_v = requires(T t) {
|
||||
{ static_cast<std::string>(t) } -> std::convertible_to<std::string>;
|
||||
};
|
||||
template<typename T>
|
||||
concept is_serde_v = std::is_same_v<T, bool> || std::is_integral_v<T> || std::is_floating_point_v<T> || is_string_v<T> || std::is_enum_v<T>;
|
||||
template<typename T, typename = void>
|
||||
struct JsonSerde {};
|
||||
template<typename T>
|
||||
struct JsonSerde<T, std::enable_if_t<is_serde_v<T>>>{
|
||||
inline static bool Read(yyjson_val* val, const void* ptr) {
|
||||
if constexpr (std::is_same_v<T, bool>) {
|
||||
*any.CastTo<T*>() = (T)yyjson_get_bool(val);
|
||||
*(T*)(ptr) = (T)yyjson_get_bool(val);
|
||||
}
|
||||
else if constexpr (std::is_integral_v<T>) {
|
||||
*any.CastTo<T*>() = (T)yyjson_get_uint(val);
|
||||
*(T*)(ptr) = (T)yyjson_get_uint(val);
|
||||
}
|
||||
else if constexpr (std::is_enum_v<T>) {
|
||||
*(T*)(ptr) = (T)yyjson_get_uint(val);
|
||||
}
|
||||
else if constexpr (std::is_floating_point_v<T>) {
|
||||
*any.CastTo<T*>() = (T)yyjson_get_real(val);
|
||||
*(T*)(ptr) = (T)yyjson_get_real(val);
|
||||
}
|
||||
else if constexpr (archive::is_string_v<T>) {
|
||||
*any.CastTo<T*>() = yyjson_get_str(val);
|
||||
else if constexpr (is_string_v<T>) {
|
||||
*(T*)(ptr) = yyjson_get_str(val);
|
||||
}
|
||||
else {
|
||||
throw std::runtime_error(std::format("unknown json read type {}", type_name<T>().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<T, bool>) {
|
||||
return yyjson_mut_bool(doc, *any.CastTo<T*>());
|
||||
return yyjson_mut_bool(doc, *(T*)(ptr));
|
||||
}
|
||||
else if constexpr (std::is_integral_v<T>) {
|
||||
return yyjson_mut_uint(doc, *any.CastTo<T*>());
|
||||
return yyjson_mut_uint(doc, *(T*)(ptr));
|
||||
}
|
||||
else if constexpr (std::is_enum_v<T>) {
|
||||
return yyjson_mut_uint(doc, (std::underlying_type_t<T>)*(T*)(ptr));
|
||||
}
|
||||
else if constexpr (std::is_floating_point_v<T>) {
|
||||
return yyjson_mut_real(doc, *any.CastTo<T*>());
|
||||
return yyjson_mut_real(doc, *(T*)(ptr));
|
||||
}
|
||||
else if constexpr (archive::is_string_v<T>) {
|
||||
auto c = (any.CastTo<T*>())->data();
|
||||
return yyjson_mut_str(doc, "");
|
||||
else if constexpr (is_string_v<T>) {
|
||||
return yyjson_mut_str(doc, ((T*)ptr)->data());
|
||||
}
|
||||
else {
|
||||
throw std::runtime_error(std::format("unknown json write type {}", type_name<T>().View()));
|
||||
return {};
|
||||
static_assert(false, "unknown json write type");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,4 +1,38 @@
|
||||
#include "serde.h"
|
||||
namespace gen {
|
||||
#ifdef API_DEBUG
|
||||
template<typename T>
|
||||
inline bool JsonRead(yyjson_val* node, const T& t) {
|
||||
if (!node) return false;
|
||||
return JsonSerde<T>::Read(node, &t);
|
||||
}
|
||||
template<typename T>
|
||||
inline yyjson_mut_val* JsonWrite(yyjson_mut_doc* doc, const T& t) {
|
||||
return JsonSerde<T>::Write(doc, &t);
|
||||
}
|
||||
#else
|
||||
#define JsonRead(node, t) if(node)JsonSerde<decltype(t)>::Read(node, &t)
|
||||
#define JsonWrite(doc, t) JsonSerde<decltype(t)>::Write(doc, &t)
|
||||
#endif
|
||||
template<typename T>
|
||||
struct JsonSerde<T, std::enable_if_t<refl::is_meta_v<T>>> {
|
||||
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 <typename T>
|
||||
struct has_json_specialization<T, std::void_t<decltype(&JsonSerde<T>::Read) >> : std::true_type {};
|
||||
struct has_json_specialization<T, std::void_t<decltype(gen::JsonSerde<T>::Read)>> : std::true_type {};
|
||||
}
|
||||
template<typename T>
|
||||
concept has_json_specialization_v = detail::has_json_specialization<T>::value;
|
||||
|
||||
#ifdef API_DEBUG
|
||||
template<typename T>
|
||||
inline bool JsonRead(yyjson_val* node, const T& t) {
|
||||
return JsonSerde<T>::Read(node, t);
|
||||
}
|
||||
template<typename T>
|
||||
inline yyjson_mut_val* JsonWrite(yyjson_mut_doc* doc, const T& t) {
|
||||
return JsonSerde<T>::Write(doc, t);
|
||||
}
|
||||
#else
|
||||
#define JsonRead(node, t) JsonSerde<decltype(t)>::Read(node, t)
|
||||
#endif
|
||||
}
|
||||
@ -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<typename T>
|
||||
static JsonVTable Make() {
|
||||
return { &JsonSerde<T>::Read, &JsonSerde<T>::Write };
|
||||
return { &gen::JsonSerde<T>::Read, &gen::JsonSerde<T>::Write };
|
||||
}
|
||||
};
|
||||
using JsonFuncTable = std::pmr::unordered_map<const UClass*, JsonVTable>;
|
||||
|
||||
@ -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<T>::StaticClass,JsonVTable::Make<T>())
|
||||
#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;
|
||||
}
|
||||
|
||||
0
engine/modules/engine/core/include/archive/type.h
Normal file
0
engine/modules/engine/core/include/archive/type.h
Normal file
@ -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<IModuleSubsystem*> mSubSystems;
|
||||
};
|
||||
}
|
||||
#include "module.inl"
|
||||
#include "module.inl"
|
||||
#include "module_gen.inl"
|
||||
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include "moudle.h"
|
||||
#include "module.h"
|
||||
namespace api {
|
||||
template<typename T1, typename T2, typename Hasher = std::hash<T1>>
|
||||
using table = std::pmr::unordered_map<T1, T2, Hasher>;
|
||||
|
||||
@ -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")
|
||||
|
||||
@ -3,53 +3,53 @@
|
||||
#include <unordered_map>
|
||||
namespace pmr
|
||||
{
|
||||
static consteval inline size_t InvalidValue() noexcept { return static_cast<size_t>(-1); }
|
||||
constexpr inline size_t string_hash(std::string_view str) noexcept;
|
||||
class NameID {
|
||||
public:
|
||||
static consteval size_t InvalidValue() noexcept { return static_cast<size_t>(-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<size_t N>
|
||||
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<size_t N>
|
||||
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<size_t N>
|
||||
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();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -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<std::size_t N>
|
||||
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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -4,6 +4,9 @@
|
||||
#include <span>
|
||||
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*;
|
||||
|
||||
44
engine/modules/engine/zlib/include/refl/detail/meta.h
Normal file
44
engine/modules/engine/zlib/include/refl/detail/meta.h
Normal file
@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
#include "field.h"
|
||||
namespace gen {
|
||||
using pmr::CName;
|
||||
using pmr::FName;
|
||||
using pmr::string_hash;
|
||||
template<typename T, size_t hash>
|
||||
struct MetaImpl {};
|
||||
template<typename T>
|
||||
struct Property {
|
||||
std::string_view name;
|
||||
T ptr;
|
||||
constexpr Property(T ptr, std::string_view name) noexcept:name(name), ptr(ptr) {}
|
||||
};
|
||||
template<typename T>
|
||||
consteval Property<T> FProperty(T ptr, std::string_view name) { return { ptr, name }; }
|
||||
|
||||
// 遍历所有字段值
|
||||
template <typename Func, typename T, size_t hash = string_hash("Meta")>
|
||||
inline void for_each_field(Func&& func, T& obj) {
|
||||
constexpr auto props = MetaImpl<T, hash>::Fields();
|
||||
std::apply([&](auto... field) {
|
||||
((func(field.name, obj.*(field.ptr))), ...);
|
||||
}, props);
|
||||
}
|
||||
}
|
||||
namespace refl {
|
||||
struct MetaHelp{
|
||||
template<typename T, typename... Args>
|
||||
static FieldPtr CtorField(T(*ptr)(Args...), const MethodData& data = {});
|
||||
|
||||
template<typename T, typename Obj>
|
||||
static FieldPtr MemberField(T Obj::* ptr, CName name, const MemberData& data = {});
|
||||
|
||||
template<typename R, typename ...Args>
|
||||
static FieldPtr MethodField(R(*ptr)(Args...), CName name, const MethodData& data = {});
|
||||
|
||||
template<typename T, typename R, typename ...Args>
|
||||
static FieldPtr MethodField(R(T::* ptr)(Args...), CName name, const MethodData& data = {});
|
||||
|
||||
template<typename T, typename R, typename ...Args>
|
||||
static FieldPtr MethodField(R(T::* ptr)(Args...)const, CName name, const MethodData& data = {});
|
||||
};
|
||||
}
|
||||
1
engine/modules/engine/zlib/include/refl/detail/meta.inl
Normal file
1
engine/modules/engine/zlib/include/refl/detail/meta.inl
Normal file
@ -0,0 +1 @@
|
||||
#include "meta.h"
|
||||
@ -95,6 +95,20 @@ namespace refl {
|
||||
using args_type_t = detail::args_type<std::remove_cv_t<T>>::type;
|
||||
};
|
||||
namespace refl {
|
||||
template<class T>
|
||||
struct Meta {};
|
||||
|
||||
template<class T>
|
||||
concept is_meta_v = requires { typename Meta<T>::Impl; };
|
||||
|
||||
template <class T>
|
||||
concept has_parent_v = requires { typename Meta<T>::Parent; };
|
||||
|
||||
template<class T>
|
||||
using meta_t = Meta<T>::Impl;
|
||||
template<class T>
|
||||
using parent_t = typename Meta<T>::Parent;
|
||||
|
||||
//类型接口
|
||||
template<typename T>
|
||||
struct TypeInfoImpl;
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
#include "uclass.h"
|
||||
#include "name.h"
|
||||
#include "type.h"
|
||||
namespace refl{
|
||||
template <class T>
|
||||
concept is_metas_v = false;//requires(const Name & name) { MetaImpl<T>::MyMetas::GetMeta(name); };
|
||||
concept is_metas_v = requires(const Name & name) { Meta<T>::GetMeta(name); };
|
||||
template<typename T>
|
||||
class UClass_Auto : public UClass {
|
||||
public:
|
||||
@ -29,13 +30,29 @@ namespace refl{
|
||||
}
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct TypeInfoImpl<void> {
|
||||
inline static UClass StaticClass{ type_name<void>().View(), 0 };
|
||||
template<typename T, typename MetaImpl>
|
||||
class UClass_Meta : public UClass {
|
||||
using FieldsType = decltype(MetaImpl::MakeFields());
|
||||
FieldsType Fields{ MetaImpl::MakeFields() };
|
||||
UClass_Meta() : UClass(type_name<T>().View(), sizeof(T)) {
|
||||
if constexpr (has_parent_v<T>) {
|
||||
parent = &TypeInfo<parent_t<T>>::StaticClass;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct TypeInfoImpl {
|
||||
using MyUClass = UClass_Auto<T>;
|
||||
inline static MyUClass StaticClass{};
|
||||
};
|
||||
template<>
|
||||
struct TypeInfoImpl<void> {
|
||||
inline static UClass StaticClass{ type_name<void>().View(), 0 };
|
||||
};
|
||||
template<is_meta_v T>
|
||||
struct TypeInfoImpl<T> {
|
||||
using MyUClass = UClass_Meta<T, meta_t<T>>;
|
||||
inline static MyUClass StaticClass{};
|
||||
};
|
||||
}
|
||||
39
engine/modules/engine/zlib/include/refl/macro.h
Normal file
39
engine/modules/engine/zlib/include/refl/macro.h
Normal file
@ -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<Class>().View(), &refl::TypeInfo<Class>::StaticClass);
|
||||
|
||||
#define GENERATED_BODY() template <typename T, size_t hash>\
|
||||
friend class gen::MetaImpl;
|
||||
/*
|
||||
struct vec3{
|
||||
USING_OVERLOAD_CTOR(vec3)
|
||||
UFUNCTION({},ref = USING_CTOR_NAME)
|
||||
vec3(){}
|
||||
}
|
||||
*/
|
||||
@ -1,4 +1,6 @@
|
||||
#pragma once
|
||||
#include "detail/name.inl"
|
||||
#include "detail/any.inl"
|
||||
#include "detail/uclass.inl"
|
||||
#include "detail/meta.inl"
|
||||
#include "detail/uclass.inl"
|
||||
#include "macro.h"
|
||||
@ -1,4 +1,4 @@
|
||||
#include "module/moudle.h"
|
||||
#include "module/module.h"
|
||||
#include "asset/asset.h"
|
||||
class VulkanModule : public api::IDynamicModule
|
||||
{
|
||||
|
||||
1
engine/modules/render/vulkan/vulkan.plugin
Normal file
1
engine/modules/render/vulkan/vulkan.plugin
Normal file
@ -0,0 +1 @@
|
||||
{"flag":0,"name":"vulkan"}
|
||||
@ -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})
|
||||
add_rules("engine.plugin", {file = "include/vulkan/module.h"})
|
||||
94
engine/tools/make_plugin/src/macro_parse.cpp
Normal file
94
engine/tools/make_plugin/src/macro_parse.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
#include "macro_parse.h"
|
||||
#include <string>
|
||||
#include <stack>
|
||||
#include <optional>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
std::string_view module_macro[] = { MODULE_DEPENDENCY , IMPLEMENT_DYNAMIC_MODULE , IMPLEMENT_STATIC_MODULE };
|
||||
pmr::vector<pmr::string> parseArgs(std::string_view& str) {
|
||||
pmr::vector<pmr::string> args(&pool);
|
||||
std::stack<char> 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<MacroData> 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<MacroData>{};
|
||||
}
|
||||
// 读取文件并返回每一行内容
|
||||
pmr::vector<MacroData> readMacroFile(const char* file_path) {
|
||||
pmr::vector<MacroData> 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;
|
||||
}
|
||||
17
engine/tools/make_plugin/src/macro_parse.h
Normal file
17
engine/tools/make_plugin/src/macro_parse.h
Normal file
@ -0,0 +1,17 @@
|
||||
#include <memory_resource>
|
||||
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<pmr::string> args;
|
||||
MacroData() :args(&pool) {}
|
||||
MacroData(const pmr::vector<pmr::string>& args) :args(args) {}
|
||||
};
|
||||
pmr::vector<MacroData> readMacroFile(const char* file_path);
|
||||
@ -1,113 +1,19 @@
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <memory_resource>
|
||||
#include <stack>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
#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<pmr::string> args;
|
||||
MacroData() :args(&pool) {}
|
||||
MacroData(const pmr::vector<pmr::string>& args):args(args) {}
|
||||
};
|
||||
pmr::vector<pmr::string> parseArgs(std::string_view& str) {
|
||||
pmr::vector<pmr::string> args(&pool);
|
||||
std::stack<char> 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<MacroData> 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<MacroData>{};
|
||||
}
|
||||
// 读取文件并返回每一行内容
|
||||
pmr::vector<MacroData> readFile(const char* file_path) {
|
||||
pmr::vector<MacroData> lines(&pool);
|
||||
std::ifstream file(file_path);
|
||||
#include "module/module.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
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<MacroData>& mdList) {
|
||||
oss << '}';
|
||||
writeFile(file_path, oss.str());
|
||||
}
|
||||
namespace api {
|
||||
struct Guid {
|
||||
int a;
|
||||
float b;
|
||||
};
|
||||
template<>
|
||||
struct JsonSerde<Guid> {
|
||||
inline static bool Read(yyjson_val* node, Any any) {
|
||||
Guid& v = *any.CastTo<Guid*>();
|
||||
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<Guid*>();
|
||||
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<MacroData>& mdList) {
|
||||
api::Guid guid;
|
||||
guid.a = 1243;
|
||||
std::string_view data = api::JsonSerialize(guid);
|
||||
auto res = api::JsonDeserialize<api::Guid>(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<api::ModuleInfo>(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;
|
||||
}
|
||||
@ -1,3 +1,8 @@
|
||||
tool_target("make_plugin")
|
||||
add_files("src/main.cpp")
|
||||
add_deps("core")
|
||||
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]])
|
||||
@ -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}
|
||||
66
engine/xmake/rule_gen/make_gen.lua
Normal file
66
engine/xmake/rule_gen/make_gen.lua
Normal file
@ -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
|
||||
19
engine/xmake/rule_gen/xmake.lua
Normal file
19
engine/xmake/rule_gen/xmake.lua
Normal file
@ -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)
|
||||
@ -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
|
||||
@ -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")
|
||||
|
||||
5
engine/xmake/rule_tool/xmake.lua
Normal file
5
engine/xmake/rule_tool/xmake.lua
Normal file
@ -0,0 +1,5 @@
|
||||
rule("engine.tool")
|
||||
-- after_build(function (target)
|
||||
-- -- do nothing
|
||||
-- --print("after_install", target:targetfile())
|
||||
-- end)
|
||||
Loading…
Reference in New Issue
Block a user