From a1ad592d31a14c674b9e44ab5fe1fe1358d03707 Mon Sep 17 00:00:00 2001 From: Marcos Magueta Date: Tue, 19 May 2026 00:31:13 -0300 Subject: CI: Fix windows build with API annotations --- CMakeLists.txt | 65 ++++++++++++---------------------- include/CursorManager.h | 2 +- include/HandlerManager.h | 2 +- include/IdentityManager.h | 2 +- include/InMemoryBackend.h | 2 +- include/LifecycleManager.h | 2 +- include/NamespaceReferenceManager.h | 2 +- include/ObjectManager.h | 4 +-- include/PermissionsManager.h | 2 +- include/RNT_C_API.h | 70 +++++++++++++++++++------------------ include/Runtime.h | 2 +- include/SqliteBackend.h | 2 +- include/VM.h | 6 ++-- src/MultigroupCodec.cpp | 8 ++++- test/MultigroupCodec.cpp | 2 +- 15 files changed, 81 insertions(+), 92 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d4af6cb..20f5244 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,4 @@ -# CMakeList.txt : CMake project for RelationalNT, include source and define -# project specific logic here. -# -cmake_minimum_required (VERSION 3.10) +cmake_minimum_required (VERSION 3.16) # Enable Hot Reload for MSVC compilers if supported. if (POLICY CMP0141) @@ -11,13 +8,16 @@ endif() project ("RelationalNT") +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +option(RNT_UNITY_BUILD "Enable unity (jumbo) builds for faster compilation" ON) + find_package(unofficial-sqlite3 CONFIG REQUIRED) find_path(PICOSHA2_INCLUDE_DIRS "picosha2.h") find_package(Catch2 3 REQUIRED) -# Add source to this project's executable. -add_executable (RelationalNT - "src/RelationalNT.cpp" +add_library(rnt_core OBJECT "src/ObjectManager.cpp" "src/PermissionsManager.cpp" "src/IdentityManager.cpp" @@ -28,38 +28,25 @@ add_executable (RelationalNT "src/TupleCodec.cpp" "src/MultigroupCodec.cpp" "src/InMemoryBackend.cpp" - "src/SqliteBackend.cpp" "src/NamespaceReferenceManager.cpp" "src/VM.cpp" ) +target_include_directories(rnt_core PUBLIC "include" ${PICOSHA2_INCLUDE_DIRS}) +set_target_properties(rnt_core PROPERTIES + POSITION_INDEPENDENT_CODE ON + UNITY_BUILD ${RNT_UNITY_BUILD} +) -target_include_directories(RelationalNT PRIVATE "include") +add_executable (RelationalNT + "src/RelationalNT.cpp" + "src/SqliteBackend.cpp" +) +target_link_libraries(RelationalNT PRIVATE rnt_core unofficial::sqlite3::sqlite3) target_compile_definitions(RelationalNT PRIVATE NT_CONSOLE_APP) - -if (CMAKE_VERSION VERSION_GREATER 3.12) - set_property(TARGET RelationalNT PROPERTY CXX_STANDARD 20) -endif() - -target_link_libraries(RelationalNT PRIVATE unofficial::sqlite3::sqlite3) -target_include_directories(RelationalNT PRIVATE ${PICOSHA2_INCLUDE_DIRS}) +set_target_properties(RelationalNT PROPERTIES UNITY_BUILD ${RNT_UNITY_BUILD}) enable_testing() -set(RNT_CORE_SOURCES - "src/ObjectManager.cpp" - "src/PermissionsManager.cpp" - "src/IdentityManager.cpp" - "src/LifecycleManager.cpp" - "src/HandlerManager.cpp" - "src/CursorManager.cpp" - "src/Merkle.cpp" - "src/TupleCodec.cpp" - "src/MultigroupCodec.cpp" - "src/InMemoryBackend.cpp" - "src/NamespaceReferenceManager.cpp" - "src/VM.cpp" -) - add_executable(RNT_tests "test/VM.cpp" "test/MultigroupCodec.cpp" @@ -67,13 +54,11 @@ add_executable(RNT_tests "test/NamespaceReferenceManager.cpp" "test/LifecycleManager.cpp" "test/CursorManager.cpp" - ${RNT_CORE_SOURCES} ) -target_include_directories(RNT_tests PRIVATE "include") -target_include_directories(RNT_tests PRIVATE ${PICOSHA2_INCLUDE_DIRS}) +target_link_libraries(RNT_tests PRIVATE rnt_core Catch2::Catch2WithMain) target_compile_definitions(RNT_tests PRIVATE NT_CONSOLE_APP) -target_link_libraries(RNT_tests PRIVATE Catch2::Catch2WithMain) -set_property(TARGET RNT_tests PROPERTY CXX_STANDARD 20) + +set_target_properties(RNT_tests PROPERTIES UNITY_BUILD OFF) include(Catch) catch_discover_tests(RNT_tests DISCOVERY_MODE PRE_TEST) @@ -81,18 +66,14 @@ catch_discover_tests(RNT_tests DISCOVERY_MODE PRE_TEST) add_library(RNT SHARED "src/RNT_C_API.cpp" "src/SqliteBackend.cpp" - ${RNT_CORE_SOURCES} ) +target_link_libraries(RNT PRIVATE rnt_core unofficial::sqlite3::sqlite3) target_include_directories(RNT PUBLIC "include") -target_include_directories(RNT PRIVATE ${PICOSHA2_INCLUDE_DIRS}) target_compile_definitions(RNT PRIVATE NT_EXPORTS) -target_link_libraries(RNT PRIVATE unofficial::sqlite3::sqlite3) -set_property(TARGET RNT PROPERTY CXX_STANDARD 20) +set_target_properties(RNT PROPERTIES UNITY_BUILD ${RNT_UNITY_BUILD}) add_executable(RNT_capi_tests "test/C_API.cpp" ) -target_include_directories(RNT_capi_tests PRIVATE "include") target_link_libraries(RNT_capi_tests PRIVATE RNT Catch2::Catch2WithMain) -set_property(TARGET RNT_capi_tests PROPERTY CXX_STANDARD 20) catch_discover_tests(RNT_capi_tests DISCOVERY_MODE PRE_TEST) diff --git a/include/CursorManager.h b/include/CursorManager.h index c2606c3..2743516 100644 --- a/include/CursorManager.h +++ b/include/CursorManager.h @@ -34,7 +34,7 @@ namespace nt * Merkle::Page(backend, merkle_root, fetch_offset, PAGE_SIZE) to retrieve * the next page of tuple hashes without loading sibling subtrees. */ - class NT_API CursorManager + class CursorManager { public: static constexpr std::size_t PAGE_SIZE = 1; diff --git a/include/HandlerManager.h b/include/HandlerManager.h index 06ed362..a9ce09d 100644 --- a/include/HandlerManager.h +++ b/include/HandlerManager.h @@ -21,7 +21,7 @@ namespace nt class PermissionsManager; /** @brief Opens and closes authorized handles to registry objects. */ - class NT_API HandlerManager + class HandlerManager { public: /** diff --git a/include/IdentityManager.h b/include/IdentityManager.h index 5c8dd14..6b487a9 100644 --- a/include/IdentityManager.h +++ b/include/IdentityManager.h @@ -21,7 +21,7 @@ namespace nt * so that error logs identify the type without dereferencing the pointer. * See docs/reactos-ob-comparison.md §2. */ - class NT_API IdentityManager + class IdentityManager { public: /** diff --git a/include/InMemoryBackend.h b/include/InMemoryBackend.h index 55472a8..1a7d3a7 100644 --- a/include/InMemoryBackend.h +++ b/include/InMemoryBackend.h @@ -21,7 +21,7 @@ namespace nt { - class NT_API InMemoryBackend : public IStorageBackend + class InMemoryBackend : public IStorageBackend { public: std::string Put(std::vector value) override; diff --git a/include/LifecycleManager.h b/include/LifecycleManager.h index 5508bc6..e053cd2 100644 --- a/include/LifecycleManager.h +++ b/include/LifecycleManager.h @@ -23,7 +23,7 @@ namespace nt * Monitor / Unmonitor manage `handle_count`. Pin / Unpin manage * `reference_count`. See docs/reactos-ob-comparison.md §1. */ - class NT_API LifecycleManager + class LifecycleManager { public: /** diff --git a/include/NamespaceReferenceManager.h b/include/NamespaceReferenceManager.h index dd91297..3264271 100644 --- a/include/NamespaceReferenceManager.h +++ b/include/NamespaceReferenceManager.h @@ -67,7 +67,7 @@ namespace nt * @todo Define the batch-update API with all-or-nothing contention semantics. * See docs/reactos-ob-comparison.md §8. */ - class NT_API NamespaceReferenceManager + class NamespaceReferenceManager { public: /** diff --git a/include/ObjectManager.h b/include/ObjectManager.h index 7531079..1391508 100644 --- a/include/ObjectManager.h +++ b/include/ObjectManager.h @@ -25,7 +25,7 @@ namespace nt * the metadata needed to reason about object type, path, references, and * handles while the concrete storage model is still being designed. */ - class NT_API ObjectManager + class ObjectManager { public: /** @brief Base type for objects stored in the registry. */ @@ -224,7 +224,7 @@ namespace nt * maps `offset` to the appropriate pair via a bijective enumeration scheme * (e.g. Cantor pairing); callers must bound such scans with a TAKE node. */ - struct NT_API ephemeral_object_type : object_type + struct ephemeral_object_type : object_type { enum class Cardinality { Finite, ConstrainedFinite, AlephZero, Continuum }; diff --git a/include/PermissionsManager.h b/include/PermissionsManager.h index 6718f9f..3af75f6 100644 --- a/include/PermissionsManager.h +++ b/include/PermissionsManager.h @@ -37,7 +37,7 @@ namespace nt * rather than re-evaluating the descriptor on every call. * See docs/reactos-ob-comparison.md §4. */ - class NT_API PermissionsManager + class PermissionsManager { public: /** diff --git a/include/RNT_C_API.h b/include/RNT_C_API.h index e6455ba..707c04a 100644 --- a/include/RNT_C_API.h +++ b/include/RNT_C_API.h @@ -35,6 +35,8 @@ #include #include +#include "Api.h" + #ifdef __cplusplus extern "C" { #endif @@ -66,7 +68,7 @@ typedef void* rnt_cursor_t; * "memory". * @return 0 on success, negative on error. */ -int rnt_init(const char* driver, const char* storage_path); +NT_API int rnt_init(const char* driver, const char* storage_path); /* ------------------------------------------------------------------ */ /* Authentication */ @@ -80,7 +82,7 @@ int rnt_init(const char* driver, const char* storage_path); * Release with rnt_free_string(). NULL on error. * @return 0 on success, negative when authentication is rejected. */ -int rnt_firewall(const char* auth_method, char** claims_out); +NT_API int rnt_firewall(const char* auth_method, char** claims_out); /* ------------------------------------------------------------------ */ /* Session lifecycle */ @@ -100,7 +102,7 @@ int rnt_firewall(const char* auth_method, char** claims_out); * Release with rnt_free_string(). * @return 0 on success, negative on error. */ -int rnt_session_open(void* connection_context, char** session_hash_out); +NT_API int rnt_session_open(void* connection_context, char** session_hash_out); /** * @brief Closes a session, unregistering it from /system/sessions/. @@ -112,7 +114,7 @@ int rnt_session_open(void* connection_context, char** session_hash_out); * @param session_hash Hash returned by rnt_session_open. * @return 0 on success, negative when the hash does not match an active session. */ -int rnt_session_close(const char* session_hash); +NT_API int rnt_session_close(const char* session_hash); /** * @brief Sets a per-session override for a branch. @@ -131,9 +133,9 @@ int rnt_session_close(const char* session_hash); * @param target_hash Snapshot hash to bind, or "" to clear. * @return 0 on success, negative on error. */ -int rnt_session_set_branch(const char* session_hash, - const char* branch_name, - const char* target_hash); +NT_API int rnt_session_set_branch(const char* session_hash, + const char* branch_name, + const char* target_hash); /* ------------------------------------------------------------------ */ /* Handle lifecycle */ @@ -151,13 +153,13 @@ int rnt_session_set_branch(const char* session_hash, * @param claims Claim string returned by rnt_firewall (may be NULL). * @return Handle pointer, or NULL when the path is not found or access is denied. */ -rnt_handle_t rnt_open_handle(const char* path, const char* claims); +NT_API rnt_handle_t rnt_open_handle(const char* path, const char* claims); /** * @brief Closes a handle, running HandlerManager::Close and Unmonitor. * @return 0 on success, negative on error. */ -int rnt_close_handle(rnt_handle_t handle); +NT_API int rnt_close_handle(rnt_handle_t handle); /** * @brief Reads the current branch-tree root hash from a BRANCH object. @@ -172,7 +174,7 @@ int rnt_close_handle(rnt_handle_t handle); * (possibly empty). Release with rnt_free_string(). * @return 0 on success, negative when the handle is not a BRANCH. */ -int rnt_branch_target(rnt_handle_t handle, char** target_hash_out); +NT_API int rnt_branch_target(rnt_handle_t handle, char** target_hash_out); /** * @brief Atomically advances a branch to point at a new branch-tree root. @@ -194,7 +196,7 @@ int rnt_branch_target(rnt_handle_t handle, char** target_hash_out); * not BRANCH, or @p new_hash is non-empty but no matching blob * exists in the KV store. */ -int rnt_branch_advance(const char* branch_path, const char* new_hash); +NT_API int rnt_branch_advance(const char* branch_path, const char* new_hash); /* ------------------------------------------------------------------ */ /* Object registration */ @@ -210,7 +212,7 @@ int rnt_branch_advance(const char* branch_path, const char* new_hash); * "/system/branches//multigroups//relations/". * @return 0 on success, negative on error. */ -int rnt_register_relation(const char* path); +NT_API int rnt_register_relation(const char* path); /** * @brief Registers a BRANCH object at the given path pointing at a branch-tree root. @@ -226,7 +228,7 @@ int rnt_register_relation(const char* path); * or "" for unborn). * @return 0 on success, negative on error. */ -int rnt_register_branch(const char* path, const char* target_hash); +NT_API int rnt_register_branch(const char* path, const char* target_hash); /** * @brief Lists all relations of a specific multigroup under a branch. @@ -243,7 +245,7 @@ int rnt_register_branch(const char* path, const char* target_hash); * @return 0 on success, negative when the path shape is wrong or the branch * is not found. */ -int rnt_list_relations(const char* branch_mg_path, char** out); +NT_API int rnt_list_relations(const char* branch_mg_path, char** out); /** * @brief Lists all multigroups bound to a branch. @@ -256,7 +258,7 @@ int rnt_list_relations(const char* branch_mg_path, char** out); * @param out Heap-allocated string; release with rnt_free_string(). * @return 0 on success, negative when the branch is not found. */ -int rnt_list_branch_multigroups(const char* branch_path, char** out); +NT_API int rnt_list_branch_multigroups(const char* branch_path, char** out); /** * @brief Lists all relations stored in a specific snapshot. @@ -270,7 +272,7 @@ int rnt_list_branch_multigroups(const char* branch_path, char** out); * @param out Set to heap-allocated string. Release with rnt_free_string(). * @return 0 on success, negative when the snapshot is not registered. */ -int rnt_list_snapshot_relations(const char* snapshot_hash, char** out); +NT_API int rnt_list_snapshot_relations(const char* snapshot_hash, char** out); /* ------------------------------------------------------------------ */ /* Tuple storage */ @@ -290,9 +292,9 @@ int rnt_list_snapshot_relations(const char* snapshot_hash, char** out); * Release with rnt_free_string(). NULL on error. * @return 0 on success, negative on error. */ -int rnt_link_tuple(const char* relation_path, - const char* kv_attrs, - char** hash_out); +NT_API int rnt_link_tuple(const char* relation_path, + const char* kv_attrs, + char** hash_out); /** * @brief Removes a tuple from the relation's Merkle tree and tuple store. @@ -306,7 +308,7 @@ int rnt_link_tuple(const char* relation_path, * @param tuple_hash 64-character hex SHA-256 of the tuple to remove. * @return 0 on success, negative when the relation is not found. */ -int rnt_unlink_tuple(const char* relation_path, const char* tuple_hash); +NT_API int rnt_unlink_tuple(const char* relation_path, const char* tuple_hash); /** * @brief Resets a relation's Merkle root to the empty-tree state. @@ -318,7 +320,7 @@ int rnt_unlink_tuple(const char* relation_path, const char* tuple_hash); * @param relation_path Slash-separated relation path. * @return 0 on success, negative when the relation is not found. */ -int rnt_clear_relation(const char* relation_path); +NT_API int rnt_clear_relation(const char* relation_path); /** * @brief Returns the current Merkle root hash for a relation. @@ -333,7 +335,7 @@ int rnt_clear_relation(const char* relation_path); * Release with rnt_free_string(). * @return 0 on success, negative when the relation is not found. */ -int rnt_relation_root(const char* relation_path, char** root_hash_out); +NT_API int rnt_relation_root(const char* relation_path, char** root_hash_out); /* ------------------------------------------------------------------ */ /* Cursor and VM */ @@ -349,7 +351,7 @@ int rnt_relation_root(const char* relation_path, char** root_hash_out); * @param handle Open RELATION handle. * @return Cursor pointer, or NULL on error. */ -rnt_cursor_t rnt_cursor_open(rnt_handle_t handle); +NT_API rnt_cursor_t rnt_cursor_open(rnt_handle_t handle); /** * @brief Advances the cursor and returns the next tuple as a kv string. @@ -363,13 +365,13 @@ rnt_cursor_t rnt_cursor_open(rnt_handle_t handle); * Release with rnt_free_string() when non-NULL. * @return 1 when a tuple was returned, 0 when exhausted, negative on error. */ -int rnt_cursor_next(rnt_cursor_t cursor, char** tuple_out); +NT_API int rnt_cursor_next(rnt_cursor_t cursor, char** tuple_out); /** * @brief Closes a cursor and releases its resources. * @return 0 on success, negative on error. */ -int rnt_cursor_close(rnt_cursor_t cursor); +NT_API int rnt_cursor_close(rnt_cursor_t cursor); /* ------------------------------------------------------------------ */ /* VM plan builder */ @@ -388,7 +390,7 @@ typedef void* rnt_plan_t; * "/system/branches/main/multigroups/warehouse/relations/public:users". * @return Plan node, or NULL when the relation does not exist or cannot be opened. */ -rnt_plan_t rnt_plan_scan(const char* relation_path); +NT_API rnt_plan_t rnt_plan_scan(const char* relation_path); /** * @brief Creates a nested-loop JOIN plan node. @@ -399,7 +401,7 @@ rnt_plan_t rnt_plan_scan(const char* relation_path); * * @return Plan node, or NULL on error. */ -rnt_plan_t rnt_plan_join(rnt_plan_t left, rnt_plan_t right); +NT_API rnt_plan_t rnt_plan_join(rnt_plan_t left, rnt_plan_t right); /** * @brief Creates a TAKE plan node that limits output to at most @p limit tuples. @@ -408,7 +410,7 @@ rnt_plan_t rnt_plan_join(rnt_plan_t left, rnt_plan_t right); * * @return Plan node, or NULL on error. */ -rnt_plan_t rnt_plan_take(rnt_plan_t source, size_t limit); +NT_API rnt_plan_t rnt_plan_take(rnt_plan_t source, size_t limit); /** * @brief Releases a plan that was built but not yet executed. @@ -417,7 +419,7 @@ rnt_plan_t rnt_plan_take(rnt_plan_t source, size_t limit); * nodes. Safe to call with NULL. Do NOT call after rnt_vm_execute_plan — * that function takes ownership. */ -void rnt_plan_free(rnt_plan_t plan); +NT_API void rnt_plan_free(rnt_plan_t plan); /** * @brief Executes a plan tree and returns a streaming VM cursor. @@ -428,7 +430,7 @@ void rnt_plan_free(rnt_plan_t plan); * * @return VM cursor, or NULL when the plan is NULL. */ -rnt_cursor_t rnt_vm_execute_plan(rnt_plan_t plan); +NT_API rnt_cursor_t rnt_vm_execute_plan(rnt_plan_t plan); /** * @brief Advances a VM cursor and returns the next merged tuple as a kv string. @@ -440,23 +442,23 @@ rnt_cursor_t rnt_vm_execute_plan(rnt_plan_t plan); * Release with rnt_free_string() when non-NULL. * @return 1 when a tuple was returned, 0 when exhausted, negative on error. */ -int rnt_vm_cursor_next(rnt_cursor_t vm_cursor, char** tuple_out); +NT_API int rnt_vm_cursor_next(rnt_cursor_t vm_cursor, char** tuple_out); /** * @brief Closes a VM cursor, releases all plan nodes, cursors, and handles. * @return 0 on success, negative on error. */ -int rnt_vm_cursor_close(rnt_cursor_t vm_cursor); +NT_API int rnt_vm_cursor_close(rnt_cursor_t vm_cursor); /* ------------------------------------------------------------------ */ /* Memory management */ /* ------------------------------------------------------------------ */ /** @brief Releases a string allocated by the API. Safe to call with NULL. */ -void rnt_free_string(char* s); +NT_API void rnt_free_string(char* s); /** @brief Releases a byte buffer allocated by the API. Safe to call with NULL. */ -void rnt_free_bytes(uint8_t* p); +NT_API void rnt_free_bytes(uint8_t* p); #ifdef __cplusplus } diff --git a/include/Runtime.h b/include/Runtime.h index aeac136..4abe8c7 100644 --- a/include/Runtime.h +++ b/include/Runtime.h @@ -10,7 +10,7 @@ namespace nt { /** @brief Top-level runtime object used by applications and the console entry point. */ - class NT_API NT + class NT { public: /** diff --git a/include/SqliteBackend.h b/include/SqliteBackend.h index ce4e465..e4cdf56 100644 --- a/include/SqliteBackend.h +++ b/include/SqliteBackend.h @@ -23,7 +23,7 @@ namespace nt { - class NT_API SqliteBackend : public IStorageBackend + class SqliteBackend : public IStorageBackend { public: /** diff --git a/include/VM.h b/include/VM.h index c560414..96cf493 100644 --- a/include/VM.h +++ b/include/VM.h @@ -63,7 +63,7 @@ namespace nt * (for EPHEMERAL_RELATION cursors) or ignored (for stored RELATION cursors, * which need no per-probe parameterization). */ - struct NT_API PathArg + struct PathArg { enum class Kind { Var, Const }; @@ -91,7 +91,7 @@ namespace nt * * TODO: Add PROJECT operator as the query layer grows. */ - struct NT_API PlanNode + struct PlanNode { enum class Op { SCAN, JOIN, TAKE }; @@ -134,7 +134,7 @@ namespace nt std::optional join_buffer; }; - class NT_API VM + class VM { public: // TODO: CursorManager should be injected as a shared runtime instance, diff --git a/src/MultigroupCodec.cpp b/src/MultigroupCodec.cpp index 81d305c..3deaa23 100644 --- a/src/MultigroupCodec.cpp +++ b/src/MultigroupCodec.cpp @@ -2,6 +2,8 @@ #include "Merkle.h" +#include + namespace nt::MultigroupCodec { // A relation with zero tuples reports an empty merkle_root externally. @@ -24,8 +26,12 @@ namespace nt::MultigroupCodec std::string Build(IStorageBackend& store, const std::vector& relations) { - std::string root; + std::map canonical; for (const auto& [name, root_hex] : relations) + canonical[name] = root_hex; + + std::string root; + for (const auto& [name, root_hex] : canonical) root = nt::Merkle::Insert(store, root, name, encode_payload(root_hex)); return root; diff --git a/test/MultigroupCodec.cpp b/test/MultigroupCodec.cpp index 25c8b53..c1e2509 100644 --- a/test/MultigroupCodec.cpp +++ b/test/MultigroupCodec.cpp @@ -29,7 +29,7 @@ std::string mk_root(char c, char d = '0') } // namespace -TEST_CASE("Build is order-independent — tree sorts intrinsically", +TEST_CASE("Build is order-independent - tree sorts intrinsically", "[multigroup-codec]") { nt::InMemoryBackend a, b; -- cgit v1.2.3