Files
stk/CHANGELOG.md

243 lines
14 KiB
Markdown

# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [1.0.0-pre.12] - 2026-03-29
### Fixed
- `gmake.mk`: changed static library extension on Windows from `.lib` to `.a` for MinGW compatibility
- `module_loader`: use `RTLD_GLOBAL` when loading modules to correctly expose host symbols to dynamic libraries
## [1.0.0-pre.11] - 2026-03-15
### Fixed
- `gmake.mk`: `PREFIX` now defaults to `/usr` on Linux instead of `/usr/local`
## [1.0.0-pre.10] - 2026-03-14
### Fixed
- `bmake.mk`: all target and object paths now anchored with `${.CURDIR}` to fix incorrect path nesting when building from outside the project root; substitution delimiters switched to `|` to avoid conflicts with path separators; compile rules now emit `-MT`/`-MF` for correct dependency file targeting; removed stale `.-include` directives for `.d` files; release lib rules now use `${.TARGET}` consistently
- `gmake.mk`: removed `AR`/`ARFLAGS_STATIC` variables and the `ifeq`-guarded static lib rules; both debug and release static lib rules now use `ar rcs` directly, as MinGW ships `ar` and `lib.exe` was incorrect
## [1.0.0-pre.9] - 2026-03-12
### Changed
- `debug` and `release` targets now produce both a shared and static library alongside each other
- obj directories split into `shared/` and `static/` subdirs to keep `-fPIC` objects isolated
- `install` no longer depends on `release`; guards with an existence check and exits with a clear message if artifacts are missing
- `uninstall` removes static lib alongside shared lib
- `build.sh`: `install` and `uninstall` now handle privilege escalation automatically via `doas` or `sudo`; skips escalation if already root
## [1.0.0-pre.8] - 2026-03-08
### Fixed
- `stk_poll()`: stale index corruption when simultaneous load and unload events occurred in the same poll cycle. New modules were previously loaded into pre-compaction slot indices; they now always append to the compacted array via `module_count + successful_appends`, matching the `append_modules` path. The two load loops have been unified into one.
- `stk_poll()`: `cascade_indices` was a fixed-size stack array of `STK_PATH_MAX` (256) elements with no bounds check. It is now heap-allocated to `module_count` entries per iteration, eliminating the silent overflow risk.
- `stk_pending_retry()`: module array was pre-allocated to `module_count + stk_pending_count` but never shrunk when fewer entries loaded than were pending. Now calls `stk_module_realloc_memory(module_count)` after the retry loop completes.
- `stk_collect_dependents()`: missing bounds guard on the `indices` write: `(*count)++` had no check against the buffer capacity before writing. Added `capacity` parameter (passed as `module_count` from the call site) and a guard that skips the write if the capacity is reached, preventing a silent overflow.
- `stk_log_modules()`: `%lu` format specifier used with `size_t` is undefined behaviour on platforms where `unsigned long` is narrower than `size_t` (e.g. MSVC 64-bit). Fixed with an explicit `(unsigned long)` cast, preserving C89 compatibility.
## [1.0.0-pre.7] - 2026-03-07
### Fixed
- `stk_module_load()`: added missing dependency failure logging when a module is deferred to the pending queue.
## [1.0.0-pre.6] - 2026-03-07
### Changed
- `stk_poll()`: replaced per-module `stk_pending_add()` calls inside the load holes and `append_modules` loops with batch collection followed by a single `stk_pending_add_batch()` call after both loops complete.
## [1.0.0-pre.5] - 2026-03-07
### Changed
- `stk_init()`: replaced per-module `stk_pending_add()` calls inside the deferred module loop with batch collection followed by a single `stk_pending_add_batch()` call after the loop.
## [1.0.0-pre.4] - 2026-03-07
### Changed
- `stk_pending_retry()`: replaced per-module `realloc` at `attempt_load` with a single bulk allocation upfront (`module_count + stk_pending_count`) before the retry loop.
- `stk_poll()`: replaced per-module `stk_pending_add()` calls inside the unload and cascade loops with batch collection followed by a single `stk_pending_add_batch()` call after each loop.
## [1.0.0-pre.3] - 2026-03-07
### Added
- `STK_MOD_DEP_LOG_BUFFER` (2048) added to `stk.h`
### Changed
- Dependency failure logging now emits a single line per module listing all unmet deps with their reason: `not found` or `requires <constraint>, have <version>`
- `Deferring 'test_mod_dep': unmet deps: test_mod (not found)`
- `Unloading 'test_mod_dep': unmet deps: test_mod (not found), renderer (requires ^2.0.0, have 1.3.0)`
- Silent defer at `stk_init` and vague `"unmet dependencies"` cascade log in `stk_poll` replaced with `stk_log_dependency_failures()`
- Kahn topological sort refactored into generic `stk_kahn_sort()` accepting a `has_dep` callback and an `on_cycle` callback, decoupling it from `stk_modules`. `stk_topo_sort()` is now a thin wrapper. `stk_sort_load_order()` uses the same core via `stk_batch_has_dep()`, inspecting tmp files so simultaneous load events are processed dependency-first without a retry cycle
- `stk_module_load()` split into `stk_module_preload()`, `stk_module_activate()`, `stk_module_discard()`, and `stk_validate_dependencies_single()`. Init is not called if deps are unmet
- On UNLOAD events in `stk_poll()`, the unload set is expanded to include all transitively dependent modules via `stk_collect_dependents()`, sorted dependents-first via `stk_sort_unload_order()`. Modules unloaded due to expansion are queued to pending
- On LOAD events with unmet dependencies, the tmp path is added to the pending queue instead of being dropped
- `stk_pending_retry()` now skips already-loaded entries and prunes entries whose file no longer exists
- `free_poll` label moved above `stk_pending_retry()` so retry always runs regardless of exit path
## [1.0.0-pre.2] - 2026-03-06
### Fixed
- Module `init` is no longer called if dependencies are not satisfied. The library handle is unloaded and a dep error is returned.
## [1.0.0-pre.1] - 2026-03-06
### Added
- **Dependency System**: Full module dependency declaration and resolution
- Modules declare dependencies via an exported `stk_mod_deps` symbol, no stk headers required in modules, only the memory layout contract must be respected (`{ char[64], char[32] }` sentinel-terminated array)
- Version constraint operators: `=` (exact), `>=` (minimum, default), `^` (compatible — same major, greater or equal minor/patch)
- Version defaults to `0.0.0` if not provided or unparseable
- Dependency validation on `stk_init` and every `stk_poll` cycle
- Topological sort with cycle detection, load and unload ordering enforced
- All dependency failures logged before returning
- **Cascade Unload**: When a module is removed, all dependents cascade unload automatically and are added to the pending queue. Cascades repeat until the loaded set is stable
- **Pending Queue**: Modules that fail dependency validation are deferred. When their dependencies become available they are retried and loaded automatically. Entries are removed if their file is deleted
### Changed
- `stk_set_module_dependencies_fn` renamed to `stk_set_module_deps_sym`. Deps are now an exported array symbol, not a function
- Default deps symbol name changed from `stk_mod_dependencies` to `stk_mod_deps`
- `stk_dep_t` added to public header `stk.h`
- `stk_mod_t` field order changed to largest-to-smallest for correct memory alignment with zero padding waste
- Dependency validation failure during `stk_init` no longer fatal, affected modules are deferred to the pending queue
- Poll cycle now logs the full loaded module list as a single summary after any event that changes the loaded set, instead of logging each module individually
### Notes
- This release marks Phase 1 complete: hot-reloading foundation with dependency management
- Memory layout contract for `stk_mod_deps`: sentinel-terminated array of `{ char[64], char[32] }`. Modules do not need to include `stk.h`, define the struct inline or via your engine's own header as long as the layout matches
## [0.1.3] - 2026-02-25
### Added
- **Module Metadata**: Optional metadata support for modules
- `stk_mod_name` - human-readable module name
- `stk_mod_version` - semantic version string
- `stk_mod_description` - module description
- All three are optional, missing symbols are not errors
- Metadata stored in tight-packed arrays with index mappings
- Setter functions to override default symbol names before `stk_init()`
## [0.1.2] - 2026-02-15
### Fixed
- **Windows**
- Module reload now works correctly, idk how it was broken
- Temp directory creation fixed
- `.tmp` directory now hidden via FILE_ATTRIBUTE_HIDDEN
- Test build fixed
- Force cmd.exe shell in gmake.mk
- Fix bash syntax errors when running build.bat
- **All Platforms**: platform_mkdir now checks if directory exists before creating
## [0.1.1] - 2026-02-14
### Fixed
- **Logging**: Corrected log level severity order in enum
- Reversed order so DEBUG (0) < INFO (1) < WARN (2) < ERROR (3)
- Fixes filtering logic where ERROR/WARN were incorrectly blocked
- Default INFO level now properly shows INFO, WARN, and ERROR while filtering DEBUG
## [0.1.0] - 2026-02-14
### Fixed
- **C89 Compliance**: Removed stdint.h dependency (C99 feature)
- Replaced all uint8_t with unsigned char throughout codebase
- Ensures strict C89 compliance for maximum portability
### Added
- **Flags system**: Centralized bitfield for boolean state and settings
- Replaces stk_initialized with stk_flags for efficient memory usage
- Single byte packs all boolean flags (STK_FLAG_INITIALIZED, STK_FLAG_LOGGING_ENABLED)
- Runtime-changeable logging control via stk_set_logging_enabled()
- **Enhanced logging system**: Complete rewrite with modern features
- Log levels: ERROR, WARN, INFO, DEBUG with runtime filtering
- Timestamps: yyyy-mm-dd HH:MM:SS.mmm format (platform-specific implementation)
- Configurable log output stream (stk_set_log_output)
- Configurable log prefix (stk_set_log_prefix, defaults to "stk")
- Configurable minimum log level (stk_set_log_level, defaults to INFO)
- Platform abstraction for timestamps (GetLocalTime on Windows, gettimeofday on POSIX)
### Changed
- **BREAKING**: stk_log() signature changed from stk_log(FILE *fp, ...) to stk_log(stk_log_level_t level, ...)
- **BREAKING**: All uint8_t types replaced with unsigned char
- All internal STK messages now use appropriate log levels
- Setting log output to NULL disabls logging
### Notes
- This release completes Phase 1 logging improvements
- Dependency management still in progress for Phase 1 completion
## [0.0.4] - 2026-02-11
### Fixed
- **Linux**: Fixed segfault from invalid module indices during extremely rapid file changes
- Added validation check to skip stale UNLOAD/RELOAD events for already-unloaded modules
- Prevents is_mod_loaded() returning -1 from being used as array index (SIZE_MAX)
- Fixed event count mismatch where loops would run more iterations than valid indices populated
- Completes the Linux hot-reload stability fixes from v0.0.2
## [0.0.3] - 2026-02-10
### Fixed
- **Compilation**: Fixed GCC `-Wrestrict` warning in Linux directory watching code by replacing `strncpy` with `memmove` for overlapping memory operations
- Ensures clean compilation without warnings while maintaining identical runtime behavior
- Uses semantically correct function for moving memory within the same buffer
## [0.0.2] - 2026-02-09
### Fixed
- **Linux**: Fixed segfaults during rapid module reloads when file changes are detected in quick succession
- Enabled file readiness checks on Linux (previously only used on Windows/BSD) to prevent loading partially-written shared libraries
- Fixed inotify event deduplication to actually remove duplicate events instead of just marking them
- Reordered reload operations to only unload old module after successfully copying new version, preventing invalid state when copy fails
- **All platforms**: Improved reload safety by deferring module unload until after successful file copy
### Changed
- Made `is_file_ready()` check available on all Unix platforms (was previously excluded on Linux)
## [0.0.1] - 2026-02-01
### Added
- Cross-platform dynamic module loading (Linux, BSD, Windows)
- Hot-reloading of native modules at runtime
- File watching for automatic module reloads (inotify/kqueue/FindFirstFile)
- Basic module metadata support
- Basic logging infrastructure (stdout/stderr)
- Error handling for failed module loads
- Robust filename handling with proper buffer bounds checking
- Install/uninstall targets for Unix systems
- Test suite with cross-platform support
### Notes
- Phase 1 in progress: logging system incomplete (no log levels, verbosity control, or output configurability)
- Dependency management and versioning not yet implemented
- API is unstable and subject to change in future releases
[Unreleased]: https://github.com/anth64/stk/compare/v1.0.0-pre.12...HEAD
[1.0.0-pre.12]: https://github.com/anth64/stk/compare/v1.0.0-pre.11...v1.0.0-pre.12
[1.0.0-pre.11]: https://github.com/anth64/stk/compare/v1.0.0-pre.10...v1.0.0-pre.11
[1.0.0-pre.10]: https://github.com/anth64/stk/compare/v1.0.0-pre.9...v1.0.0-pre.10
[1.0.0-pre.9]: https://github.com/anth64/stk/compare/v1.0.0-pre.8...v1.0.0-pre.9
[1.0.0-pre.8]: https://github.com/anth64/stk/compare/v1.0.0-pre.7...v1.0.0-pre.8
[1.0.0-pre.7]: https://github.com/anth64/stk/compare/v1.0.0-pre.6...v1.0.0-pre.7
[1.0.0-pre.6]: https://github.com/anth64/stk/compare/v1.0.0-pre.5...v1.0.0-pre.6
[1.0.0-pre.5]: https://github.com/anth64/stk/compare/v1.0.0-pre.4...v1.0.0-pre.5
[1.0.0-pre.4]: https://github.com/anth64/stk/compare/v1.0.0-pre.3...v1.0.0-pre.4
[1.0.0-pre.3]: https://github.com/anth64/stk/compare/v1.0.0-pre.2...v1.0.0-pre.3
[1.0.0-pre.2]: https://github.com/anth64/stk/compare/v1.0.0-pre.1...v1.0.0-pre.2
[1.0.0-pre.1]: https://github.com/anth64/stk/compare/v0.1.3...v1.0.0-pre.1
[0.1.3]: https://github.com/anth64/stk/releases/tag/v0.1.3
[0.1.2]: https://github.com/anth64/stk/releases/tag/v0.1.2
[0.1.1]: https://github.com/anth64/stk/releases/tag/v0.1.1
[0.1.1]: https://github.com/anth64/stk/releases/tag/v0.1.1
[0.1.0]: https://github.com/anth64/stk/releases/tag/v0.1.0
[0.0.4]: https://github.com/anth64/stk/releases/tag/v0.0.4
[0.0.3]: https://github.com/anth64/stk/releases/tag/v0.0.3
[0.0.2]: https://github.com/anth64/stk/releases/tag/v0.0.2
[0.0.1]: https://github.com/anth64/stk/releases/tag/v0.0.1