Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
1480e1b
:sparkles: Fix juno juno
robinonsay Sep 19, 2025
4144d89
:sparkles: Fix map
robinonsay Sep 19, 2025
1aec23a
:sparkles: Refactor hash
robinonsay Sep 20, 2025
ca84380
:sparkles: Add comments to hash map
robinonsay Sep 20, 2025
94d2f36
:sparkles: Make consitency changes
robinonsay Sep 20, 2025
242ae76
:sparkles: Make documentation changes
robinonsay Sep 20, 2025
6f5ae20
:memo: Change Readme
robinonsay Sep 20, 2025
f87f005
:sparkles: Change assert semicolon
robinonsay Sep 21, 2025
725e615
Add api to queue buff
robinonsay Sep 22, 2025
f0d3048
Update src/juno_time.c
robinonsay Sep 22, 2025
b18a8a9
Update tests/test_map.c
robinonsay Sep 22, 2025
b996834
Move inline to global
robinonsay Sep 22, 2025
b64ef83
Fix newline
robinonsay Sep 22, 2025
583d528
:fire: Remove union forward declare
robinonsay Sep 23, 2025
49c33d3
:sparkles: Remove forward union declare and upadet tests
robinonsay Sep 23, 2025
f2a7be3
:sparkles: Add copy to queue verify
robinonsay Sep 23, 2025
3e8f3a0
:sparkles: Update stack
robinonsay Oct 1, 2025
615be36
:sparkles: Remove src specific libs
robinonsay Oct 1, 2025
08e280e
:sparkles: Update memory api
robinonsay Oct 2, 2025
84ae751
:sparkles: Fix unit tests
robinonsay Oct 2, 2025
6d17201
:sparkles: Add alignment checks
robinonsay Oct 2, 2025
996d28a
:sparkles: Update stack api
robinonsay Oct 2, 2025
d29bef5
Update tests/test_stack.c
robinonsay Oct 2, 2025
77e0f81
Update tests/test_queue.c
robinonsay Oct 2, 2025
12dd4ac
Update src/juno_memory_block.c
robinonsay Oct 2, 2025
0ec5c0f
Make small changes
robinonsay Oct 2, 2025
5e7f1bb
Merge pull request #92 from robinonsay/feautre/new-mem
robinonsay Oct 2, 2025
5fb844b
Change to check pointer type
robinonsay Oct 2, 2025
ac513e4
Check pointer type also checks aligbnment
robinonsay Oct 2, 2025
2abc6ef
cast in check pointer
robinonsay Oct 2, 2025
dabeb14
Change cmake
robinonsay Oct 2, 2025
4c7660c
:sparkles: Fix alignment issue
robinonsay Oct 2, 2025
d639ff4
Fix alignment bug
robinonsay Oct 2, 2025
902cb14
i:sparkles: Make minor fixes
robinonsay Oct 2, 2025
a378387
:sparkles: Increment cmake to v1.0
robinonsay Oct 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 137 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# LibJuno — Copilot review playbook (repo-specific)

Purpose: Enable thorough MR reviews for LibJuno, a lightweight C11 library for embedded/freestanding targets, with emphasis on memory safety, determinism, developer experience, and deployability.

Trust this file first. Search the repo only when a step is unclear or fails.

---

## 1) What LibJuno is (and is not)

- Lightweight C11 library designed for embedded systems; can build freestanding (no libc) and emphasizes memory safety and determinism.
- Core themes:
- A small module system with dependency-injection (DI) via API vtables and macros (see `include/juno/README.md`).
- Deterministic memory utilities: block-based allocator with reference counting (no malloc required) and helpers (see `include/juno/memory/README.md`).
- Utility algorithms and containers (CRC variants, buffers/queues/stacks, maps, time, etc.).
- Tests use the Unity framework vendored in `deps/unity/`.

---

## 2) Build, test, docs — how to run here

Preconditions
- Use out-of-tree builds (`build/`). Initialize submodules if added in future.
- C standard is enforced as C11; warnings are enabled and treated as errors.

Common CMake flows
- Configure (static lib by default):
- Debug + tests: `cmake -S . -B build -DJUNO_TESTS=ON -DCMAKE_BUILD_TYPE=Debug`
- Release: `cmake -S . -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo`
- Sanitizers (host review): add any of
- `-DJUNO_ASAN=ON`, `-DJUNO_UBSAN=ON`
- Freestanding (no hosted libc):
- `-DJUNO_FREESTANDING=ON` (adds `-ffreestanding -nostdlib`; ensure no hosted headers in changes)
- Coverage (host):
- `-DJUNO_COVERAGE=ON` (links `gcov`, enables coverage flags)
- Examples: `-DJUNO_EXAMPLES=ON` to build samples in `examples/`.
- Shared library: `-DJUNO_SHARED=ON` to also build a shared artifact.

Build and test
- Build: `cmake --build build -j`
- Run tests (when `JUNO_TESTS=ON`):
- `ctest --test-dir build --output-on-failure`
- Tests are auto-discovered from `tests/` and link `unity` and `m`.

Docs
- Doxygen: configure with `-DJUNO_DOCS=ON`, then `cmake --build build --target docs`.

Install/package
- Install headers and libs: `cmake --install build --prefix <staging>`
- CMake package export: `cmake/junoConfig.cmake.in` is provided; verify `find_package(juno)` consumers as part of packaging checks.

---

## 3) Directory map (quick mental model)

- `include/juno/` — public headers (module system, memory, status, APIs). See `include/juno/README.md` and `include/juno/memory/README.md`.
- `src/` — implementation: CRCs (`juno_ccitt*.c`, `juno_kermit.c`, `juno_zip.c`), buffers/queues/stacks, memory block/heap, maps, time, etc.
- `tests/` — unit tests compiled when `JUNO_TESTS=ON`; `deps/unity` vendored test framework.
- `examples/` — minimal usage and DI demos; gated by `JUNO_EXAMPLES`.
- `docs/` + `Doxyfile.in` — documentation assets and template.
- `cmake/` — packaging config.
- `scripts/` — helper generators (templates, docs, versioning).

---

## 4) Validation pipeline for this repo

Run locally in this order and record results:
1) Configure + build (Debug) with sanitizers (when host review):
- `-DJUNO_TESTS=ON -DJUNO_ASAN=ON -DJUNO_UBSAN=ON -DCMAKE_BUILD_TYPE=Debug`
2) Run all tests via `ctest --output-on-failure`.
3) Build Release (`RelWithDebInfo`) and ensure no warnings (warnings are `-Werror`).
4) Optional: Coverage (`-DJUNO_COVERAGE=ON`) and generate reports (`lcov/genhtml`).
5) Docs build (`-DJUNO_DOCS=ON`, target `docs`).
6) Install/package sanity: `cmake --install` into a staging prefix; smoke check `junoConfig.cmake` and includes.

Notes
- Compilers: GCC/Clang expected. Project sets strict warnings (e.g., `-Wall -Wextra -Werror -Wshadow -Wcast-align -Wundef -Wswitch -Wmissing-field-initializers -fno-common -fno-strict-aliasing`).
- For freestanding builds, ensure added code avoids hosted headers and syscalls.

---

## 5) LibJuno-focused code review checklist

Memory safety & UB
- Block allocator: verify bounds, reuse of freed blocks, and reference counting semantics. Ensure:
- `JunoMemory_BlockInit` parameters are validated; type sizes match usage.
- `Get/Put/Update` respect element size and block limits; reject double-free; `Put` fails when refs > 1.
- All return codes (`JUNO_STATUS_T`) are checked at call sites.
- Avoid libc when `JUNO_FREESTANDING=ON`; no hidden dynamic allocation in hot paths.
- Integer and pointer hygiene: no narrowing, no invalid shifts, alignments explicit; observe strict aliasing rules.

Module system & DI (see `include/juno/README.md`)
- Every module sets `ptApi` to a valid vtable during init; failure handler (`JUNO_FAILURE_HANDLER`) and user data wired.
- Derived types overlay base via `JUNO_MODULE/JUNO_MODULE_DERIVE`; ensure member access uses the correct view and alignment.
- API contracts are clear: inputs validated, null checks present, and failure paths call the failure handler with actionable messages.

Concurrency/real-time
- No blocking I/O or heap in ISR-sensitive paths; minimal critical sections; volatile and barriers when required by shared state.

Portability & build flags
- Code builds clean with the project’s warning set; no reliance on compiler-specific extensions unless guarded.
- When `JUNO_SHARED=ON`, confirm symbol visibility and no accidental ABI leaks from private headers.

Tests & examples
- Unit tests cover edge cases for allocators (empty/full pool, refcounting, invalid free), containers (under/overflow), and CRC correctness against vectors.
- Examples compile with `JUNO_EXAMPLES=ON` and match documented usage in READMEs.

Docs & DX
- Public headers are self-documenting; Doxygen groups render without warnings.
- Namespaces/prefixes consistent (`Juno*`, `JUNO_*`); error codes and macro usage are discoverable from headers.

---

## 6) Common pitfalls seen in this repo

- Freestanding mode requires avoiding hosted headers even in helpers/tests; gate usage with `#if !JUNO_FREESTANDING` where necessary.
- Tests link `m` (math); ensure new tests include only headers available on host.
- Watch for off-by-one in buffer/queue/stack implementations and mixing of signed/unsigned indices.
- When updating install/package, validate `cmake/junoConfig.cmake.in` and the exported targets; run a small consumer CMake to `find_package(juno)`.

---

## 7) What to record in MR reviews

- Exact configure/build/test commands and outcomes (pass/fail), compiler versions, sanitizer results.
- Any deviations from README or CI, including steps required to build docs or examples.
- Specific file/line issues with concrete suggestions or diffs (headers first, then sources, then tests).
- Packaging/install verification notes (what installed, include paths, and find_package smoke test results).

---

## 8) When to search the repo

- If something is unclear or fails, consult: `README.md`, `include/juno/README.md`, `include/juno/memory/README.md`, top-level `CMakeLists.txt`, `tests/CMakeLists.txt`, `cmake/junoConfig.cmake.in`, `docs/`, `examples/`, `scripts/`.

Final instruction: Prefer these sequences and checklists for LibJuno. If a command fails, document the failure, adjust minimally, and continue the review using the closest equivalent in this repository.
6 changes: 5 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@
"variant": "cpp",
"algorithm": "cpp",
"type_traits": "cpp",
"utility": "cpp"
"utility": "cpp",
"memory_api.h": "c",
"compare": "c",
"functional": "c",
"tuple": "c"
}
}
72 changes: 43 additions & 29 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.10)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
Expand All @@ -10,10 +10,14 @@ option(JUNO_COVERAGE "Compile Juno with code coverage" OFF)
option(JUNO_DOCS "Enable doxygen docs" OFF)
option(JUNO_PIC "Compile Juno with Position Independent Code" ON)
option(JUNO_SHARED "Compile the juno shared library" OFF)
option(JUNO_FREESTANDING "Compile as a freestanding library" OFF)
option(JUNO_ASAN "Compile ASAN" OFF)
option(JUNO_UBSAN "Compile with UBSAN" OFF)
option(JUNO_EXAMPLES "Compile Juno Examples" OFF)
message("Compiler: ${CMAKE_C_COMPILER}")
message("Testing: ${JUNO_TESTS}")

project(juno VERSION 0.42.0 LANGUAGES C CXX)
project(juno VERSION 1.0.0 LANGUAGES C CXX)

if(JUNO_API)
add_definitions(-DJUNO_API)
Expand All @@ -29,6 +33,8 @@ add_library(${PROJECT_NAME} STATIC
target_include_directories(${PROJECT_NAME} PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/include>
PRIVATE
${PROJECT_SOURCE_DIR}/src
)

set(JUNO_COMPILE_OPTIONS
Expand All @@ -52,8 +58,6 @@ set(JUNO_COMPILE_CXX_OPTIONS
)

set(JUNO_COMPILE_C_OPTIONS
-Wstrict-prototypes # Warn if a function is declared without specifying argument types
-Wmissing-prototypes # Warn if a global function is defined without a previous prototype declaration
)

if(JUNO_PIC)
Expand All @@ -67,48 +71,53 @@ if(JUNO_COVERAGE)
link_libraries(gcov)
endif()

set(JUNO_LIBS ${PROJECT_NAME})
foreach(file ${JUNO_SRCS})
# Get the file name without extension (NAME_WE stands for Name Without Extension)
get_filename_component(lib_name ${file} NAME_WE)
add_library(${lib_name} STATIC
${file}
)
list(APPEND JUNO_LIBS ${lib_name})
endforeach()

# Specify the include directories for consumers of this library
foreach(lib ${JUNO_LIBS})
target_include_directories(${lib} PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/include>
PRIVATE
${PROJECT_SOURCE_DIR}/src
)
# Enable a comprehensive set of warnings
target_compile_options(${lib} PRIVATE
${JUNO_COMPILE_OPTIONS}
$<$<COMPILE_LANGUAGE:C>:${JUNO_COMPILE_C_OPTIONS}>
$<$<COMPILE_LANGUAGE:CXX>:${JUNO_COMPILE_CXX_OPTIONS}>
if(JUNO_FREESTANDING)
list(APPEND JUNO_COMPILE_C_OPTIONS
-nostdlib
-ffreestanding # Disable the hosted environment
-ffreestanding
)
target_link_options(${lib} PRIVATE
-nostdlib
)
endforeach()
endif()
if(JUNO_ASAN)
add_compile_options(
-fsanitize=address
)
add_link_options(
-fsanitize=address
)
endif()
if(JUNO_UBSAN)
add_compile_options(
-fsanitize=undefined
)
add_link_options(
-fsanitize=undefined
)
endif()
# Enable a comprehensive set of warnings
target_compile_options(${PROJECT_NAME} PRIVATE
${JUNO_COMPILE_OPTIONS}
$<$<COMPILE_LANGUAGE:C>:${JUNO_COMPILE_C_OPTIONS}>
$<$<COMPILE_LANGUAGE:CXX>:${JUNO_COMPILE_CXX_OPTIONS}>

)

if(JUNO_SHARED)
set(JUNO_SHARED_TARGET ${PROJECT_NAME}_shared)
add_library(${JUNO_SHARED_TARGET} SHARED ${JUNO_SRCS})
target_include_directories(${JUNO_SHARED_TARGET} PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/include>
PRIVATE
${PROJECT_SOURCE_DIR}/src
)
endif()

install(
TARGETS ${JUNO_LIBS} ${JUNO_SHARED_TARGET} ${JUNO_POSIX_TARGET}
TARGETS ${PROJECT_NAME} ${JUNO_SHARED_TARGET} ${JUNO_POSIX_TARGET}
EXPORT junoTargets # for later use in find_package()
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # usually “lib”
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
Expand All @@ -131,6 +140,11 @@ if(JUNO_TESTS)
add_subdirectory(${PROJECT_SOURCE_DIR}/tests)
endif()

if(JUNO_EXAMPLES)
set(CMAKE_BUILD_TYPE Debug)
add_subdirectory(${PROJECT_SOURCE_DIR}/examples)
endif()


if(JUNO_DOCS)
# 1) Find Doxygen
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,4 @@
Juno is the name of my wonderful dog and
she has brought me so much comfort and stability throughout the years.
I wanted to honor her legacy by naming an open-source library after her.

17 changes: 17 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Create the library (update the source files as needed)
set(JUNO_EXAMPLE_DIR ${PROJECT_SOURCE_DIR}/examples)
aux_source_directory(${JUNO_EXAMPLE_DIR} JUNO_EXAMPLE_SRCS)


# Loop over each file and remove the extension
foreach(file ${JUNO_EXAMPLE_SRCS})
# Get the file name without extension (NAME_WE stands for Name Without Extension)
get_filename_component(example_name ${file} NAME_WE)
add_executable(${example_name} ${file})
target_link_libraries(${example_name} ${PROJECT_NAME} unity m)
target_compile_options(${example_name} PRIVATE
${JUNO_COMPILE_OPTIONS}
$<$<COMPILE_LANGUAGE:C>:${JUNO_COMPILE_C_OPTIONS}>
$<$<COMPILE_LANGUAGE:CXX>:${JUNO_COMPILE_CXX_OPTIONS}>
)
endforeach()
4 changes: 4 additions & 0 deletions examples/di_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,7 @@ In this tutorial, we’ll walk through:
We’ll use the example code provided in the “gastank\_api.h”, “engine\_api.h”, “battery\_api.h”, “car\_api.h” files, plus their implementations, to illustrate these concepts. By the end, you’ll see how a modular, DI-driven design can keep your embedded software clean, testable, and maintainable.
*/

int main(void)
{
return 0;
}
6 changes: 6 additions & 0 deletions examples/example_sb.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include "juno/sb/msg_api.h"

int main(void)
{
return 0;
}
27 changes: 14 additions & 13 deletions examples/example_state_machine.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ union JUNO_SM_STATE_T JUNO_MODULE(JUNO_SM_STATE_API_T, JUNO_SM_STATE_ROOT_T,
);

/// The action that should be executed in this state
static JUNO_STATUS_T StateAction(JUNO_SM_STATE_T *ptJunoSm)
static JUNO_STATUS_T StateAction(JUNO_SM_STATE_ROOT_T *ptJunoSm)
{
JUNO_STATUS_T tStatus = JunoSm_StateVerify(&ptJunoSm->tRoot);
JUNO_STATUS_T tStatus = JunoSm_StateVerify(ptJunoSm);
JUNO_ASSERT_SUCCESS(tStatus, return tStatus);
TRAFFIC_LIGHT_STATE_T *ptTrafficLightState = (TRAFFIC_LIGHT_STATE_T*) ptJunoSm;
printf("Current State: %u\n", ptTrafficLightState->tThisLight);
Expand All @@ -35,9 +35,9 @@ static JUNO_STATUS_T StateAction(JUNO_SM_STATE_T *ptJunoSm)
return JUNO_STATUS_SUCCESS;
}
/// Returns a bool result whether the current state should exit
static JUNO_RESULT_BOOL_T ShouldExit(JUNO_SM_STATE_T *ptJunoSm)
static JUNO_RESULT_BOOL_T ShouldExit(JUNO_SM_STATE_ROOT_T *ptJunoSm)
{
JUNO_STATUS_T tStatus = JunoSm_StateVerify(&ptJunoSm->tRoot);
JUNO_STATUS_T tStatus = JunoSm_StateVerify(ptJunoSm);
JUNO_RESULT_BOOL_T tResult = {0};
TRAFFIC_LIGHT_STATE_T *ptTrafficLightState = (TRAFFIC_LIGHT_STATE_T*) ptJunoSm;
tResult.tStatus = tStatus;
Expand All @@ -47,9 +47,9 @@ static JUNO_RESULT_BOOL_T ShouldExit(JUNO_SM_STATE_T *ptJunoSm)
}


static JUNO_STATUS_T ResetState(JUNO_SM_STATE_T *ptJunoSm)
static JUNO_STATUS_T ResetState(JUNO_SM_STATE_ROOT_T *ptJunoSm)
{
JUNO_STATUS_T tStatus = JunoSm_StateVerify(&ptJunoSm->tRoot);
JUNO_STATUS_T tStatus = JunoSm_StateVerify(ptJunoSm);
JUNO_ASSERT_SUCCESS(tStatus, return tStatus);
TRAFFIC_LIGHT_STATE_T *ptTrafficLightState = (TRAFFIC_LIGHT_STATE_T*) ptJunoSm;
ptTrafficLightState->iCounter = 0;
Expand Down Expand Up @@ -86,9 +86,10 @@ TRAFFIC_LIGHT_SM_T tSm = {
},
};

int main()
int main(void)
{
JUNO_STATUS_T tStatus = JunoSm_Init(&tSm.tRoot, &tSm.tStates[TRAFFIC_RED].tRoot, NULL, NULL);
JUNO_ASSERT_SUCCESS(tStatus, return -1);
for(size_t i = 0; i < TRAFFIC_COUNT; i++)
{
TRAFFIC_LIGHT_STATE_T *ptSmState = &tSm.tStates[i];
Expand All @@ -97,21 +98,21 @@ int main()
while(true)
{
JUNO_SM_RESULT_STATE_T tStateResult = JunoSm_GetCurrentState(&tSm.tRoot);
JUNO_ASSERT_SUCCESS(tStateResult.tStatus, break;);
JUNO_SM_STATE_ROOT_T *ptSmState = &tStateResult.tOk->tRoot;
JUNO_ASSERT_SUCCESS(tStateResult.tStatus, break);
JUNO_SM_STATE_ROOT_T *ptSmState = tStateResult.tOk;
if(ptSmState)
{
const JUNO_SM_STATE_API_T *ptSmStateApi = ptSmState->ptApi;
JUNO_RESULT_BOOL_T tBoolResult = ptSmStateApi->ShouldExit((JUNO_SM_STATE_T *)ptSmState);
JUNO_ASSERT_SUCCESS(tBoolResult.tStatus, break;);
JUNO_RESULT_BOOL_T tBoolResult = ptSmStateApi->ShouldExit(ptSmState);
JUNO_ASSERT_SUCCESS(tBoolResult.tStatus, break);
if(tBoolResult.tOk)
{
ptSmStateApi->ResetState((JUNO_SM_STATE_T *)ptSmState);
ptSmStateApi->ResetState(ptSmState);
JunoSm_TransitionState(&tSm.tRoot);
}
else
{
ptSmStateApi->StateAction((JUNO_SM_STATE_T *)ptSmState);
ptSmStateApi->StateAction(ptSmState);
}
}
}
Expand Down
Loading