Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Foundation libc #361

Merged
merged 26 commits into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
73d7ed4
empty initial commit
Jan 3, 2024
6908e38
Initial commit: Implements a handful of functions.
Jan 3, 2024
d591357
Some more hints
Jan 3, 2024
922de3c
Adds docs about scope and stubs out headers.
Jan 3, 2024
5945657
Stubs out zig module files, installs all headers.
Jan 3, 2024
b0f2528
Even more readme.
Jan 3, 2024
0e0d6fc
Adds MIT licence.
Jan 3, 2024
47f5c67
Completes the string.h header.
Jan 5, 2024
78def9d
Adds a nix flake for tooling, clang-format file and formats string.h,…
Jan 5, 2024
29f689a
Adds header validator, implements some header contents.
Jan 5, 2024
3e7253b
Even more work on the headers, adds more validation code
Jan 5, 2024
4c159fa
Fixes errno to work on single-threaded targets, adds CI
Jan 5, 2024
afe9006
Adds CI badge to README.md
Jan 5, 2024
b7e5cab
Implements ctype.h functions, adds support for panics, adds more code…
Jan 21, 2024
0c228a7
Add assert.h, fix installation of headers (#1)
mattnite Jan 21, 2024
843d8bf
Adds checks for validating assert, improves assertion behaviour based…
Jan 23, 2024
b82d2c3
update to zig 0.12.0 (#2)
mattnite May 21, 2024
9283a12
update zon (#3)
mattnite May 21, 2024
6a32c97
Updates nix flake and CI
Jun 16, 2024
513a52e
tiny fix for 0.14
elpekenin Nov 24, 2024
5281055
Merge pull request #4 from elpekenin/0.14prep
ikskuh Nov 25, 2024
95a14e7
Implement static assert
Jan 10, 2025
098891d
Exclude from C++ builds
Jan 10, 2025
e21e92f
Fix build error, add test
Jan 11, 2025
62de5f4
Merge pull request #5 from arkadiuszwojcik/static_assert
ikskuh Jan 11, 2025
50a3a00
Add 'modules/foundation-libc/' from commit '62de5f43c6947d8f4b99723da…
mattnite Jan 24, 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
26 changes: 26 additions & 0 deletions modules/foundation-libc/.clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
Language: Cpp
BasedOnStyle: LLVM

# basic indentation is 4 spaces, indented by spaces:
IndentWidth: 4
TabWidth: 4
UseTab: Never

# use east const for better readability:
QualifierAlignment: Right

# do not tack pointer to type nor value:
PointerAlignment: Middle

# align function names and keep them apart at least one line
AlignConsecutiveDeclarations: AcrossEmptyLines

# we sort includes to prevent merge conflicts:
SortIncludes: CaseSensitive

# disable column limit:
ColumnLimit: 0

---

1 change: 1 addition & 0 deletions modules/foundation-libc/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.zig text=auto eol=lf
28 changes: 28 additions & 0 deletions modules/foundation-libc/.github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Continuous Integration

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]

runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Zig
uses: mlugg/setup-zig@v1
with:
version: 0.13.0

- name: Generate and validate packages
working-directory: test
run: |
zig build validate
2 changes: 2 additions & 0 deletions modules/foundation-libc/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.zig-cache/
zig-out/
19 changes: 19 additions & 0 deletions modules/foundation-libc/LICENCE
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Copyright (c) 2024 Felix "xq" Queißner

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
OR OTHER DEALINGS IN THE SOFTWARE.
125 changes: 125 additions & 0 deletions modules/foundation-libc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Foundation libc

[![Continuous Integration](https://github.com/ZigEmbeddedGroup/foundation-libc/actions/workflows/build.yml/badge.svg?branch=main)](https://github.com/ZigEmbeddedGroup/foundation-libc/actions/workflows/build.yml)

A C standard library that only implements a subset of functions that can be safely used without an operating system.
This is called a [freestanding environment](https://en.cppreference.com/w/cpp/freestanding).

This libc is primarily meant to be used with microcontrollers, hobbyist operating systems and so on.

## Support

The first goal is to reach full C11 *freestanding* support.

- No support for locales
- No allocator (ship your own!)
- No support for functions that require an operating system of sorts in the background.
- No support for `wchar_t` and `wchar.h` as it isn't portable between compilers.
- Multi-byte character strings are implemented as UTF-8.

## Customization

Foundation libc doesn't really support much customization/configuration except for the hard required options.

There is [`foundation/libc.h`](include/foundation/libc.h) which documents the behaviour of all required configurations.

Right now, the following configurations exist:

- `foundation_libc_panic_handler`, which allows users to catch detectable undefined behaviour.

You can also configure the libc by chosing the build mode:

- `Debug`: Implements additional safety checks and adds breakpoints in panics.
- `ReleaseSafe`: Keeps the safety checks, but removes breakpoints.
- `ReleaseSmall`: Still keeps a certain amount of safety, but drops long internal strings to reduce code and ram size.
- `ReleaseFast`: Gotta go fast. Drops all safety and assumes all code behaves well.

There are also certain "usage" configurations that can be chosen to affect behaviour when *using* the headers. Those are implemented as C macros/defines:

- `FOUNDATION_LIBC_ASSERT` is a global macro that defines how `assert()` should behave:
- `FOUNDATION_LIBC_ASSERT_DEFAULT=0`: Behaves like a regular assert that can print file name, assertion message and line.
- `FOUNDATION_LIBC_ASSERT_NOFILE=1`: Drops the filename from the assertion to reduce code size.
- `FOUNDATION_LIBC_ASSERT_NOMSG=2`: Additionally drops the assertion message from the assertion to reduce code size.
- `FOUNDATION_LIBC_ASSERT_EXPECTED=3`: Replaces `assert(…)` with a construct that tells the compiler the assertion is always met. Makes code very fast. Assertions aren't checked.

## Development

Zig Version: 0.11

Run
```sh-session
user@microzig ~/foundation-libc $ zig build
user@microzig ~/foundation-libc $
```

to compile the libc and generate a lib file in `zig-out/lib` as well as the headers in `zig-out/include`.

## Contribution

Start by grabbing a header marked with ⏳ or 🛠 and implement the functions from that header. See if others already have a PR open for those functions so you don't do work twice!

Leverage functions from Zig `std` if possible as they are already well tested and should work.

Which functions belong into which header can be figured out by taking a look at the *C11 Standard Draft* document or the *IBM libc functions* list. [cppreference.com](https://en.cppreference.com/w/c) usually has the better docs though, so best check out both.

### Style Guides

- The header files are ment to be as minimal as possible
- Do not use comments documenting the functions, they are well documented everywhere else.
- Only insert empty lines between functions if necessarity for clarity
- Keep function names sorted alphabetically
- Try not to use macros at all
- Use `clang-format` with the provided style file.


## Links

- [C11 Standard](https://www.iso.org/standard/57853.html)
- [C11 Standard Draft](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1548.pdf)
- [ziglibc](https://github.com/marler8997/ziglibc)
- [libc-test](https://wiki.musl-libc.org/libc-test.html) by musl
- [cppreference on freestanding](https://en.cppreference.com/w/cpp/freestanding)
- [GCC on freestanding](https://gcc.gnu.org/onlinedocs/gcc/Standards.html#C-Language)
- [IBM libc functions](https://www.ibm.com/docs/en/i/7.5?topic=extensions-standard-c-library-functions-table-by-name) (function to header map)
- [cppreference](https://en.cppreference.com/w/c)
- [clang-format style options](https://releases.llvm.org/16.0.0/tools/clang/docs/ClangFormatStyleOptions.html)

## Status

⏳ (not started), 🛠 (work in progress), ⚠️ (partial support), ✅ (full support), ❌ (no support), 🔮 (potential future support), 🔀 (implemented by compiler)

| Header File | Header Status | Implementation Status | Description |
| --------------- | ------------- | --------------------- | ------------------------------------------------------------------------------------------------------- |
| `assert.h` | ✅ | ✅ | Conditionally compiled macro that compares its argument to zero |
| `complex.h` | ❌ | | (since C99) Complex number arithmetic |
| `ctype.h` | ✅ | ✅ | Functions to determine the type contained in character data |
| `errno.h` | ✅ | ✅ | Macros reporting error conditions |
| `fenv.h` | 🔮 | | (since C99) Floating-point environment |
| `float.h` | 🔀 | | Limits of floating-point types |
| `inttypes.h` | ⏳ | ⏳ | (since C99) Format conversion of integer types |
| `iso646.h` | 🔀 | | (since C95) Alternative operator spellings |
| `limits.h` | 🔀 | | Ranges of integer types |
| `locale.h` | ❌ | | Localization utilities |
| `math.h` | 🛠 | ⏳ | Common mathematics functions |
| `setjmp.h` | 🛠 | ⏳ | Nonlocal jumps |
| `signal.h` | ❌ | | Signal handling |
| `stdalign.h` | 🔀 | | (since C11) alignas and alignof convenience macros |
| `stdarg.h` | 🔀 | | Variable arguments |
| `stdatomic.h` | 🔮 | | (since C11) Atomic operations |
| `stdbit.h` | 🔮 | | (since C23) Macros to work with the byte and bit representations of types |
| `stdbool.h` | 🔀 | | (since C99) Macros for boolean type |
| `stdckdint.h` | 🔮 | | (since C23) macros for performing checked integer arithmetic |
| `stddef.h` | 🔀 | | Common macro definitions |
| `stdint.h` | 🔀 | | (since C99) Fixed-width integer types |
| `stdio.h` | ❌ | | Input/output |
| `stdlib.h` | 🛠 | 🛠 | General utilities: memory management, program utilities, string conversions, random numbers, algorithms |
| `stdnoreturn.h` | 🔀 | | (since C11) noreturn convenience macro |
| `string.h` | ✅ | 🛠 | String handling |
| `tgmath.h` | ⏳ | ⏳ | (since C99) Type-generic math (macros wrapping math.h and complex.h) |
| `threads.h` | ❌ | | (since C11) Thread library |
| `time.h` | ❌ | | Time/date utilities |
| `uchar.h` | 🛠 | ⏳ | (since C11) UTF-16 and UTF-32 character utilities |
| `wchar.h` | ❌ | | (since C95) Extended multibyte and wide character utilities |
| `wctype.h` | ❌ | | (since C95) Functions to determine the type contained in wide character data |


48 changes: 48 additions & 0 deletions modules/foundation-libc/build.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
const std = @import("std");

pub fn build(b: *std.Build) void {
const validation_step = b.step("validate", "Runs the test suite and validates everything. Automatically triggered in Debug builds.");

const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});

const single_threaded = b.option(bool, "single_threaded", "Create a single-threaded libc implementation (default: false)") orelse false;

// Run validation in debug builds for convenience:
if (optimize == .Debug) {
b.getInstallStep().dependOn(validation_step);
}

const libc = b.addStaticLibrary(.{
.name = "foundation",
.target = target,
.optimize = optimize,
.root_source_file = b.path("src/libc.zig"),
.single_threaded = single_threaded,
});

libc.addIncludePath(b.path("include"));
for (header_files) |header_name|
libc.installHeader(
b.path(b.fmt("include/{s}", .{header_name})),
header_name,
);

libc.installHeadersDirectory(b.path("include/foundation"), "foundation", .{});

b.installArtifact(libc);
}

const header_files = [_][]const u8{
"assert.h",
"ctype.h",
"errno.h",
"inttypes.h",
"math.h",
"setjmp.h",
"stdlib.h",
"string.h",
"tgmath.h",
"uchar.h",
"foundation/libc.h",
};
12 changes: 12 additions & 0 deletions modules/foundation-libc/build.zig.zon
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.{
.name = "foundation-libc",
.version = "0.0.0",
.paths = .{
"LICENSE",
"README.md",
"build.zig",
"build.zig.zon",
"include",
"src",
},
}
Loading
Loading