From 203b60cf656d00f39a63c09d7d12bda644ce8c6b Mon Sep 17 00:00:00 2001 From: laentropia Date: Tue, 26 May 2026 13:52:28 -0600 Subject: [PATCH] refactor: xmake is now in use --- .gitignore | 6 ++ CMakeLists.txt | 97 ---------------------------- include/{arena.h => lae_arena.h} | 6 +- src/{arena.c => lae_arena.c} | 95 +++++++++++++-------------- src/main.c | 2 +- test/CMakeLists.txt | 107 ------------------------------- test/test_arena.c | 2 +- xmake.lua | 87 +++++++++++++++++++++++++ 8 files changed, 142 insertions(+), 260 deletions(-) delete mode 100644 CMakeLists.txt rename include/{arena.h => lae_arena.h} (96%) rename src/{arena.c => lae_arena.c} (60%) delete mode 100644 test/CMakeLists.txt create mode 100644 xmake.lua diff --git a/.gitignore b/.gitignore index 0bd57ed..d1a83ec 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,12 @@ out/ out/Debug/ out/Release/ +# xmake +xmake/ +xmake/* +.xmake +.xmake/* + # Cmake files CMakeCache.txt CMakeFiles/ diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index b350ff7..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,97 +0,0 @@ -cmake_minimum_required(VERSION 3.20) -project( - arena - VERSION 1.0 - LANGUAGES C) - -# ------------------------------------------------ -# C standard — no compiler extensions -# ------------------------------------------------ -set(CMAKE_C_STANDARD 11) -set(CMAKE_C_STANDARD_REQUIRED ON) -set(CMAKE_C_EXTENSIONS OFF) - -# Export compile_commands.json (clangd / IDEs) -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) - -# ------------------------------------------------ -# Is this the root project or embedded (CPM / FetchContent)? -# ------------------------------------------------ -if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) - set(ARENA_IS_TOP_LEVEL ON) -else() - set(ARENA_IS_TOP_LEVEL OFF) -endif() - -# ------------------------------------------------ -# Options -# ------------------------------------------------ -option(ARENA_BUILD_TESTS "Build arena tests" ${ARENA_IS_TOP_LEVEL}) -option(ARENA_BUILD_EXAMPLE "Build arena example" ${ARENA_IS_TOP_LEVEL}) -option(ARENA_ENABLE_INSTALL "Install arena" ${ARENA_IS_TOP_LEVEL}) -option(ARENA_ENABLE_SANITIZERS "Enable Address Sanitizer in tests" ON) - -# ------------------------------------------------ -# Portable warning flags -# ------------------------------------------------ -if(MSVC) - set(ARENA_WARNING_FLAGS /W4) -else() - set(ARENA_WARNING_FLAGS -Wall -Wextra -Wpedantic) -endif() - -# ================================================================ -# LIBRARY -# ================================================================ -add_library(arena src/arena.c) - -# Namespaced alias → consumers can write arena::arena -add_library(arena::arena ALIAS arena) - -target_include_directories( - arena PUBLIC $ - $) - -# Propagate C11 requirement to consumers -target_compile_features(arena PUBLIC c_std_11) - -# Warnings only for the lib itself, not propagated -target_compile_options(arena PRIVATE ${ARENA_WARNING_FLAGS}) - -# ================================================================ -# EXAMPLE (optional, only when top-level) -# ================================================================ -if(ARENA_BUILD_EXAMPLE) - add_executable(arena_example src/main.c) - target_link_libraries(arena_example PRIVATE arena) -endif() - -# ================================================================ -# TESTS -# ================================================================ -if(ARENA_BUILD_TESTS) - enable_testing() - add_subdirectory(test) -endif() - -# ================================================================ -# INSTALL -# ================================================================ -if(ARENA_ENABLE_INSTALL) - include(GNUInstallDirs) - - install( - TARGETS arena - EXPORT arenaTargets - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) - - install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) - - install( - EXPORT arenaTargets - FILE arenaTargets.cmake - NAMESPACE arena:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/arena) -endif() diff --git a/include/arena.h b/include/lae_arena.h similarity index 96% rename from include/arena.h rename to include/lae_arena.h index a9a03fe..8a9f786 100644 --- a/include/arena.h +++ b/include/lae_arena.h @@ -1,5 +1,5 @@ -#ifndef ARENA_H -#define ARENA_H +#ifndef LAE_ARENA_H +#define LAE_ARENA_H #include #include @@ -61,4 +61,4 @@ ArenaSizeResult arena_get_align_padding(Arena* arena, size_t alignment); // I shouldn't cover. ArenaErr arena_ensure_capacity(Arena* arena, size_t size, size_t alignment); -#endif // !ARENA_H +#endif // !RENA_H diff --git a/src/arena.c b/src/lae_arena.c similarity index 60% rename from src/arena.c rename to src/lae_arena.c index 7d7c34d..4ea4bbc 100644 --- a/src/arena.c +++ b/src/lae_arena.c @@ -1,4 +1,4 @@ -#include "arena.h" +#include "lae_arena.h" #include #include #include @@ -6,13 +6,12 @@ #include struct Arena { - uint8_t *buffer; - size_t capacity; - size_t offset; + uint8_t* buffer; + size_t capacity; + size_t offset; }; - -ArenaErr arena_init(Arena **arena, size_t capacity) { +ArenaErr arena_init(Arena** arena, size_t capacity) { if (arena == NULL) { return ARENA_NULL_ARG; } @@ -21,20 +20,20 @@ ArenaErr arena_init(Arena **arena, size_t capacity) { return ARENA_INVALID_SIZE; } - Arena *new_arena = malloc(sizeof(Arena)); + Arena* new_arena = malloc(sizeof(Arena)); if (new_arena == NULL) { return ARENA_BAD_ALLOC; } - void *buffer = malloc(capacity); + void* buffer = malloc(capacity); if (buffer == NULL) { return ARENA_BAD_ALLOC; } - *new_arena = (Arena) { - .buffer = buffer, + *new_arena = (Arena){ + .buffer = buffer, .capacity = capacity, - .offset = 0, + .offset = 0, }; *arena = new_arena; @@ -42,14 +41,14 @@ ArenaErr arena_init(Arena **arena, size_t capacity) { return ARENA_OK; } -ArenaErr arena_destroy(Arena **arena) { +ArenaErr arena_destroy(Arena** arena) { if (arena == NULL || *arena == NULL) { return ARENA_NULL_ARG; } free((*arena)->buffer); - (*arena)->buffer = NULL; - (*arena)->offset = 0; + (*arena)->buffer = NULL; + (*arena)->offset = 0; (*arena)->capacity = 0; free(*arena); *arena = NULL; @@ -57,44 +56,47 @@ ArenaErr arena_destroy(Arena **arena) { return ARENA_OK; } -ArenaPointer arena_alloc(Arena *arena, size_t size, size_t alignment) { +ArenaPointer arena_alloc(Arena* arena, size_t size, size_t alignment) { if (arena == NULL) { - return (ArenaPointer) {.is_valid = false, .err = ARENA_NULL_ARG}; + return (ArenaPointer){.is_valid = false, .err = ARENA_NULL_ARG}; } if (size < 1) { - return (ArenaPointer) {.is_valid = false, .err = ARENA_INVALID_SIZE}; + return (ArenaPointer){.is_valid = false, .err = ARENA_INVALID_SIZE}; } if (alignment < 1) { - return (ArenaPointer) {.is_valid = false, .err = ARENA_INVALID_ALIGN}; + return (ArenaPointer){.is_valid = false, .err = ARENA_INVALID_ALIGN}; } ArenaSizeResult padding = arena_get_align_padding(arena, alignment); if (!padding.is_valid) { - return (ArenaPointer) {.is_valid = false, .err = padding.err}; + return (ArenaPointer){.is_valid = false, .err = padding.err}; } ArenaErr cap_err = arena_ensure_capacity(arena, size, alignment); - if(cap_err != ARENA_OK) { - return (ArenaPointer) {.is_valid = false, .err = ARENA_OUT_OF_SPACE}; + if (cap_err != ARENA_OK) { + return (ArenaPointer){.is_valid = false, .err = ARENA_OUT_OF_SPACE}; } if (arena->offset + padding.val + size > arena->capacity) { - return (ArenaPointer) {.is_valid = false, .err = ARENA_OUT_OF_SPACE}; + return (ArenaPointer){.is_valid = false, .err = ARENA_OUT_OF_SPACE}; } if (arena->offset > SIZE_MAX - padding.val - size) { - return (ArenaPointer) {.is_valid = false, .err = ARENA_CAPACITY_OVERFLOW}; + return (ArenaPointer){.is_valid = false, + .err = ARENA_CAPACITY_OVERFLOW}; } size_t aligned_offset = arena->offset + padding.val; arena->offset = aligned_offset + size; - return (ArenaPointer) {.is_valid = true, .offset = aligned_offset, .arena = arena}; + return (ArenaPointer){.is_valid = true, + .offset = aligned_offset, + .arena = arena}; } -ArenaErr arena_ensure_capacity(Arena *arena, size_t size, size_t alignment) { +ArenaErr arena_ensure_capacity(Arena* arena, size_t size, size_t alignment) { if (arena == NULL) { return ARENA_NULL_ARG; } @@ -150,38 +152,36 @@ ArenaErr arena_ensure_capacity(Arena *arena, size_t size, size_t alignment) { } } -ArenaPointer arena_push(Arena *arena, void *data, size_t size, size_t alignment) { +ArenaPointer +arena_push(Arena* arena, void* data, size_t size, size_t alignment) { if (arena == NULL || data == NULL) { - return (ArenaPointer) {.is_valid = false, .err = ARENA_NULL_ARG}; + return (ArenaPointer){.is_valid = false, .err = ARENA_NULL_ARG}; } if (size < 1) { - return (ArenaPointer) {.is_valid = false, .err = ARENA_INVALID_SIZE}; + return (ArenaPointer){.is_valid = false, .err = ARENA_INVALID_SIZE}; } if (size < 1) { - return (ArenaPointer) {.is_valid = false, .err = ARENA_INVALID_ALIGN}; + return (ArenaPointer){.is_valid = false, .err = ARENA_INVALID_ALIGN}; } ArenaErr err = arena_ensure_capacity(arena, size, alignment); if (err != ARENA_OK) { - return (ArenaPointer) {.is_valid = false, .err = err}; + return (ArenaPointer){.is_valid = false, .err = err}; } ArenaPointer pointer = arena_alloc(arena, size, alignment); if (!pointer.is_valid) { return pointer; } - - memcpy( - arena_unwrap_pointer(pointer), - data, - size); + + memcpy(arena_unwrap_pointer(pointer), data, size); return pointer; } -ArenaErr arena_realloc(Arena *arena, size_t new_capacity) { +ArenaErr arena_realloc(Arena* arena, size_t new_capacity) { if (arena == NULL) { return ARENA_NULL_ARG; } @@ -190,43 +190,36 @@ ArenaErr arena_realloc(Arena *arena, size_t new_capacity) { return ARENA_INVALID_SIZE; } - uint8_t *tmp = realloc(arena->buffer, new_capacity); + uint8_t* tmp = realloc(arena->buffer, new_capacity); if (tmp == NULL) { return ARENA_BAD_ALLOC; } - arena->buffer = tmp; + arena->buffer = tmp; arena->capacity = new_capacity; return ARENA_OK; } - - -ArenaSizeResult arena_get_align_padding(Arena *arena, size_t alignment) { +ArenaSizeResult arena_get_align_padding(Arena* arena, size_t alignment) { if (arena == NULL) { - return (ArenaSizeResult){ .is_valid = false, .err = ARENA_NULL_ARG }; + return (ArenaSizeResult){.is_valid = false, .err = ARENA_NULL_ARG}; } if (alignment == 0 || (alignment & (alignment - 1)) != 0) { - return (ArenaSizeResult){ .is_valid = false, .err = ARENA_INVALID_ALIGN }; + return (ArenaSizeResult){.is_valid = false, .err = ARENA_INVALID_ALIGN}; } uintptr_t current_address = (uintptr_t)(arena->buffer + arena->offset); - size_t mask = alignment - 1; + size_t mask = alignment - 1; size_t padding = (size_t)(-current_address) & mask; - return (ArenaSizeResult){ - .is_valid = true, - .val = padding - }; + return (ArenaSizeResult){.is_valid = true, .val = padding}; } -void *arena_unwrap_pointer(ArenaPointer p) { +void* arena_unwrap_pointer(ArenaPointer p) { if (!p.is_valid) { return NULL; } return p.arena->buffer + p.offset; } - - diff --git a/src/main.c b/src/main.c index 02a75d8..c5bc80b 100644 --- a/src/main.c +++ b/src/main.c @@ -1,4 +1,4 @@ -#include "arena.h" +#include "lae_arena.h" #include int main(void) { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt deleted file mode 100644 index 94b0088..0000000 --- a/test/CMakeLists.txt +++ /dev/null @@ -1,107 +0,0 @@ -# ================================================================ -# FIND CMOCKA (system → FetchContent as fallback) -# ================================================================ -find_package(cmocka QUIET) - -if(NOT cmocka_FOUND) - message( - STATUS "[arena] cmocka not found on system — fetching with FetchContent...") - - include(FetchContent) - FetchContent_Declare( - cmocka - GIT_REPOSITORY https://git.cryptomilk.org/projects/cmocka.git - GIT_TAG cmocka-1.1.7 - GIT_SHALLOW TRUE) - - # Static lib only, no cmocka examples or self-tests - set(WITH_STATIC_LIB - ON - CACHE BOOL "" FORCE) - set(WITH_SHARED_LIB - OFF - CACHE BOOL "" FORCE) - set(WITH_CMOCKERY_SUPPORT - OFF - CACHE BOOL "" FORCE) - set(WITH_EXAMPLES - OFF - CACHE BOOL "" FORCE) - set(UNIT_TESTING - OFF - CACHE BOOL "" FORCE) - set(PICKY_DEVELOPER - OFF - CACHE BOOL "" FORCE) - - FetchContent_MakeAvailable(cmocka) - - # Normalize the target name (varies across cmocka versions) - if(NOT TARGET cmocka::cmocka) - if(TARGET cmocka-static) - add_library(cmocka::cmocka ALIAS cmocka-static) - elseif(TARGET cmocka) - add_library(cmocka::cmocka ALIAS cmocka) - else() - message( - WARNING - "[arena] Could not create cmocka::cmocka target — skipping tests.") - return() - endif() - endif() -endif() - -# ================================================================ -# DETECT ADDRESS SANITIZER SUPPORT -# ================================================================ -set(ARENA_USE_ASAN OFF) - -if(ARENA_ENABLE_SANITIZERS) - if(MSVC) - if(MSVC_VERSION GREATER_EQUAL 1928) - set(ARENA_USE_ASAN ON) - else() - message(STATUS "[arena] MSVC < 16.9: ASAN not available.") - endif() - elseif(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang" AND NOT WIN32) - include(CheckCCompilerFlag) - check_c_compiler_flag(-fsanitize=address ARENA_COMPILER_HAS_ASAN) - if(ARENA_COMPILER_HAS_ASAN) - set(ARENA_USE_ASAN ON) - else() - message(STATUS "[arena] Compiler does not support -fsanitize=address.") - endif() - else() - message(STATUS "[arena] Unknown platform/compiler — ASAN skipped.") - endif() - - if(ARENA_USE_ASAN) - message(STATUS "[arena] Address Sanitizer enabled.") - endif() -endif() - -# ================================================================ -# TEST EXECUTABLE -# ================================================================ -add_executable(test_arena test_arena.c) - -target_link_libraries(test_arena PRIVATE arena cmocka::cmocka) - -target_compile_features(test_arena PRIVATE c_std_11) - -# Apply ASAN flags per compiler -if(ARENA_USE_ASAN) - if(MSVC) - target_compile_options(test_arena PRIVATE /fsanitize=address) - else() - target_compile_options(test_arena PRIVATE -fsanitize=address - -fno-omit-frame-pointer) - target_link_options(test_arena PRIVATE -fsanitize=address) - endif() -endif() - -# ================================================================ -# CTEST REGISTRATION -# ================================================================ -add_test(NAME arena_tests COMMAND test_arena) -set_tests_properties(arena_tests PROPERTIES TIMEOUT 30) diff --git a/test/test_arena.c b/test/test_arena.c index 756b524..1d86f8b 100644 --- a/test/test_arena.c +++ b/test/test_arena.c @@ -9,7 +9,7 @@ #include #include -#include "arena.h" +#include "lae_arena.h" static void test_push_3_ints(void **state) { (void) state; diff --git a/xmake.lua b/xmake.lua new file mode 100644 index 0000000..0f0c677 --- /dev/null +++ b/xmake.lua @@ -0,0 +1,87 @@ +set_project("lae_arena") +set_version("1.0.0") + +set_languages("c11") + +add_rules("mode.debug", "mode.release") + +-- clang compile commands +add_rules("plugin.compile_commands.autoupdate") + +-- ========================================================= +-- Options +-- ========================================================= + +option("tests") +set_default(false) +set_showmenu(true) +option_end() + +option("example") +set_default(false) +set_showmenu(true) +option_end() + +option("asan") +set_default(false) +set_showmenu(true) +option_end() + +-- ========================================================= +-- Packages +-- ========================================================= + +add_requires("cmocka", { optional = true }) -- For tests + +-- ========================================================= +-- Library +-- ========================================================= + +target("lae_arena") +set_kind("static") + +add_files("src/lae_arena.c") + +add_headerfiles("include/*.h") + +add_includedirs("include", { public = true }) + +if is_mode("debug") then + add_cflags("-Wall", "-Wextra", "-Wpedantic") +end + +-- ========================================================= +-- Example executable +-- ========================================================= + +if has_config("example") then + target("example") + set_kind("binary") + + add_files("src/main.c") + + add_deps("lae_arena") +end + +-- ========================================================= +-- Tests +-- ========================================================= + +if has_config("tests") then + target("test_arena") + set_kind("binary") + + add_files("test/test_arena.c") + + add_deps("lae_arena") + + add_packages("cmocka") + + add_tests("default") + + if has_config("asan") then + add_cflags("-fsanitize=address", "-fno-omit-frame-pointer", { force = true }) + + add_ldflags("-fsanitize=address", { force = true }) + end +end