diff --git a/autogen/src/cache.cpp b/autogen/src/cache.cpp deleted file mode 100644 index c465ddb..0000000 --- a/autogen/src/cache.cpp +++ /dev/null @@ -1,85 +0,0 @@ -#include "cache.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace fs = std::filesystem; - -extern std::map> SUBCLASSES; -extern std::map SUPERCLASS; - -std::map LAST_MODIFIED_TIMES; - -void loadModTimes(std::string path); -void writeModTimes(std::string path); - -void loadCaches(std::string outDir) { - fs::path cacheDir = fs::path(outDir) / ".cache"; - if (!fs::exists(cacheDir)) return; - - fs::path modtimesFile = cacheDir / "modified.txt"; - if (fs::exists(modtimesFile)) - loadModTimes(modtimesFile); -} - -void flushCaches(std::string outDir) { - fs::path cacheDir = fs::path(outDir) / ".cache"; - fs::create_directories(cacheDir); - - fs::path modtimesFile = cacheDir / "modified.txt"; - writeModTimes(modtimesFile); -} - -void loadModTimes(std::string path) { - std::ifstream stream(path); - - std::string line; - while (std::getline(stream, line)) { - int pos = line.find(":"); - std::string filename = line.substr(0, pos); - std::string timestr = line.substr(pos+1); - uint64_t time = std::stoull(timestr); - LAST_MODIFIED_TIMES[filename] = time; - } - - stream.close(); -} - -void writeModTimes(std::string path) { - std::ofstream stream(path); - - for (auto& [key, time] : LAST_MODIFIED_TIMES) { - stream << key.c_str() << ":" << time << "\n"; - } - - stream.close(); -} - -bool hasFileBeenUpdated(std::string path) { - path = fs::canonical(path); - if (LAST_MODIFIED_TIMES.count(path) == 0) return true; - - // https://stackoverflow.com/a/31258680/16255372 - auto rawtime = fs::last_write_time(path); - auto rawtime_ms = std::chrono::time_point_cast(rawtime); - uint64_t time = std::chrono::duration_cast(rawtime_ms.time_since_epoch()).count(); - - uint64_t cachedTime = LAST_MODIFIED_TIMES[path]; - return time > cachedTime; -} - -void markFileCached(std::string path) { - path = fs::canonical(path); - // https://stackoverflow.com/a/31258680/16255372 - auto rawtime = fs::last_write_time(path); - auto rawtime_ms = std::chrono::time_point_cast(rawtime); - uint64_t time = std::chrono::duration_cast(rawtime_ms.time_since_epoch()).count(); - - LAST_MODIFIED_TIMES[path] = time; -} \ No newline at end of file diff --git a/autogen/src/cache.h b/autogen/src/cache.h deleted file mode 100644 index 2e10202..0000000 --- a/autogen/src/cache.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include -#include - -void loadCaches(std::string outDir); -void flushCaches(std::string outDir); - -bool hasFileBeenUpdated(std::string path); -void markFileCached(std::string path); \ No newline at end of file diff --git a/autogen/src/main.cpp b/autogen/src/main.cpp index 9bf0475..82adfa0 100644 --- a/autogen/src/main.cpp +++ b/autogen/src/main.cpp @@ -16,84 +16,33 @@ namespace fs = std::filesystem; int main(int argc, char** argv) { if (argc < 4) { - fprintf(stderr, "Usage: autogen \n"); + fprintf(stderr, "Usage: autogen \n"); return 1; } - loadCaches(argv[3]); - - std::vector headerFiles; - - // Scrape directory for header files - for (const fs::directory_entry& file : fs::recursive_directory_iterator(argv[2])) { - if (!file.is_regular_file()) continue; // Not a file, skip - if (file.path().extension() != ".h") continue; // Not a header file, skip - if (!hasFileBeenUpdated(file.path())) { - fs::path relpath = fs::relative(file.path(), argv[1]); - printf("[AUTOGEN] Skipping file %s...\n", relpath.c_str()); - continue; - } - markFileCached(file.path()); - - headerFiles.push_back(file.path()); - } - AnalysisState state; - // analyzeClasses("../core/src/objects/part.h", argv[1], &state); - // for (auto& [_, clazz] : state.classes) { - // printf("Class: %s\n", clazz.name.c_str()); - // if (clazz.baseClass != "") - // printf("==> Base class: %s\n", clazz.baseClass.c_str()); - // if (clazz.explorerIcon != "") - // printf("==> Explorer icon: %s\n", clazz.explorerIcon.c_str()); - // printf("==> Flags (%x): ", clazz.flags); - // if (clazz.flags & ClassFlag_Service) - // printf("INSTANCE_SERVICE "); - // if (clazz.flags & ClassFlag_NotCreatable) - // printf("INSTANCE_NOT_CREATABLE "); - // if (clazz.flags & ClassFlag_Hidden) - // printf("INSTANCE_HIDDEN"); - // printf("\n"); + fs::path srcRoot = argv[1]; + fs::path srcPath = argv[2]; + fs::path outPath = argv[3]; - // if (!clazz.properties.empty()) - // printf("==> Properties:\n"); - // for (auto prop : clazz.properties) { - // printf("====> %s (%s) (%s)\n", prop.name.c_str(), prop.fieldName.c_str(), prop.backingFieldType.c_str()); - // } - // } + fs::path relpath = fs::relative(srcPath, srcRoot); + printf("[AUTOGEN] Processing file %s...\n", relpath.c_str()); + analyzeClasses(srcPath, srcRoot, &state); - // First-pass: Analyze type hierarchy - for (std::string path : headerFiles) { - fs::path relpath = fs::relative(path, argv[1]); - printf("[AUTOGEN] Processing file %s...\n", relpath.c_str()); - analyzeClasses(path, argv[1], &state); - } + fs::create_directories(outPath.parent_path()); // Make sure generated dir exists before we try writing to it + + if (state.classes.empty()) + return 0; + + printf("[AUTOGEN] Generating file %s...\n", relpath.c_str()); + std::ofstream outStream(outPath); - printf("[AUTOGEN] Generating cpp files...\n"); - fs::create_directories(argv[3]); // Make sure generated dir exists before we try writing to it for (auto& [_, clazz] : state.classes) { - fs::path outPath = fs::path(argv[3]) / ("class_" + clazz.name + ".cpp"); - std::ofstream outStream(outPath); - writeCodeForClass(outStream, clazz); - outStream.close(); } - // // Write __all__.cpp file - // fs::path outPath = fs::path(argv[3]) / "__all__.cpp"; - // std::ofstream outStream(outPath); + outStream.close(); - // // TODO: replace these with just direct filenames that can be converted by - // // CMake itself - // for (auto& [_, clazz] : state.classes) { - // std::string includeName = "class_" + clazz.name + ".cpp"; - - // outStream << "#include \"" << includeName << "\"\n"; - // } - - // outStream.close(); - - - flushCaches(argv[3]); + return 0; } \ No newline at end of file diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index be55604..503a85a 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -16,11 +16,29 @@ find_package(PkgConfig REQUIRED) pkg_check_modules(LUAJIT REQUIRED luajit) # Run autogen -add_custom_target(build_autogen ALL - COMMAND "${CMAKE_BINARY_DIR}/autogen/autogen" "${CMAKE_CURRENT_SOURCE_DIR}/src" "${CMAKE_CURRENT_SOURCE_DIR}/src/objects" "${CMAKE_BINARY_DIR}/generated" +file(GLOB_RECURSE AUTOGEN_SOURCES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/src/objects" "src/objects/*.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(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}" + ) + + list(APPEND AUTOGEN_OUTS "${OUT_PATH}") +endforeach() + +add_custom_target(autogen_build ALL + DEPENDS ${AUTOGEN_OUTS} ) -file(GLOB_RECURSE SOURCES "src/*.cpp" "src/*.h" "${CMAKE_BINARY_DIR}/generated/__all__.cpp") +file(GLOB_RECURSE SOURCES "src/*.cpp" "src/*.h") +list(APPEND SOURCES ${AUTOGEN_OUTS}) add_library(openblocks STATIC ${SOURCES}) set_target_properties(openblocks PROPERTIES OUTPUT_NAME "openblocks") target_link_libraries(openblocks ${GLEW_LIBRARIES} ${LUAJIT_LIBRARIES} OpenGL::GL ReactPhysics3D::ReactPhysics3D pugixml::pugixml) diff --git a/core/src/objects/joint/jointinstance.h b/core/src/objects/joint/jointinstance.h index 970d29a..99d0459 100644 --- a/core/src/objects/joint/jointinstance.h +++ b/core/src/objects/joint/jointinstance.h @@ -8,7 +8,7 @@ class Part; class Workspace; -class INSTANCE_SERVICE() JointInstance : public Instance { +class INSTANCE_WITH(abstract) JointInstance : public Instance { AUTOGEN_PREAMBLE std::weak_ptr oldPart0;