refactor(autogen): moved object-related autogeneration into its own namespace/directory
This commit is contained in:
parent
deb72660da
commit
66f7f0bea6
10 changed files with 204 additions and 141 deletions
|
@ -4,8 +4,8 @@ find_package(Clang REQUIRED)
|
|||
add_executable(autogen
|
||||
src/main.cpp
|
||||
src/util.cpp
|
||||
src/analysis.cpp
|
||||
src/codegen.cpp
|
||||
src/object/analysis.cpp
|
||||
src/object/codegen.cpp
|
||||
)
|
||||
|
||||
set_target_properties(autogen PROPERTIES OUTPUT_NAME "autogen")
|
||||
|
|
|
@ -6,26 +6,23 @@
|
|||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include "analysis.h"
|
||||
#include "codegen.h"
|
||||
|
||||
#include "object/analysis.h"
|
||||
#include "object/codegen.h"
|
||||
|
||||
// namespace data {
|
||||
// #include "data/analysis.h"
|
||||
// #include "data/codegen.h"
|
||||
// }
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 4) {
|
||||
fprintf(stderr, "Usage: autogen <src-root> <src-file> <out-dir>\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
AnalysisState state;
|
||||
|
||||
fs::path srcRoot = argv[1];
|
||||
fs::path srcPath = argv[2];
|
||||
fs::path outPath = argv[3];
|
||||
int processObject(fs::path srcRoot, fs::path srcPath, fs::path outPath) {
|
||||
object::AnalysisState state;
|
||||
|
||||
fs::path relpath = fs::relative(srcPath, srcRoot);
|
||||
printf("[AUTOGEN] Processing file %s...\n", relpath.c_str());
|
||||
analyzeClasses(srcPath, srcRoot, &state);
|
||||
object::analyzeClasses(srcPath, srcRoot, &state);
|
||||
|
||||
fs::create_directories(outPath.parent_path()); // Make sure generated dir exists before we try writing to it
|
||||
|
||||
|
@ -33,10 +30,32 @@ int main(int argc, char** argv) {
|
|||
std::ofstream outStream(outPath);
|
||||
|
||||
for (auto& [_, clazz] : state.classes) {
|
||||
writeCodeForClass(outStream, clazz);
|
||||
object::writeCodeForClass(outStream, clazz);
|
||||
}
|
||||
|
||||
outStream.close();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 4) {
|
||||
fprintf(stderr, "Usage: autogen <object|data> <src-root> <src-file> <out-dir>\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string codeType = argv[1];
|
||||
|
||||
fs::path srcRoot = argv[2];
|
||||
fs::path srcPath = argv[3];
|
||||
fs::path outPath = argv[4];
|
||||
|
||||
if (codeType == "object") {
|
||||
return processObject(srcRoot, srcPath, outPath);
|
||||
} else if (codeType == "data") {
|
||||
return processObject(srcRoot, srcPath, outPath);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Unknown class type '%s'\n", codeType.c_str());
|
||||
return -1;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
#include "analysis.h"
|
||||
#include "util.h"
|
||||
#include "../util.h"
|
||||
#include <clang-c/CXFile.h>
|
||||
#include <clang-c/CXSourceLocation.h>
|
||||
#include <clang-c/Index.h>
|
||||
|
@ -7,77 +7,11 @@
|
|||
#include <optional>
|
||||
#include <filesystem>
|
||||
|
||||
using namespace object;
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
// Very simple parser
|
||||
// Example format:
|
||||
// name="Hello!", world=Test, read_only
|
||||
// Result:
|
||||
// "name": "Hello!", "world": "Test", "read_only": ""
|
||||
std::map<std::string, std::string> parseAnnotationString(std::string src) {
|
||||
std::map<std::string, std::string> result;
|
||||
|
||||
std::string currentIdent = "";
|
||||
std::string currentValue = "";
|
||||
int stage = 0;
|
||||
bool quoted = false;
|
||||
|
||||
int i = 0;
|
||||
for (; i < src.length(); i++) {
|
||||
if (src[i] == ' ' && (stage != 2 || !quoted)) continue; // Ignore spaces if not in stage 2 and quoted
|
||||
if (src[i] == ',' && stage == 0) continue; // Let empty commas slip by
|
||||
if (stage < 2 && (src[i] >= 'a' && src[i] <= 'z' || src[i] >= 'A' && src[i] <= 'Z' || src[i] >= '0' && src[i] <= '9' || src[i] == '_')) {
|
||||
currentIdent += src[i];
|
||||
stage = 1;
|
||||
continue;
|
||||
}
|
||||
if (stage == 1 && src[i] == '=') { // What follows is a value
|
||||
stage = 2;
|
||||
continue;
|
||||
}
|
||||
if (stage == 1 && src[i] == ',') { // Value-less key
|
||||
stage = 0;
|
||||
result[currentIdent] = "";
|
||||
currentIdent = "";
|
||||
continue;
|
||||
}
|
||||
if (stage == 2 && quoted && src[i] == '"') { // Close a quoted string
|
||||
quoted = false;
|
||||
continue;
|
||||
}
|
||||
if (stage == 2 && !quoted && src[i] == '"') { // Start a quoted string
|
||||
quoted = true;
|
||||
continue;
|
||||
}
|
||||
if (stage == 2 && !quoted && (src[i] == ' ' || src[i] == ',')) { // Terminate the string
|
||||
stage = 0;
|
||||
result[currentIdent] = currentValue;
|
||||
currentIdent = "";
|
||||
currentValue = "";
|
||||
continue;
|
||||
}
|
||||
if (stage == 2) { // Otherwise if in stage 2, simply add the character
|
||||
currentValue += src[i];
|
||||
continue;
|
||||
}
|
||||
fprintf(stderr, "Unexpected symbol: %c at index %d\n", src[i], i);
|
||||
fprintf(stderr, "\t%s\n", src.c_str());
|
||||
fprintf(stderr, "\t%s^\n", i > 0 ? std::string(i, '~').c_str() : "");
|
||||
abort();
|
||||
}
|
||||
|
||||
// Add the remaining value
|
||||
if (stage == 1) {
|
||||
result[currentIdent] = "";
|
||||
} else if (stage == 2) {
|
||||
result[currentIdent] = currentValue;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool findInstanceAnnotation(CXCursor cur) {
|
||||
static bool findInstanceAnnotation(CXCursor cur) {
|
||||
bool found = false;
|
||||
// Look for annotations in the class itself
|
||||
x_clang_visitChildren(cur, [&](CXCursor cur, CXCursor parent) {
|
||||
|
@ -93,38 +27,7 @@ bool findInstanceAnnotation(CXCursor cur) {
|
|||
return found;
|
||||
}
|
||||
|
||||
std::optional<std::string> findAnnotation(CXCursor cur, std::string annotationName) {
|
||||
std::optional<std::string> ret = std::nullopt;
|
||||
|
||||
x_clang_visitChildren(cur, [&](CXCursor cur, CXCursor parent) {
|
||||
CXCursorKind kind = clang_getCursorKind(cur);
|
||||
if (kind != CXCursor_AnnotateAttr) return CXChildVisit_Continue;
|
||||
|
||||
std::string annString = x_clang_toString(clang_getCursorDisplayName(cur));
|
||||
if (annString != annotationName) return CXChildVisit_Continue;
|
||||
|
||||
// Look inside for a StringLiteral
|
||||
|
||||
x_clang_visitChildren(cur, [&](CXCursor cur, CXCursor parent) {
|
||||
CXCursorKind kind = clang_getCursorKind(cur);
|
||||
// if (kind != CXCursor_StringLiteral) return CXChildVisit_Recurse;
|
||||
// String literals cannot be parsed as CXCursor_StringLiteral. I don't know why.
|
||||
if (kind != CXCursor_UnexposedExpr) return CXChildVisit_Recurse;
|
||||
|
||||
// https://stackoverflow.com/a/63859988/16255372
|
||||
auto res = clang_Cursor_Evaluate(cur);
|
||||
ret = clang_EvalResult_getAsStr(res);
|
||||
clang_EvalResult_dispose(res);
|
||||
|
||||
return CXChildVisit_Break;
|
||||
});
|
||||
|
||||
return CXChildVisit_Break;
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string findBaseClass(CXCursor cur) {
|
||||
static std::string findBaseClass(CXCursor cur) {
|
||||
std::string baseClass = "";
|
||||
x_clang_visitChildren(cur, [&](CXCursor cur, CXCursor parent) {
|
||||
CXCursorKind kind = clang_getCursorKind(cur);
|
||||
|
@ -137,8 +40,8 @@ std::string findBaseClass(CXCursor cur) {
|
|||
return baseClass;
|
||||
}
|
||||
|
||||
std::string currentCategory = "";
|
||||
void processField(CXCursor cur, ClassAnalysis* state) {
|
||||
static std::string currentCategory = "";
|
||||
static void processField(CXCursor cur, ClassAnalysis* state) {
|
||||
std::optional<std::string> propertyDef = findAnnotation(cur, "OB::def_prop");
|
||||
if (!propertyDef) return;
|
||||
|
||||
|
@ -216,7 +119,7 @@ void processField(CXCursor cur, ClassAnalysis* state) {
|
|||
};
|
||||
}
|
||||
|
||||
void processClass(CXCursor cur, AnalysisState* state, std::string className, std::string srcRoot) {
|
||||
static void processClass(CXCursor cur, AnalysisState* state, std::string className, std::string srcRoot) {
|
||||
ClassAnalysis anly;
|
||||
|
||||
// Find base class
|
||||
|
@ -264,7 +167,7 @@ void processClass(CXCursor cur, AnalysisState* state, std::string className, std
|
|||
}
|
||||
|
||||
// https://clang.llvm.org/docs/LibClang.html
|
||||
bool analyzeClasses(std::string path, std::string srcRoot, AnalysisState* state) {
|
||||
bool object::analyzeClasses(std::string path, std::string srcRoot, AnalysisState* state) {
|
||||
const char* cargs[] = { "-x", "c++", "-I", srcRoot.c_str(), "-D__AUTOGEN__", 0 };
|
||||
// THANK YOU SO MUCH THIS STACKOVERFLOW ANSWER IS SO HELPFUL
|
||||
// https://stackoverflow.com/a/59206378/16255372
|
|
@ -4,6 +4,8 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace object {
|
||||
|
||||
enum ClassFlags {
|
||||
ClassFlag_NotCreatable = 1<<0,
|
||||
ClassFlag_Service = 1<<1,
|
||||
|
@ -56,4 +58,6 @@ struct AnalysisState {
|
|||
std::map<std::string, ClassAnalysis> classes;
|
||||
};
|
||||
|
||||
bool analyzeClasses(std::string path, std::string srcRoot, AnalysisState* state);
|
||||
bool analyzeClasses(std::string path, std::string srcRoot, AnalysisState* state);
|
||||
|
||||
}
|
|
@ -4,7 +4,9 @@
|
|||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
std::map<std::string, std::string> CATEGORY_STR = {
|
||||
using namespace object;
|
||||
|
||||
static std::map<std::string, std::string> CATEGORY_STR = {
|
||||
{ "APPEARANCE", "PROP_CATEGORY_APPEARENCE" },
|
||||
{ "DATA", "PROP_CATEGORY_DATA" },
|
||||
{ "BEHAVIOR", "PROP_CATEGORY_BEHAVIOR" },
|
||||
|
@ -13,7 +15,7 @@ std::map<std::string, std::string> CATEGORY_STR = {
|
|||
{ "SURFACE_INPUT", "PROP_CATEGORY_SURFACE_INPUT" },
|
||||
};
|
||||
|
||||
std::map<std::string, std::string> MAPPED_TYPE = {
|
||||
static std::map<std::string, std::string> MAPPED_TYPE = {
|
||||
{ "bool", "Data::Bool" },
|
||||
{ "int", "Data::Int" },
|
||||
{ "float", "Data::Float" },
|
||||
|
@ -21,11 +23,11 @@ std::map<std::string, std::string> MAPPED_TYPE = {
|
|||
{ "glm::vec3", "Vector3" },
|
||||
};
|
||||
|
||||
std::map<std::string, std::monostate> ENUM_TYPES = {
|
||||
static std::map<std::string, std::monostate> ENUM_TYPES = {
|
||||
{ "SurfaceType", std::monostate() }
|
||||
};
|
||||
|
||||
std::string parseWeakPtr(std::string weakPtrType) {
|
||||
static std::string parseWeakPtr(std::string weakPtrType) {
|
||||
if (!weakPtrType.starts_with("std::weak_ptr")) return "";
|
||||
|
||||
int pos0 = weakPtrType.find("<");
|
||||
|
@ -35,7 +37,7 @@ std::string parseWeakPtr(std::string weakPtrType) {
|
|||
return subtype;
|
||||
}
|
||||
|
||||
std::string castFromVariant(std::string valueStr, std::string fieldType) {
|
||||
static std::string castFromVariant(std::string valueStr, std::string fieldType) {
|
||||
// Manual exception for now, enums will get their own system eventually
|
||||
if (fieldType == "SurfaceType") {
|
||||
return "(SurfaceType)(int)" + valueStr + ".get<Data::Int>()";
|
||||
|
@ -45,7 +47,7 @@ std::string castFromVariant(std::string valueStr, std::string fieldType) {
|
|||
return valueStr + ".get<" + (!mappedType.empty() ? mappedType : fieldType) + ">()";
|
||||
}
|
||||
|
||||
std::string castToVariant(std::string valueStr, std::string fieldType) {
|
||||
static std::string castToVariant(std::string valueStr, std::string fieldType) {
|
||||
// Manual exception for now, enums will get their own system eventually
|
||||
if (fieldType == "SurfaceType") {
|
||||
return "Data::Int((int)" + valueStr + ")";
|
||||
|
@ -64,7 +66,7 @@ std::string castToVariant(std::string valueStr, std::string fieldType) {
|
|||
return valueStr;
|
||||
}
|
||||
|
||||
void writePropertySetHandler(std::ofstream& out, ClassAnalysis state) {
|
||||
static void writePropertySetHandler(std::ofstream& out, ClassAnalysis state) {
|
||||
out << "fallible<MemberNotFound, AssignToReadOnlyMember> " << state.name << "::InternalSetPropertyValue(std::string name, Data::Variant value) {";
|
||||
|
||||
out << "\n ";
|
||||
|
@ -105,7 +107,7 @@ void writePropertySetHandler(std::ofstream& out, ClassAnalysis state) {
|
|||
out << "\n};\n\n";
|
||||
}
|
||||
|
||||
void writePropertyUpdateHandler(std::ofstream& out, ClassAnalysis state) {
|
||||
static void writePropertyUpdateHandler(std::ofstream& out, ClassAnalysis state) {
|
||||
out << "void " << state.name << "::InternalUpdateProperty(std::string name) {";
|
||||
|
||||
out << "\n ";
|
||||
|
@ -125,7 +127,7 @@ void writePropertyUpdateHandler(std::ofstream& out, ClassAnalysis state) {
|
|||
out << "\n};\n\n";
|
||||
}
|
||||
|
||||
void writePropertyGetHandler(std::ofstream& out, ClassAnalysis state) {
|
||||
static void writePropertyGetHandler(std::ofstream& out, ClassAnalysis state) {
|
||||
out << "result<Data::Variant, MemberNotFound> " << state.name << "::InternalGetPropertyValue(std::string name) {";
|
||||
|
||||
out << "\n ";
|
||||
|
@ -151,7 +153,7 @@ void writePropertyGetHandler(std::ofstream& out, ClassAnalysis state) {
|
|||
out << "\n};\n\n";
|
||||
}
|
||||
|
||||
void writePropertiesList(std::ofstream& out, ClassAnalysis state) {
|
||||
static void writePropertiesList(std::ofstream& out, ClassAnalysis state) {
|
||||
out << "std::vector<std::string> " << state.name << "::InternalGetProperties() {\n";
|
||||
out << " std::vector<std::string> properties = " << state.baseClass << "::InternalGetProperties();\n";
|
||||
|
||||
|
@ -164,7 +166,7 @@ void writePropertiesList(std::ofstream& out, ClassAnalysis state) {
|
|||
out << "};\n\n";
|
||||
}
|
||||
|
||||
void writePropertyMetaHandler(std::ofstream& out, ClassAnalysis state) {
|
||||
static void writePropertyMetaHandler(std::ofstream& out, ClassAnalysis state) {
|
||||
out << "result<PropertyMeta, MemberNotFound> " << state.name << "::InternalGetPropertyMeta(std::string name) {";
|
||||
|
||||
out << "\n ";
|
||||
|
@ -204,7 +206,7 @@ void writePropertyMetaHandler(std::ofstream& out, ClassAnalysis state) {
|
|||
out << "\n};\n\n";
|
||||
}
|
||||
|
||||
void writeCodeForClass(std::ofstream& out, ClassAnalysis& state) {
|
||||
void object::writeCodeForClass(std::ofstream& out, ClassAnalysis& state) {
|
||||
std::string strFlags;
|
||||
if (state.flags & ClassFlag_NotCreatable)
|
||||
strFlags += " | INSTANCE_NOTCREATABLE";
|
|
@ -3,4 +3,8 @@
|
|||
#include "analysis.h"
|
||||
#include <fstream>
|
||||
|
||||
void writeCodeForClass(std::ofstream& out, ClassAnalysis& state);
|
||||
namespace object {
|
||||
|
||||
void writeCodeForClass(std::ofstream& out, ClassAnalysis& state);
|
||||
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
#include "util.h"
|
||||
#include <clang-c/CXString.h>
|
||||
#include <optional>
|
||||
|
||||
static CXChildVisitResult _visitorFunc(CXCursor cursor, CXCursor parent, CXClientData client_data) {
|
||||
X_CXCursorVisitor* func = (X_CXCursorVisitor*)client_data;
|
||||
|
@ -14,4 +15,97 @@ std::string x_clang_toString(CXString string) {
|
|||
std::string str(clang_getCString(string));
|
||||
clang_disposeString(string);
|
||||
return str;
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> parseAnnotationString(std::string src) {
|
||||
std::map<std::string, std::string> result;
|
||||
|
||||
std::string currentIdent = "";
|
||||
std::string currentValue = "";
|
||||
int stage = 0;
|
||||
bool quoted = false;
|
||||
|
||||
int i = 0;
|
||||
for (; i < src.length(); i++) {
|
||||
if (src[i] == ' ' && (stage != 2 || !quoted)) continue; // Ignore spaces if not in stage 2 and quoted
|
||||
if (src[i] == ',' && stage == 0) continue; // Let empty commas slip by
|
||||
if (stage < 2 && (src[i] >= 'a' && src[i] <= 'z' || src[i] >= 'A' && src[i] <= 'Z' || src[i] >= '0' && src[i] <= '9' || src[i] == '_')) {
|
||||
currentIdent += src[i];
|
||||
stage = 1;
|
||||
continue;
|
||||
}
|
||||
if (stage == 1 && src[i] == '=') { // What follows is a value
|
||||
stage = 2;
|
||||
continue;
|
||||
}
|
||||
if (stage == 1 && src[i] == ',') { // Value-less key
|
||||
stage = 0;
|
||||
result[currentIdent] = "";
|
||||
currentIdent = "";
|
||||
continue;
|
||||
}
|
||||
if (stage == 2 && quoted && src[i] == '"') { // Close a quoted string
|
||||
quoted = false;
|
||||
continue;
|
||||
}
|
||||
if (stage == 2 && !quoted && src[i] == '"') { // Start a quoted string
|
||||
quoted = true;
|
||||
continue;
|
||||
}
|
||||
if (stage == 2 && !quoted && (src[i] == ' ' || src[i] == ',')) { // Terminate the string
|
||||
stage = 0;
|
||||
result[currentIdent] = currentValue;
|
||||
currentIdent = "";
|
||||
currentValue = "";
|
||||
continue;
|
||||
}
|
||||
if (stage == 2) { // Otherwise if in stage 2, simply add the character
|
||||
currentValue += src[i];
|
||||
continue;
|
||||
}
|
||||
fprintf(stderr, "Unexpected symbol: %c at index %d\n", src[i], i);
|
||||
fprintf(stderr, "\t%s\n", src.c_str());
|
||||
fprintf(stderr, "\t%s^\n", i > 0 ? std::string(i, '~').c_str() : "");
|
||||
abort();
|
||||
}
|
||||
|
||||
// Add the remaining value
|
||||
if (stage == 1) {
|
||||
result[currentIdent] = "";
|
||||
} else if (stage == 2) {
|
||||
result[currentIdent] = currentValue;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::optional<std::string> findAnnotation(CXCursor cur, std::string annotationName) {
|
||||
std::optional<std::string> ret = std::nullopt;
|
||||
|
||||
x_clang_visitChildren(cur, [&](CXCursor cur, CXCursor parent) {
|
||||
CXCursorKind kind = clang_getCursorKind(cur);
|
||||
if (kind != CXCursor_AnnotateAttr) return CXChildVisit_Continue;
|
||||
|
||||
std::string annString = x_clang_toString(clang_getCursorDisplayName(cur));
|
||||
if (annString != annotationName) return CXChildVisit_Continue;
|
||||
|
||||
// Look inside for a StringLiteral
|
||||
|
||||
x_clang_visitChildren(cur, [&](CXCursor cur, CXCursor parent) {
|
||||
CXCursorKind kind = clang_getCursorKind(cur);
|
||||
// if (kind != CXCursor_StringLiteral) return CXChildVisit_Recurse;
|
||||
// String literals cannot be parsed as CXCursor_StringLiteral. I don't know why.
|
||||
if (kind != CXCursor_UnexposedExpr) return CXChildVisit_Recurse;
|
||||
|
||||
// https://stackoverflow.com/a/63859988/16255372
|
||||
auto res = clang_Cursor_Evaluate(cur);
|
||||
ret = clang_EvalResult_getAsStr(res);
|
||||
clang_EvalResult_dispose(res);
|
||||
|
||||
return CXChildVisit_Break;
|
||||
});
|
||||
|
||||
return CXChildVisit_Break;
|
||||
});
|
||||
return ret;
|
||||
}
|
|
@ -2,10 +2,21 @@
|
|||
|
||||
#include <clang-c/Index.h>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
typedef std::function<CXChildVisitResult(CXCursor cursor, CXCursor parent)> X_CXCursorVisitor;
|
||||
|
||||
unsigned x_clang_visitChildren(CXCursor parent, X_CXCursorVisitor visitor);
|
||||
|
||||
std::string x_clang_toString(CXString string);
|
||||
std::string x_clang_toString(CXString string);
|
||||
|
||||
// Very simple parser
|
||||
// Example format:
|
||||
// name="Hello!", world=Test, read_only
|
||||
// Result:
|
||||
// "name": "Hello!", "world": "Test", "read_only": ""
|
||||
std::map<std::string, std::string> parseAnnotationString(std::string src);
|
||||
|
||||
std::optional<std::string> findAnnotation(CXCursor cur, std::string annotationName);
|
|
@ -16,18 +16,18 @@ find_package(PkgConfig REQUIRED)
|
|||
pkg_check_modules(LUAJIT REQUIRED luajit)
|
||||
|
||||
# Run autogen
|
||||
file(GLOB_RECURSE AUTOGEN_SOURCES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/src/objects" "src/objects/*.h")
|
||||
file(GLOB_RECURSE AUTOGEN_SOURCES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/src" "src/objects/*.h" "src/datatypes/*.h")
|
||||
|
||||
# https://cmake.org/cmake/help/book/mastering-cmake/chapter/Custom%20Commands.html
|
||||
foreach (SRC ${AUTOGEN_SOURCES})
|
||||
string(REGEX REPLACE "[.]h$" ".cpp" OUT_SRC_NAME ${SRC})
|
||||
set(SRC_PATH "${CMAKE_CURRENT_SOURCE_DIR}/src/objects/${SRC}")
|
||||
set(SRC_PATH "${CMAKE_CURRENT_SOURCE_DIR}/src/${SRC}")
|
||||
set(OUT_PATH "${CMAKE_BINARY_DIR}/generated/${OUT_SRC_NAME}")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${OUT_PATH}"
|
||||
DEPENDS "${SRC_PATH}"
|
||||
COMMAND "${CMAKE_BINARY_DIR}/autogen/autogen" "${CMAKE_CURRENT_SOURCE_DIR}/src" "${SRC_PATH}" "${OUT_PATH}"
|
||||
COMMAND "${CMAKE_BINARY_DIR}/autogen/autogen" "object" "${CMAKE_CURRENT_SOURCE_DIR}/src" "${SRC_PATH}" "${OUT_PATH}"
|
||||
)
|
||||
|
||||
list(APPEND AUTOGEN_OUTS "${OUT_PATH}")
|
||||
|
|
26
core/src/datatypes/annotation.h
Normal file
26
core/src/datatypes/annotation.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
// Markers for the autogen engine to generate getters, setters, lua, etc.
|
||||
|
||||
// Base macros
|
||||
#ifdef __AUTOGEN__
|
||||
#define def_data(...) clang::annotate("OB::def_data", #__VA_ARGS__)
|
||||
#define def_data_prop(...) clang::annotate("OB::def_data_prop", #__VA_ARGS__)
|
||||
#define def_data_method(...) clang::annotate("OB::def_data_method", #__VA_ARGS__)
|
||||
#else
|
||||
#define def_data(...)
|
||||
#define def_data_prop(...)
|
||||
#define def_data_method(...)
|
||||
#endif
|
||||
|
||||
// Helper macros
|
||||
#define DEF_DATA [[ def_data() ]]
|
||||
#define DEF_DATA_PROP [[ def_data_prop() ]]
|
||||
#define DEF_DATA_METHOD [[ def_data_method() ]]
|
||||
|
||||
#define AUTOGEN_PREAMBLE_DATA \
|
||||
public: \
|
||||
virtual const TypeInfo& GetType() const override; \
|
||||
static const TypeInfo TYPE; \
|
||||
virtual void PushLuaValue(lua_State*) const override; \
|
||||
private:
|
Loading…
Add table
Reference in a new issue