diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index dd03e8d0..b8b42731 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -18,25 +18,43 @@ jobs: strategy: fail-fast: true matrix: - os: [windows-latest, ubuntu-latest, macos-latest] + # os: [windows-latest, ubuntu-latest, macos-latest] // TODO: + os: [windows-latest, ubuntu-24.04] build-variant: [Debug, Release] steps: - uses: actions/checkout@v4 # TODO: Install GCC without using a script. - - if: matrix.os == 'ubuntu-latest' + - if: matrix.os == 'ubuntu-24.04' name: Installing GCC uses: egor-tensin/setup-gcc@v1 with: - version: 12 + version: 14 - - if: matrix.os == 'ubuntu-latest' + # - if: matrix.os == 'ubuntu-24.04' + # name: Installing GCC + # run: | + # sudo apt-get install gcc-14.2.0 g++-14.2.0 + # echo "gcc=$gcc" >> $env:GITHUB_OUTPUT + # echo "gxx=$gxx" >> $env:GITHUB_OUTPUT + - if: matrix.os == 'ubuntu-24.04' + name: Setup Ninja + uses: ashutoshvarma/setup-ninja@master + with: + version: 1.12.1 + + - if: matrix.os == 'ubuntu-24.04' name: Installing Linux dependencies run: | sudo apt update sudo apt-get install -y libx11-dev libxkbcommon-x11-dev libx11-xcb-dev - - name: Configuring + - if: matrix.os == 'ubuntu-24.04' + name: Configuring + run: cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=${{matrix.build-variant}} -DCORE_BUILD_UNITY=OFF # TODO: Re-enable unity build. + + - if: matrix.os != 'ubuntu-24.04' + name: Configuring run: cmake -B build -DCMAKE_BUILD_TYPE=${{matrix.build-variant}} -DCORE_BUILD_UNITY=OFF # TODO: Re-enable unity build. - name: Building diff --git a/CMakeLists.txt b/CMakeLists.txt index d89b002a..933f4cc7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.20) +cmake_minimum_required(VERSION 3.28.2) project(core VERSION 0.0.1) @@ -18,6 +18,7 @@ set(CMAKE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/$") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/$") set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/$") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/$") +set(PREBUILT_MODULE_PATH "${CMAKE_BINARY_DIR}/bin/$") # Global compile definitions. set(GLOBAL_COMPILE_DEFINITIONS @@ -34,9 +35,11 @@ set(GLOBAL_COMPILE_DEFINITIONS $<$:PLATFORM_MACOS=1> ) +set(CMAKE_CXX_STANDARD 20) + # Global compile options. if(MSVC) - set(GLOBAL_COMPILE_OPTIONS -W4 -WX -std:c++20 -Zc:preprocessor -wd5105) + set(GLOBAL_COMPILE_OPTIONS -W4 -WX -std:c++20 -Zc:preprocessor -wd5105 -wd4273) else() # TODO: -Wno-deprecated-declarations is due to doctest.h sprintf() function. set(GLOBAL_COMPILE_OPTIONS -Wall -Wextra -pedantic -Werror -std=c++2b -fno-exceptions -Wno-invalid-offsetof -Wno-nested-anon-types -Wno-c++11-narrowing -Wno-gnu-zero-variadic-macro-arguments -Wno-deprecated-declarations -Wno-enum-constexpr-conversion -Wno-unknown-warning-option diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 298f1276..fae5a380 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -1,8 +1,6 @@ set(HEADER_FILES - base64.h defer.h defines.h - ecs.h formatter.h hash.h json.h @@ -26,8 +24,6 @@ set(HEADER_FILES ) set(SOURCE_FILES - base64.cpp - ecs.cpp formatter.cpp json.cpp log.cpp @@ -76,6 +72,18 @@ if(${CORE_BUILD_STATIC}) set(BUILD_TYPE STATIC) endif() add_library(core ${BUILD_TYPE} ${HEADER_FILES} ${SOURCE_FILES}) + +# TODO: +target_sources(core + PUBLIC + FILE_SET all_my_modules TYPE CXX_MODULES + BASE_DIRS + ${PROJECT_SOURCE_DIR} + FILES + base64.cppm + ecs.cppm +) + target_link_libraries(core PUBLIC ${LIBS}) target_compile_options(core PRIVATE ${GLOBAL_COMPILE_OPTIONS}) target_compile_definitions(core PRIVATE ${GLOBAL_COMPILE_DEFINITIONS}) diff --git a/core/base64.cpp b/core/base64.cppm similarity index 52% rename from core/base64.cpp rename to core/base64.cppm index 1dd6ef63..ad159ded 100644 --- a/core/base64.cpp +++ b/core/base64.cppm @@ -1,9 +1,23 @@ -#include "core/base64.h" +module; + +#include "core/export.h" +#include "core/defines.h" +#include "core/export.h" +#include "core/memory/memory.h" +#include "core/containers/string.h" + +export module base64; + +/* + TODO: + - [ ] Should decode return a String or an Array? + - [ ] Should use Result? +*/ inline static constexpr const char *BASE64_CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -String -base64_encode(const u8 *data, u64 size, memory::Allocator *allocator) +export CORE_API String +base64_encode(const u8 *data, u64 size, memory::Allocator *allocator = memory::heap_allocator()) { String out = string_init(allocator); @@ -30,8 +44,8 @@ base64_encode(const u8 *data, u64 size, memory::Allocator *allocator) return out; } -String -base64_decode(const String &data, memory::Allocator *allocator) +export CORE_API String +base64_decode(const String &data, memory::Allocator *allocator = memory::heap_allocator()) { constexpr auto index = [](const String &data, char c) -> u8 { for (u8 i = 0; i < data.count; ++i) @@ -81,4 +95,34 @@ base64_decode(const String &data, memory::Allocator *allocator) } return out; +} + +export inline String +base64_encode(const Block &data, memory::Allocator *allocator = memory::heap_allocator()) +{ + return base64_encode((const u8 *)data.data, data.size, allocator); +} + +export inline String +base64_encode(const Array &data, memory::Allocator *allocator = memory::heap_allocator()) +{ + return base64_encode(data.data, data.count, allocator); +} + +export inline String +base64_encode(const String &data, memory::Allocator *allocator = memory::heap_allocator()) +{ + return base64_encode((const u8 *)data.data, data.count, allocator); +} + +export inline String +base64_encode(const char *data, memory::Allocator *allocator = memory::heap_allocator()) +{ + return base64_encode(string_literal(data), allocator); +} + +export inline String +base64_decode(const char *data, memory::Allocator *allocator = memory::heap_allocator()) +{ + return base64_decode(string_literal(data), allocator); } \ No newline at end of file diff --git a/core/base64.h b/core/base64.h deleted file mode 100644 index 0d24c9d6..00000000 --- a/core/base64.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include "core/defines.h" -#include "core/export.h" -#include "core/memory/memory.h" -#include "core/containers/string.h" - -/* - TODO: - - [ ] Should decode return a String or an Array? - - [ ] Should use Result? -*/ - -CORE_API String -base64_encode(const u8 *data, u64 size, memory::Allocator *allocator = memory::heap_allocator()); - -inline static String -base64_encode(const Block &data, memory::Allocator *allocator = memory::heap_allocator()) -{ - return base64_encode((const u8 *)data.data, data.size, allocator); -} - -inline static String -base64_encode(const Array &data, memory::Allocator *allocator = memory::heap_allocator()) -{ - return base64_encode(data.data, data.count, allocator); -} - -inline static String -base64_encode(const String &data, memory::Allocator *allocator = memory::heap_allocator()) -{ - return base64_encode((const u8 *)data.data, data.count, allocator); -} - -inline static String -base64_encode(const char *data, memory::Allocator *allocator = memory::heap_allocator()) -{ - return base64_encode(string_literal(data), allocator); -} - -CORE_API String -base64_decode(const String &data, memory::Allocator *allocator = memory::heap_allocator()); - -inline static String -base64_decode(const char *data, memory::Allocator *allocator = memory::heap_allocator()) -{ - return base64_decode(string_literal(data), allocator); -} \ No newline at end of file diff --git a/core/ecs.cpp b/core/ecs.cpp deleted file mode 100644 index 8009a9a3..00000000 --- a/core/ecs.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "ecs.h" - -#include - -namespace ecs -{ - Entity - entity_new() - { - static std::atomic id = 0; - return Entity{id.fetch_add(1)}; - } -} \ No newline at end of file diff --git a/core/ecs.h b/core/ecs.cppm similarity index 86% rename from core/ecs.h rename to core/ecs.cppm index 6aa0c5dc..ab7c297d 100644 --- a/core/ecs.h +++ b/core/ecs.cppm @@ -1,4 +1,4 @@ -#pragma once +module; #include "core/export.h" #include "core/defines.h" @@ -8,10 +8,13 @@ #include #include #include +#include + +export module ecs; namespace ecs { - struct Entity + export struct Entity { u64 id = U64_MAX; @@ -28,9 +31,6 @@ namespace ecs } }; - CORE_API Entity - entity_new(); - typedef u64 Component_Hash; struct IComponent_Table @@ -121,7 +121,7 @@ namespace ecs } }; - struct ECS + export struct ECS { Hash_Table component_tables; @@ -186,13 +186,13 @@ namespace ecs } }; - inline static ECS + export inline ECS ecs_new() { return {hash_table_init()}; } - inline static void + export inline void ecs_free(ECS &self) { for (auto &[_, v] : self.component_tables) @@ -201,50 +201,59 @@ namespace ecs hash_table_deinit(self.component_tables); } - template - inline static void + export template + inline void ecs_add_table(ECS &self) { - hash_table_insert(self.component_tables, (u64)typeid(T).hash_code(), (IComponent_Table *)memory::allocate_and_call_constructor>()); + const std::type_info &info = typeid(T); + hash_table_insert(self.component_tables, (u64)info.hash_code(), (IComponent_Table *)memory::allocate_and_call_constructor>()); } - template - inline static const T * + export template + inline const T * ecs_component_read(ECS &self, Entity e) { return self.read(e); } - template - inline static T * + export template + inline T * ecs_component_write(ECS &self, Entity e) { return self.write(e); } - template - inline static void + export template + inline void ecs_component_remove(ECS &self, Entity e) { self.remove(e); } - template - inline static Array + export template + inline Array ecs_entity_list(ECS &self) { return self.list(); } // TODO: Test this. - inline static void + export inline void ecs_reload(ECS &self) { self.reload(); } + export CORE_API Entity + entity_new() + { + static std::atomic id = 0; + return Entity{id.fetch_add(1)}; + } + // TODO: Rename this to ecs_entity_remove()? - inline static void + // TODO: Should set the id of the removed entity to U64_MAX? + export inline void ecs_entity_free(ECS &self, Entity e) { self.entity_free(e); diff --git a/core/hash.h b/core/hash.h index 2c19a67e..8a1ef754 100644 --- a/core/hash.h +++ b/core/hash.h @@ -3,7 +3,7 @@ #include "core/defines.h" // 32 bit Fowler-Noll-Vo hash. -inline static u64 +inline u64 hash_fnv_x32(const void *key, u64 key_length) { const u32 p = 16777619U; @@ -22,7 +22,7 @@ hash_fnv_x32(const void *key, u64 key_length) } template -inline static u64 +inline u64 hash(const T &) { static_assert(sizeof(T) == 0, "There is no 'u64 hash(const T &)' function overload defined for this type."); @@ -30,86 +30,86 @@ hash(const T &) } template -inline static u64 +inline u64 hash(T *key) { return u64(key); }; template -inline static u64 +inline u64 hash(const T *key) { return u64(key); }; -inline static u64 +inline u64 hash(bool key) { return u64(key); } -inline static u64 +inline u64 hash(char key) { return u64(key); } -inline static u64 +inline u64 hash(i8 key) { return u64(key); } -inline static u64 +inline u64 hash(i16 key) { return u64(key); } -inline static u64 +inline u64 hash(i32 key) { return u64(key); } -inline static u64 +inline u64 hash(i64 key) { return u64(key); } -inline static u64 +inline u64 hash(u8 key) { return u64(key); } -inline static u64 +inline u64 hash(u16 key) { return u64(key); } -inline static u64 +inline u64 hash(u32 key) { return u64(key); } -inline static u64 +inline u64 hash(u64 key) { return u64(key); } -inline static u64 +inline u64 hash(f32 key) { return hash_fnv_x32(&key, sizeof(f32)); } -inline static u64 +inline u64 hash(f64 key) { return hash_fnv_x32(&key, sizeof(f64)); diff --git a/core/json.cpp b/core/json.cpp index 8ea42bd9..7e9da69b 100644 --- a/core/json.cpp +++ b/core/json.cpp @@ -2,6 +2,7 @@ #include "core/platform/platform.h" +#include #include struct JSON_Parser diff --git a/core/memory/heap_allocator.cpp b/core/memory/heap_allocator.cpp index d011e22c..7aff51c9 100644 --- a/core/memory/heap_allocator.cpp +++ b/core/memory/heap_allocator.cpp @@ -3,6 +3,7 @@ #include "core/log.h" #include "core/platform/platform.h" +#include #include #include #if DEBUG diff --git a/core/memory/memory.h b/core/memory/memory.h index 16d99294..4e26ce99 100644 --- a/core/memory/memory.h +++ b/core/memory/memory.h @@ -37,35 +37,35 @@ namespace memory CORE_API Allocator * temp_allocator(); - inline static void * + inline void * allocate(u64 size) { auto allocator = heap_allocator(); return allocator->allocate(size); } - inline static void * + inline void * allocate(Allocator *allocator, u64 size) { return allocator->allocate(size); } template - inline static T * + inline T * allocate() { return (T *)allocate(sizeof(T)); } template - inline static T * + inline T * allocate(Allocator *allocator) { return (T *)allocate(allocator, sizeof(T)); } template - inline static T * + inline T * allocate_and_call_constructor(TArgs &&...args) { T *data = allocate(); @@ -74,7 +74,7 @@ namespace memory } template - inline static T * + inline T * allocate_and_call_constructor(Allocator *allocator, TArgs &&...args) { T *data = allocate(allocator); @@ -82,7 +82,7 @@ namespace memory return data; } - inline static void * + inline void * allocate_zeroed(u64 size) { void *data = allocate(size); @@ -90,7 +90,7 @@ namespace memory return data; } - inline static void * + inline void * allocate_zeroed(Allocator *allocator, u64 size) { void *data = allocate(allocator, size); @@ -99,34 +99,34 @@ namespace memory } template - inline static T * + inline T * allocate_zeroed() { return (T *)allocate_zeroed(sizeof(T)); } template - inline static T * + inline T * allocate_zeroed(Allocator *allocator) { return (T *)allocate_zeroed(allocator, sizeof(T)); } - inline static void + inline void deallocate(void *data) { auto allocator = heap_allocator(); allocator->deallocate(data); } - inline static void + inline void deallocate(Allocator *allocator, void *data) { allocator->deallocate(data); } template - inline static void + inline void deallocate_and_call_destructor(T *data) { data->~T(); @@ -134,7 +134,7 @@ namespace memory } template - inline static void + inline void deallocate_and_call_destructor(Allocator *allocator, T *data) { data->~T(); diff --git a/core/platform/platform_linux.cpp b/core/platform/platform_linux.cpp index 248c89e9..86754593 100644 --- a/core/platform/platform_linux.cpp +++ b/core/platform/platform_linux.cpp @@ -20,6 +20,7 @@ #include #include #include +#include static char current_executable_directory[PATH_MAX] = {}; diff --git a/core/serialization/json_serializer.h b/core/serialization/json_serializer.h index 6e3b6a8d..1a018479 100644 --- a/core/serialization/json_serializer.h +++ b/core/serialization/json_serializer.h @@ -4,11 +4,12 @@ #include "core/defines.h" #include "core/json.h" #include "core/log.h" -#include "core/base64.h" #include "core/containers/array.h" #include "core/containers/string.h" #include "core/containers/hash_table.h" +import base64; + struct Json_Serializer { memory::Allocator *allocator; diff --git a/core/utils.h b/core/utils.h index aa42597e..113ed3da 100644 --- a/core/utils.h +++ b/core/utils.h @@ -2,7 +2,7 @@ #include "core/defines.h" -inline static u64 +inline u64 next_power_of_two(i32 value) { --value; diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt index abd393d9..5ac782bd 100644 --- a/unittest/CMakeLists.txt +++ b/unittest/CMakeLists.txt @@ -16,6 +16,7 @@ set(HEADER_FILES set(SOURCE_FILES src/unittest.cpp src/unittest_core.cpp + src/unittest_ecs.cpp src/unittest_containers.cpp src/unittest_platform.cpp src/unittest_reflect.cpp diff --git a/unittest/src/unittest_core.cpp b/unittest/src/unittest_core.cpp index a4aa205d..16e77981 100644 --- a/unittest/src/unittest_core.cpp +++ b/unittest/src/unittest_core.cpp @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -8,6 +7,8 @@ #include #include +import base64; + #include TEST_CASE("[CORE]: Arena_Allocator") diff --git a/unittest/src/unittest_ecs.cpp b/unittest/src/unittest_ecs.cpp new file mode 100644 index 00000000..18437027 --- /dev/null +++ b/unittest/src/unittest_ecs.cpp @@ -0,0 +1,38 @@ +#include +#include + +import ecs; + +#include + +struct Position +{ + f32 x, y; +}; + +TEST_CASE("[ECS]") +{ + ecs::ECS world = ecs::ecs_new(); + DEFER(ecs::ecs_free(world)); + + ecs::ecs_add_table(world); + + ecs::Entity entity1 = ecs::entity_new(); + DEFER(ecs::ecs_entity_free(world, entity1)); + CHECK(entity1.id == 0); + + auto *position_read = ecs::ecs_component_read(world, entity1); + CHECK(position_read == nullptr); + + auto &position1 = *ecs::ecs_component_write(world, entity1); + position1 = Position{1.0f, 1.0f}; + + position_read = ecs::ecs_component_read(world, entity1); + CHECK(position_read != nullptr); + CHECK(position_read->x == 1.0f); + CHECK(position_read->y == 1.0f); + + ecs::Entity entity2 = ecs::entity_new(); + CHECK(entity2.id == 1); + DEFER(ecs::ecs_entity_free(world, entity2)); +} \ No newline at end of file