Add vlibc scaffold, build system, and documentation
Establish the repository layout per Vox guidelines (layouts/C.md, building/C.md): Autotools build (GCC-only, C23), five compatibility profiles (--enable-onlyposix/--enable-muslmimic/--enable-muslext/ --enable-spoof, default vlibc), alongside/overwrite install methods, vlibc-gcc/vlibc-clang drivers, static-linking requirement (except spoof), benchmark harness, and tooling (.clang-format/.clang-tidy/ .clangd + compile_commands.json).
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
# clang-format configuration for vlibc.
|
||||
# Keep in sync with STYLEGUIDE.md.
|
||||
|
||||
BasedOnStyle: LLVM
|
||||
Language: Cpp
|
||||
|
||||
IndentWidth: 4
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
ContinuationIndentWidth: 4
|
||||
ColumnLimit: 100
|
||||
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: true
|
||||
AfterClass: true
|
||||
AfterControlStatement: Always
|
||||
AfterEnum: true
|
||||
AfterFunction: true
|
||||
AfterNamespace: true
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: true
|
||||
BeforeElse: true
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
AlwaysBreakAfterReturnType: TopLevel
|
||||
PointerAlignment: Right
|
||||
DerivePointerAlignment: false
|
||||
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
|
||||
SortIncludes: CaseSensitive
|
||||
ReflowComments: false
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
# clang-tidy configuration for vlibc.
|
||||
# Keep in sync with STYLEGUIDE.md.
|
||||
|
||||
Checks: >
|
||||
bugprone-*,
|
||||
clang-analyzer-*,
|
||||
misc-*,
|
||||
performance-*,
|
||||
portability-*,
|
||||
readability-*,
|
||||
-readability-magic-numbers,
|
||||
-readability-identifier-length,
|
||||
-readability-function-cognitive-complexity,
|
||||
-misc-include-cleaner
|
||||
|
||||
WarningsAsErrors: 'bugprone-*,clang-analyzer-*'
|
||||
HeaderFilterRegex: '^include/'
|
||||
|
||||
FormatStyle: file
|
||||
@@ -0,0 +1,19 @@
|
||||
# clangd language-server configuration for vlibc.
|
||||
# Provides fallback flags so the LSP reports errors on valid code even before
|
||||
# compile_commands.json is regenerated (see layouts/C.md).
|
||||
|
||||
CompileFlags:
|
||||
CompilationDatabase: .
|
||||
Add:
|
||||
- -std=c23
|
||||
- -Iinclude
|
||||
|
||||
Diagnostics:
|
||||
UnusedIncludes: Strict
|
||||
ClangTidy:
|
||||
Add:
|
||||
- bugprone-*
|
||||
- clang-analyzer-*
|
||||
|
||||
Index:
|
||||
Background: Build
|
||||
+51
@@ -52,3 +52,54 @@ Module.symvers
|
||||
Mkfile.old
|
||||
dkms.conf
|
||||
|
||||
# Autotools backup files (autoreconf/autoheader).
|
||||
*~
|
||||
*.orig
|
||||
*.rej
|
||||
|
||||
# ---> vlibc / Autotools
|
||||
# Generated build system. `configure` and `autogen.sh` are tracked (layouts/C.md);
|
||||
# the Makefiles and other artifacts produced from configure.ac / Makefile.am are not.
|
||||
Makefile
|
||||
Makefile.in
|
||||
.dirstamp
|
||||
/aclocal.m4
|
||||
/autom4te.cache/
|
||||
/config.h
|
||||
/config.h.in
|
||||
/config.log
|
||||
/config.status
|
||||
/config.guess
|
||||
/config.sub
|
||||
/install-sh
|
||||
/missing
|
||||
/depcomp
|
||||
/ltmain.sh
|
||||
/libtool
|
||||
/libtool.m4
|
||||
/ltoptions.m4
|
||||
/ltsugar.m4
|
||||
/ltversion.m4
|
||||
/lt~obsolete.m4
|
||||
/stamp-h1
|
||||
/build-aux/
|
||||
/m4/
|
||||
|
||||
# Libtool build directories and artifacts.
|
||||
.deps/
|
||||
.libs/
|
||||
*.lo
|
||||
|
||||
# Build outputs (bin/{release,debug}); keep the directory placeholders.
|
||||
/bin/release/*
|
||||
!/bin/release/.gitkeep
|
||||
/bin/debug/*
|
||||
!/bin/debug/.gitkeep
|
||||
|
||||
# Generated compiler drivers (from tools/*.in); the templates are tracked.
|
||||
/tools/vlibc-gcc
|
||||
/tools/vlibc-clang
|
||||
|
||||
# Built benchmark harnesses (benchmarks/bench_* are generated from bench_*.c).
|
||||
/benchmarks/bench_vlibc
|
||||
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
# Contributing
|
||||
|
||||
## Compiler policy
|
||||
|
||||
vlibc is built with **exactly one compiler: GCC**. There is no fallback to
|
||||
another compiler (`building/C.md`). This lets vlibc use compiler extensions
|
||||
freely while keeping behavior deterministic.
|
||||
|
||||
## Building
|
||||
|
||||
```sh
|
||||
./autogen.sh # autoreconf + configure
|
||||
make # build
|
||||
make debug # -O0 -g3 into bin/debug/
|
||||
make release # -O3 into bin/release/
|
||||
make bench # build + run benchmarks
|
||||
make clean # remove artifacts
|
||||
```
|
||||
|
||||
`autogen.sh` regenerates the build system from `configure.ac` / `Makefile.am`
|
||||
and then runs `configure`. The generated `configure` script is tracked; the
|
||||
Makefiles it produces are not.
|
||||
|
||||
### Compatibility profiles
|
||||
|
||||
Pick exactly one (they are mutually exclusive):
|
||||
|
||||
| Flag | Profile | Description |
|
||||
|-----------------------|--------------|-----------------------------------|
|
||||
| *(default)* | `vlibc` | glibc-extended, extended features |
|
||||
| `--enable-onlyposix` | `onlyposix` | pure POSIX, nothing more |
|
||||
| `--enable-muslmimic` | `muslmimic` | musl-like, light |
|
||||
| `--enable-muslext` | `muslext` | musl-extended |
|
||||
| `--enable-spoof` | `spoof` | glibc replica (drop-in) |
|
||||
|
||||
### Install methods
|
||||
|
||||
```sh
|
||||
./autogen.sh --with-install=alongside # default: keep system libc
|
||||
./autogen.sh --with-install=overwrite # replace system libc
|
||||
```
|
||||
|
||||
### Static linking
|
||||
|
||||
Full static linking is **required** for every profile except `spoof`. Configure
|
||||
rejects `--disable-static` for those profiles.
|
||||
|
||||
## Benchmarks
|
||||
|
||||
Every component must be benchmarked against the software it replaces
|
||||
(`musts/BENCHMARKING.md`). A component slower than glibc is failing.
|
||||
|
||||
```sh
|
||||
./autogen.sh --with-libc=glibc # reference comparison
|
||||
make bench
|
||||
```
|
||||
|
||||
## Style and linting
|
||||
|
||||
- `.clang-format` — run `clang-format` before committing; it must agree with
|
||||
`STYLEGUIDE.md`.
|
||||
- `.clang-tidy` — `bugprone-*` and `clang-analyzer-*` are warnings-as-errors.
|
||||
- Keep `compile_commands.json` fresh (`make compile-commands`) so language
|
||||
servers do not report errors on valid code.
|
||||
|
||||
## Vendoring
|
||||
|
||||
Third-party code goes in `thirdparty/`, with its upstream source, version, and
|
||||
license recorded alongside it. No external downloads at build time.
|
||||
|
||||
## Submitting changes
|
||||
|
||||
1. Open an issue describing the problem or feature first.
|
||||
2. Keep changes small and focused; one concern per change.
|
||||
3. Add or update benchmarks and documentation with the change.
|
||||
4. Ensure `make debug`, `make release`, and `make bench` pass.
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
# vlibc — top-level build (see building/C.md and layouts/C.md).
|
||||
|
||||
SUBDIRS = benchmarks
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include
|
||||
AM_CFLAGS = @VLIBC_CFLAGS@
|
||||
|
||||
# ---- Library -------------------------------------------------------------
|
||||
vlibc_include_HEADERS = include/vlibc.h
|
||||
vlibc_lib_LTLIBRARIES = libvlibc.la
|
||||
|
||||
libvlibc_la_SOURCES = src/vlibc.c
|
||||
libvlibc_la_LDFLAGS = -version-info 0:0:0 -no-undefined
|
||||
|
||||
# Install location depends on the install method (see configure.ac).
|
||||
if INSTALL_OVERWRITE
|
||||
vlibc_includedir = $(includedir)
|
||||
vlibc_libdir = $(libdir)
|
||||
else
|
||||
vlibc_includedir = $(prefix)/lib/vlibc/include
|
||||
vlibc_libdir = $(prefix)/lib/vlibc/lib
|
||||
endif
|
||||
|
||||
# ---- Compiler drivers ----------------------------------------------------
|
||||
bin_SCRIPTS = tools/vlibc-gcc tools/vlibc-clang
|
||||
|
||||
# ---- Targets -------------------------------------------------------------
|
||||
# layouts/C.md requires `make debug`, `make release`, `make bench` and
|
||||
# `make clean`; build outputs land in bin/{release,debug}.
|
||||
DEBUG_CFLAGS = -O0 -g3 -DDEBUG
|
||||
RELEASE_CFLAGS = -O3 -DNDEBUG
|
||||
|
||||
debug:
|
||||
$(MAKE) clean
|
||||
$(MAKE) all AM_CFLAGS="$(AM_CFLAGS) $(DEBUG_CFLAGS)"
|
||||
$(MKDIR_P) bin/debug
|
||||
-cp -P .libs/libvlibc.so* bin/debug/
|
||||
-cp .libs/libvlibc.a bin/debug/
|
||||
|
||||
release:
|
||||
$(MAKE) clean
|
||||
$(MAKE) all AM_CFLAGS="$(AM_CFLAGS) $(RELEASE_CFLAGS)"
|
||||
$(MKDIR_P) bin/release
|
||||
-cp -P .libs/libvlibc.so* bin/release/
|
||||
-cp .libs/libvlibc.a bin/release/
|
||||
|
||||
bench: all
|
||||
$(MAKE) -C benchmarks bench
|
||||
|
||||
# Regenerate compile_commands.json (requires `bear`). Captures both the
|
||||
# library sources and the on-demand benchmark harness.
|
||||
compile-commands: clean
|
||||
bear -- $(MAKE) all
|
||||
bear --append -- $(MAKE) -C benchmarks bench_vlibc
|
||||
|
||||
.PHONY: debug release bench compile-commands
|
||||
@@ -1,3 +1,72 @@
|
||||
# vlibc
|
||||
|
||||
A modern replacement for glibc, with modern features and extensions of the standard. Plus compatibility with glibc.
|
||||
A modern replacement for glibc: a performant, standard-conforming C library
|
||||
with modern extensions and high glibc compatibility.
|
||||
|
||||
vlibc is written in C (C23, with C2y/C29 opt-in), built with Autotools and a
|
||||
single compiler (GCC, no fallback). Full static linking is a first-class,
|
||||
required capability.
|
||||
|
||||
## Capabilities
|
||||
|
||||
- **Five compatibility profiles**, from the lightest to the most compatible:
|
||||
1. `--enable-onlyposix` — pure POSIX, nothing more.
|
||||
2. `--enable-muslmimic` — musl-like, light and musl-compatible.
|
||||
3. `--enable-muslext` — musl-extended.
|
||||
4. `--enable-spoof` — a glibc replica, for drop-in compatibility with
|
||||
scripts and programs that rely on long-standing glibc behavior.
|
||||
5. *(default)* — **vlibc**: glibc-extended, without the spoofing layer, but
|
||||
with extended standard features and high glibc compatibility.
|
||||
- **Two install methods** (`--with-install=`):
|
||||
- `alongside` (default) — install next to the system libc, under a
|
||||
vlibc-specific tree; the system libc is left untouched.
|
||||
- `overwrite` — replace the system libc in place.
|
||||
- **`vlibc-gcc` and `vlibc-clang`** compiler drivers, so consuming projects
|
||||
build against vlibc with either compiler.
|
||||
- **Full static linking** is required for every profile except `spoof`.
|
||||
- **Compiler intent** is declared on the public API (e.g.
|
||||
`__attribute__((const))`) so the compiler can fold and eliminate calls,
|
||||
keeping statically linked binaries small.
|
||||
|
||||
## Build
|
||||
|
||||
```sh
|
||||
./autogen.sh # regenerate build system + configure
|
||||
make # build
|
||||
make debug # build with -O0 -g3 into bin/debug/
|
||||
make release # build with -O3 into bin/release/
|
||||
make bench # build and run benchmarks
|
||||
make clean # remove build artifacts
|
||||
make compile-commands # regenerate compile_commands.json (needs bear)
|
||||
```
|
||||
|
||||
Common configure options:
|
||||
|
||||
```sh
|
||||
./autogen.sh --enable-spoof # glibc replica profile
|
||||
./autogen.sh --with-install=overwrite # replace system libc
|
||||
./autogen.sh --with-libc=glibc # benchmark against glibc
|
||||
./autogen.sh --enable-c29 # experimental C2y (C29)
|
||||
```
|
||||
|
||||
User-provided `CFLAGS` and `LDFLAGS` are honored.
|
||||
|
||||
## Layout
|
||||
|
||||
```
|
||||
include/ public headers (mandatory)
|
||||
src/ implementation sources
|
||||
benchmarks/ benchmark harnesses (vs. glibc/musl)
|
||||
docs/ behavior and glibc-difference documentation
|
||||
thirdparty/ vendored third-party libraries
|
||||
tools/ vlibc-gcc / vlibc-clang driver templates
|
||||
bin/{release,debug}/ build outputs
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
- `docs/overview.md` — what vlibc is and how it behaves.
|
||||
- `docs/compatibility.md` — the five profiles and glibc differences.
|
||||
- `docs/install.md` — the two install methods.
|
||||
- `CONTRIBUTING.md` — how to contribute.
|
||||
- `STYLEGUIDE.md` — how code should look.
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
# Styleguide
|
||||
|
||||
This file is the source of truth for how vlibc code looks. `.clang-format` is
|
||||
generated from / kept in sync with it.
|
||||
|
||||
## Language
|
||||
|
||||
- C23 is the default standard; C2y (C29) is opt-in via `--enable-c29`.
|
||||
- GCC only. Compiler extensions (`__attribute__`, statement expressions,
|
||||
`defer` under C2y) are permitted and encouraged where they improve clarity
|
||||
or performance.
|
||||
|
||||
## Formatting
|
||||
|
||||
- 4-space indent, no tabs.
|
||||
- 100-column limit.
|
||||
- Allman braces: opening brace on its own line, for functions and blocks.
|
||||
- Always use braces, even for single-statement blocks (avoids `goto fail`-style
|
||||
bugs and matches `.clang-tidy`).
|
||||
- Pointer and qualifier attach to the name: `const char *s`, `int *p`.
|
||||
- Spaces around binary operators; no space after unary operators.
|
||||
|
||||
The one exception to Allman braces is the C++ linkage guard: `extern "C" {`
|
||||
keeps its opening brace attached (encoded as `AfterExternBlock: false` in
|
||||
`.clang-format`), because that is the idiomatic form every C header uses.
|
||||
|
||||
```c
|
||||
int
|
||||
foo(const char *s, size_t n)
|
||||
{
|
||||
if (n == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int)(s[0] == 'x');
|
||||
}
|
||||
```
|
||||
|
||||
## Naming
|
||||
|
||||
- Functions and variables: `snake_case`.
|
||||
- Types: `snake_case` (struct tags); typedefs avoid the POSIX-reserved `_t`
|
||||
suffix.
|
||||
- Macros and constants: `UPPER_SNAKE_CASE`.
|
||||
- Public identifiers are prefixed `vlibc_` to avoid collisions.
|
||||
- Identifiers beginning with `_` (or `__`, or `_[A-Z]`) are reserved for the
|
||||
implementation and the C/POSIX standards — do not introduce new ones.
|
||||
|
||||
## Include guards
|
||||
|
||||
Public headers use traditional include guards:
|
||||
|
||||
```c
|
||||
#ifndef VLIBC_H
|
||||
#define VLIBC_H
|
||||
...
|
||||
#endif /* VLIBC_H */
|
||||
```
|
||||
|
||||
`#pragma once` is a widely supported extension but is deliberately not used:
|
||||
it relies on compiler-specific path canonicalization and can mis-deduplicate
|
||||
headers reachable through symlinks or bind mounts. For a libc whose headers are
|
||||
consumed in many toolchain configurations, explicit guards are the robust
|
||||
default.
|
||||
|
||||
## Compiler intent
|
||||
|
||||
Public declarations annotate *intent* so the compiler can optimize statically
|
||||
linked binaries (see `docs/overview.md`):
|
||||
|
||||
- `__attribute__((const))` — result depends only on arguments.
|
||||
- `__attribute__((pure))` — no side effects; may read memory.
|
||||
- `__attribute__((always_inline))`, `__attribute__((leaf))`,
|
||||
`__attribute__((malloc))`, `__attribute__((access, ...))` — as appropriate.
|
||||
|
||||
Every public function carries the tightest correct attribute.
|
||||
|
||||
## Error handling
|
||||
|
||||
- No empty blocks; no silent failure.
|
||||
- Library functions return errors via return codes or `errno`; they never
|
||||
terminate the caller's process.
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
# vlibc — Autotools bootstrap (layouts/C.md).
|
||||
#
|
||||
# Regenerates the build system (configure, Makefile.in, ...) from the
|
||||
# *.ac / *.am sources and then runs configure, passing through any
|
||||
# arguments. The generated `configure` script is tracked; the Makefiles
|
||||
# it produces are not (see .gitignore).
|
||||
|
||||
set -e
|
||||
|
||||
srcdir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
||||
cd "$srcdir"
|
||||
|
||||
autoreconf -i -f
|
||||
|
||||
./configure "$@"
|
||||
@@ -0,0 +1,27 @@
|
||||
# vlibc — benchmark harnesses (musts/BENCHMARKING.md).
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include
|
||||
AM_CFLAGS = @VLIBC_CFLAGS@
|
||||
|
||||
# Built only on demand (via `make bench`), so `make all` does not need the
|
||||
# library to be built first.
|
||||
EXTRA_PROGRAMS = bench_vlibc
|
||||
bench_vlibc_SOURCES = bench_vlibc.c
|
||||
|
||||
# By default benchmarks link against vlibc itself. --with-libc=glibc links the
|
||||
# same harness against the system glibc; --with-libc=musl builds it with
|
||||
# musl-gcc for the musl reference.
|
||||
if BENCH_LINK_VLIBC
|
||||
bench_vlibc_LDADD = ../libvlibc.la
|
||||
else
|
||||
bench_vlibc_LDADD =
|
||||
endif
|
||||
|
||||
if BENCH_LINK_MUSL
|
||||
CC = $(MUSL_CC)
|
||||
endif
|
||||
|
||||
bench: bench_vlibc
|
||||
./bench_vlibc
|
||||
|
||||
.PHONY: bench
|
||||
@@ -0,0 +1,33 @@
|
||||
# Benchmarking
|
||||
|
||||
Every vlibc component is benchmarked against the software it replaces, per
|
||||
`musts/BENCHMARKING.md`. A component that is slower or worse at its task than
|
||||
the software it replaces is considered failing.
|
||||
|
||||
## Layout
|
||||
|
||||
- Each benchmark harness is a standalone C program in this directory, named
|
||||
`bench_<component>.c`.
|
||||
- `bench_vlibc.c` is the skeleton that per-component benchmarks build on.
|
||||
|
||||
## Running
|
||||
|
||||
```sh
|
||||
./autogen.sh # configure (default: link against vlibc)
|
||||
make bench # build and run the harnesses
|
||||
|
||||
# Reference comparison against the libc vlibc replaces:
|
||||
./autogen.sh --with-libc=glibc
|
||||
make bench
|
||||
|
||||
# musl reference (requires musl-gcc):
|
||||
./autogen.sh --with-libc=musl
|
||||
make bench
|
||||
```
|
||||
|
||||
## Adding a benchmark
|
||||
|
||||
1. Add `bench_<component>.c` here and list it in `benchmarks/Makefile.am`.
|
||||
2. Measure the component against the equivalent glibc (and musl) call.
|
||||
3. Report wall-clock time, throughput, and any binary-size difference.
|
||||
4. If vlibc is slower, the benchmark fails — fix the implementation.
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Benchmark harness for vlibc (musts/BENCHMARKING.md).
|
||||
*
|
||||
* Every vlibc component is benchmarked against the software it replaces.
|
||||
* This stub times vlibc_version() and is the skeleton that per-component
|
||||
* benchmarks build on. Reconfigure with --with-libc=musl or --with-libc=glibc
|
||||
* to link the same harness against a reference libc for comparison.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <vlibc.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#define ITERATIONS 100000000ULL
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
volatile const char *version = NULL;
|
||||
struct timespec start;
|
||||
struct timespec end;
|
||||
double whole;
|
||||
double frac;
|
||||
double seconds;
|
||||
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &start) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (unsigned long long i = 0; i < ITERATIONS; i++)
|
||||
{
|
||||
version = vlibc_version();
|
||||
}
|
||||
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &end) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
whole = (double)(end.tv_sec - start.tv_sec);
|
||||
frac = (double)(end.tv_nsec - start.tv_nsec) / 1000000000.0;
|
||||
seconds = whole + frac;
|
||||
|
||||
printf("vlibc_version() x %llu: %.3f s (%.2f ns/call), version=%s\n", ITERATIONS, seconds,
|
||||
seconds * 1000000000.0 / ITERATIONS, (const char *)version);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
# vlibc
|
||||
@@ -0,0 +1 @@
|
||||
# vlibc
|
||||
@@ -0,0 +1,57 @@
|
||||
[
|
||||
{
|
||||
"file": "bench_vlibc.c",
|
||||
"arguments": [
|
||||
"/usr/sbin/gcc",
|
||||
"-DHAVE_CONFIG_H",
|
||||
"-I.",
|
||||
"-I..",
|
||||
"-I../include",
|
||||
"-std=c23",
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-g",
|
||||
"-O2",
|
||||
"-MT",
|
||||
"bench_vlibc.o",
|
||||
"-MD",
|
||||
"-MP",
|
||||
"-MF",
|
||||
".deps/bench_vlibc.Tpo",
|
||||
"-c",
|
||||
"-o",
|
||||
"bench_vlibc.o",
|
||||
"bench_vlibc.c"
|
||||
],
|
||||
"directory": "/home/specter/vox/vlibc/benchmarks",
|
||||
"output": "bench_vlibc.o"
|
||||
},
|
||||
{
|
||||
"file": "src/vlibc.c",
|
||||
"arguments": [
|
||||
"/usr/sbin/gcc",
|
||||
"-DHAVE_CONFIG_H",
|
||||
"-I.",
|
||||
"-I./include",
|
||||
"-std=c23",
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-g",
|
||||
"-O2",
|
||||
"-MT",
|
||||
"src/vlibc.lo",
|
||||
"-MD",
|
||||
"-MP",
|
||||
"-MF",
|
||||
"src/.deps/vlibc.Tpo",
|
||||
"-c",
|
||||
"src/vlibc.c",
|
||||
"-fPIC",
|
||||
"-DPIC",
|
||||
"-o",
|
||||
"src/.libs/vlibc.o"
|
||||
],
|
||||
"directory": "/home/specter/vox/vlibc",
|
||||
"output": "src/.libs/vlibc.o"
|
||||
}
|
||||
]
|
||||
File diff suppressed because it is too large
Load Diff
+180
@@ -0,0 +1,180 @@
|
||||
# -*- Autoconf -*-
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
#
|
||||
# vlibc — build configuration (see building/C.md and layouts/C.md).
|
||||
|
||||
AC_PREREQ([2.71])
|
||||
|
||||
AC_INIT([vlibc],
|
||||
[0.1.0],
|
||||
[https://vox.dev/vlibc],
|
||||
[vlibc],
|
||||
[https://vox.dev/])
|
||||
|
||||
AC_CONFIG_SRCDIR([include/vlibc.h])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
AM_INIT_AUTOMAKE([foreign subdir-objects])
|
||||
|
||||
# ---- Language / compiler -------------------------------------------------
|
||||
# vlibc is implemented in C. Exactly one compiler is selected, with no fallback
|
||||
# to another (building/C.md): GCC.
|
||||
#
|
||||
# Note: AC_PROG_CC sets $GCC to "yes" for any __GNUC__-compatible compiler
|
||||
# (including clang), so it cannot be used to enforce the single-compiler rule.
|
||||
# Verify the compiler is genuinely GCC, not a compatible one.
|
||||
AC_PROG_CC
|
||||
AC_MSG_CHECKING([whether the compiler is GCC])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [
|
||||
#if !defined(__GNUC__) || defined(__clang__)
|
||||
#error "vlibc requires GCC"
|
||||
#endif
|
||||
])],
|
||||
[AC_MSG_RESULT([yes])],
|
||||
[AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([vlibc must be built with GCC (building/C.md). The active compiler is not GCC; re-run with CC=gcc. No fallback to another compiler is provided.])])
|
||||
|
||||
# Enable standard library extensions / POSIX declarations in the host toolchain.
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
|
||||
# ---- C standard ----------------------------------------------------------
|
||||
# The latest stable C standard is used by default (C23). C2y (C29) is opt-in
|
||||
# until it is ratified (languages/C.md).
|
||||
AC_ARG_ENABLE([c29],
|
||||
[AS_HELP_STRING([--enable-c29],
|
||||
[Enable experimental C2y (C29) mode, incl. defer statements (default: C23)])])
|
||||
|
||||
vlibc_cstd=c23
|
||||
AS_IF([test "x$enable_c29" = "xyes"], [vlibc_cstd=c2y])
|
||||
|
||||
AC_MSG_CHECKING([whether $CC supports -std=$vlibc_cstd])
|
||||
vlibc_save_CFLAGS=$CFLAGS
|
||||
CFLAGS="$CFLAGS -std=$vlibc_cstd"
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])],
|
||||
[AC_MSG_RESULT([yes])],
|
||||
[AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([$CC does not support -std=$vlibc_cstd])])
|
||||
CFLAGS=$vlibc_save_CFLAGS
|
||||
|
||||
AC_SUBST([VLIBC_CFLAGS], ["-std=$vlibc_cstd -Wall -Wextra"])
|
||||
|
||||
# ---- Compatibility profile ----------------------------------------------
|
||||
# Exactly one of the five profiles is active. They are mutually exclusive;
|
||||
# the default is "vlibc" (glibc-extended, but without the spoofing layer).
|
||||
#
|
||||
# 1 --enable-onlyposix pure POSIX, nothing more
|
||||
# 2 --enable-muslmimic musl-like, light
|
||||
# 3 --enable-muslext musl-extended
|
||||
# 4 --enable-spoof glibc replica (drop-in compatibility)
|
||||
# 5 (default) vlibc (glibc-extended)
|
||||
AC_ARG_ENABLE([onlyposix],
|
||||
[AS_HELP_STRING([--enable-onlyposix],
|
||||
[Build the lightest vlibc: pure POSIX, nothing more])])
|
||||
AC_ARG_ENABLE([muslmimic],
|
||||
[AS_HELP_STRING([--enable-muslmimic],
|
||||
[Build a musl-like vlibc: light, musl-compatible])])
|
||||
AC_ARG_ENABLE([muslext],
|
||||
[AS_HELP_STRING([--enable-muslext],
|
||||
[Build musl-extended vlibc: musl plus more])])
|
||||
AC_ARG_ENABLE([spoof],
|
||||
[AS_HELP_STRING([--enable-spoof],
|
||||
[Build a glibc replica: drop-in glibc compatibility])])
|
||||
|
||||
vlibc_profile=vlibc
|
||||
vlibc_profiles=0
|
||||
AS_IF([test "x$enable_onlyposix" = "xyes"],
|
||||
[vlibc_profile=onlyposix; vlibc_profiles=$((vlibc_profiles + 1))])
|
||||
AS_IF([test "x$enable_muslmimic" = "xyes"],
|
||||
[vlibc_profile=muslmimic; vlibc_profiles=$((vlibc_profiles + 1))])
|
||||
AS_IF([test "x$enable_muslext" = "xyes"],
|
||||
[vlibc_profile=muslext; vlibc_profiles=$((vlibc_profiles + 1))])
|
||||
AS_IF([test "x$enable_spoof" = "xyes"],
|
||||
[vlibc_profile=spoof; vlibc_profiles=$((vlibc_profiles + 1))])
|
||||
|
||||
AS_IF([test "$vlibc_profiles" -gt 1],
|
||||
[AC_MSG_ERROR([--enable-onlyposix, --enable-muslmimic, --enable-muslext and --enable-spoof are mutually exclusive])])
|
||||
|
||||
case "$vlibc_profile" in
|
||||
onlyposix) vlibc_level=1 ;;
|
||||
muslmimic) vlibc_level=2 ;;
|
||||
muslext) vlibc_level=3 ;;
|
||||
spoof) vlibc_level=4 ;;
|
||||
vlibc) vlibc_level=5 ;;
|
||||
esac
|
||||
|
||||
AC_DEFINE_UNQUOTED([VLIBC_PROFILE], ["$vlibc_profile"],
|
||||
[Active compatibility profile name])
|
||||
AC_DEFINE_UNQUOTED([VLIBC_LEVEL], [$vlibc_level],
|
||||
[Active compatibility level (1..5)])
|
||||
AS_CASE([$vlibc_profile],
|
||||
[onlyposix], [AC_DEFINE([VLIBC_PROFILE_ONLYPOSIX], [1], [Pure POSIX profile])],
|
||||
[muslmimic], [AC_DEFINE([VLIBC_PROFILE_MUSLMIMIC], [1], [musl-like profile])],
|
||||
[muslext], [AC_DEFINE([VLIBC_PROFILE_MUSLEXT], [1], [musl-extended profile])],
|
||||
[spoof], [AC_DEFINE([VLIBC_PROFILE_SPOOF], [1], [glibc spoof profile])],
|
||||
[vlibc], [AC_DEFINE([VLIBC_PROFILE_VLIBC], [1], [vlibc (glibc-ext) profile])])
|
||||
|
||||
AC_SUBST([vlibc_profile])
|
||||
|
||||
# ---- Install method ------------------------------------------------------
|
||||
# "alongside" installs vlibc next to the system libc: headers and libraries go
|
||||
# under a vlibc-specific tree, used via the vlibc-gcc / vlibc-clang drivers.
|
||||
# "overwrite" replaces the system libc in place.
|
||||
AC_ARG_WITH([install],
|
||||
[AS_HELP_STRING([--with-install=@<:@alongside|overwrite@:>@],
|
||||
[Install method: alongside (default) keeps the system libc; overwrite replaces it])],
|
||||
[],
|
||||
[with_install=alongside])
|
||||
|
||||
AS_CASE([$with_install],
|
||||
[alongside|overwrite], [],
|
||||
[AC_MSG_ERROR([--with-install must be 'alongside' or 'overwrite'])])
|
||||
|
||||
AC_DEFINE_UNQUOTED([VLIBC_INSTALL_MODE], ["$with_install"], [Install mode])
|
||||
AM_CONDITIONAL([INSTALL_OVERWRITE], [test "x$with_install" = "xoverwrite"])
|
||||
AC_SUBST([vlibc_install_mode], ["$with_install"])
|
||||
|
||||
# ---- Static linking ------------------------------------------------------
|
||||
# Full static linking is a hard requirement for every profile except spoof
|
||||
# (the spoofing layer needs dynamic facilities a static build cannot provide).
|
||||
AS_IF([test "x$vlibc_profile" != "xspoof" && test "x$enable_static" = "xno"],
|
||||
[AC_MSG_ERROR([the '$vlibc_profile' profile requires static linking; remove --disable-static])])
|
||||
|
||||
# ---- Reference libc for benchmarks --------------------------------------
|
||||
# Benchmarks are built against the software vlibc replaces (musts/BENCHMARKING.md).
|
||||
# By default they link against vlibc itself; --with-libc selects musl or glibc
|
||||
# for the reference comparison.
|
||||
AC_ARG_WITH([libc],
|
||||
[AS_HELP_STRING([--with-libc=@<:@vlibc|musl|glibc@:>@],
|
||||
[Select the libc that benchmark binaries link against (default: vlibc)])],
|
||||
[],
|
||||
[with_libc=vlibc])
|
||||
|
||||
AS_CASE([$with_libc],
|
||||
[vlibc], [],
|
||||
[glibc], [],
|
||||
[musl],
|
||||
[AC_CHECK_PROG([MUSL_CC], [musl-gcc], [musl-gcc], [])
|
||||
AS_IF([test -z "$MUSL_CC"],
|
||||
[AC_MSG_ERROR([--with-libc=musl requires musl-gcc to be in PATH])])],
|
||||
[AC_MSG_ERROR([--with-libc must be 'vlibc', 'musl', or 'glibc'])])
|
||||
|
||||
AM_CONDITIONAL([BENCH_LINK_VLIBC], [test "x$with_libc" = "xvlibc"])
|
||||
AM_CONDITIONAL([BENCH_LINK_MUSL], [test "x$with_libc" = "xmusl"])
|
||||
|
||||
# ---- Libtool -------------------------------------------------------------
|
||||
LT_INIT
|
||||
|
||||
AC_CONFIG_FILES([Makefile
|
||||
benchmarks/Makefile
|
||||
tools/vlibc-gcc
|
||||
tools/vlibc-clang])
|
||||
|
||||
# Make the generated compiler drivers executable. This must run after the
|
||||
# files are created, so it lives in AC_CONFIG_COMMANDS (not the AC_CONFIG_FILES
|
||||
# trailing command, which runs before generation).
|
||||
AC_CONFIG_COMMANDS([chmod-vlibc-drivers],
|
||||
[chmod +x tools/vlibc-gcc tools/vlibc-clang])
|
||||
|
||||
AC_OUTPUT
|
||||
@@ -0,0 +1,30 @@
|
||||
# Compatibility
|
||||
|
||||
vlibc offers five compatibility profiles, selected at configure time. They are
|
||||
mutually exclusive; the default is `vlibc`.
|
||||
|
||||
| Level | Flag | Profile | What it provides |
|
||||
|-------|----------------------|-------------|---------------------------------------------------------|
|
||||
| 1 | `--enable-onlyposix` | `onlyposix` | Pure POSIX, nothing more — the lightest possible build. |
|
||||
| 2 | `--enable-muslmimic` | `muslmimic` | musl-like, still light, with musl-compatible features. |
|
||||
| 3 | `--enable-muslext` | `muslext` | An extension of musl, adding more. |
|
||||
| 4 | `--enable-spoof` | `spoof` | A glibc replica: emulates glibc for drop-in compatibility, higher than `muslext` or `vlibc` full. |
|
||||
| 5 | *(default)* | `vlibc` | glibc-extended: glibc minus its baggage, plus extended standard features. High (but not spoof-level) glibc compatibility. |
|
||||
|
||||
## Differences from glibc
|
||||
|
||||
- **No legacy baggage.** vlibc targets modern, standard-conforming behavior and
|
||||
drops glibc's deprecated and non-standard behaviors unless a profile
|
||||
explicitly restores them.
|
||||
- **Extended standard features.** The `vlibc` profile adds extensions on top of
|
||||
the C and POSIX standards that glibc does not provide.
|
||||
- **Spoofing is opt-in.** The `--enable-spoof` profile re-enables the
|
||||
long-standing legacy behaviors that scripts rely on, for drop-in
|
||||
compatibility with existing binaries and build systems.
|
||||
|
||||
## Full static linking
|
||||
|
||||
Every profile except `spoof` must be able to link fully statically. The
|
||||
`spoof` profile is exempt: its glibc-emulation layer depends on dynamic
|
||||
facilities (e.g. `dlopen`-based compatibility shims) that a static build cannot
|
||||
provide.
|
||||
@@ -0,0 +1,43 @@
|
||||
# Install methods
|
||||
|
||||
vlibc has two install methods, selected with `--with-install=`.
|
||||
|
||||
## Alongside (default)
|
||||
|
||||
```sh
|
||||
./autogen.sh --with-install=alongside
|
||||
make
|
||||
make install
|
||||
```
|
||||
|
||||
- Does **not** replace the system libc.
|
||||
- Installs headers and libraries under a vlibc-specific tree:
|
||||
`$prefix/lib/vlibc/include` and `$prefix/lib/vlibc/lib`.
|
||||
- Consuming projects use the shipped drivers:
|
||||
|
||||
```sh
|
||||
vlibc-gcc -o app app.c # GCC backend
|
||||
vlibc-clang -o app app.c # Clang backend
|
||||
```
|
||||
|
||||
## Overwrite
|
||||
|
||||
```sh
|
||||
./autogen.sh --with-install=overwrite
|
||||
make
|
||||
make install
|
||||
```
|
||||
|
||||
- Replaces the system libc in place: headers go to `$prefix/include`, libraries
|
||||
to `$prefix/lib`.
|
||||
- The shipped drivers then use the system include/lib paths directly.
|
||||
|
||||
## Compiler drivers
|
||||
|
||||
`vlibc-gcc` and `vlibc-clang` are thin wrappers generated by `configure`. They
|
||||
add vlibc's include and library paths (according to the install method) and
|
||||
delegate to `gcc` / `clang`.
|
||||
|
||||
> **Note:** the drivers are currently stubs. Full sysroot handling for
|
||||
> `overwrite` installs and cross-compilation, and the `-static`/`-lvlibc`
|
||||
> wiring, are added as the library's ABI matures.
|
||||
@@ -0,0 +1,46 @@
|
||||
# Overview
|
||||
|
||||
vlibc is Vox's replacement for glibc: a C and POSIX library that is modern,
|
||||
standard-conforming, and fast. The behavior of the software and its
|
||||
differences from glibc are documented here so they can be understood without
|
||||
reading optimized source.
|
||||
|
||||
## Goals
|
||||
|
||||
- **Replace glibc** for the programs that want a lighter, faster, and cleaner
|
||||
libc, while retaining high compatibility.
|
||||
- **Be benchmarkable**: every component is measured against glibc (and musl);
|
||||
a component slower than what it replaces is considered failing
|
||||
(`musts/BENCHMARKING.md`).
|
||||
- **Static-linking first**: fully static linking is a hard requirement for
|
||||
every profile except `spoof`.
|
||||
- **Honor user flags**: `CFLAGS` and `LDFLAGS` are respected; the build uses
|
||||
exactly one compiler (GCC) with no fallback.
|
||||
|
||||
## Compatibility profiles
|
||||
|
||||
See `docs/compatibility.md` for the five profiles (`onlyposix`, `muslmimic`,
|
||||
`muslext`, `spoof`, `vlibc`) and their differences from glibc.
|
||||
|
||||
## Install methods
|
||||
|
||||
See `docs/install.md` for the `alongside` and `overwrite` install methods and
|
||||
the `vlibc-gcc` / `vlibc-clang` drivers.
|
||||
|
||||
## Compiler intent
|
||||
|
||||
Static linking pulls a whole library into every binary, which is expensive in
|
||||
size. To offset this, the public API declares *intent* to the compiler via
|
||||
attributes such as `__attribute__((const))` and `__attribute__((pure))`. When
|
||||
the compiler knows a call has no side effects and a predictable result, it can
|
||||
fold or eliminate it during optimization, shrinking the final binary even when
|
||||
vlibc is statically linked in full.
|
||||
|
||||
This is a deliberate design constraint: every public function carries the
|
||||
tightest correct intent attribute (see `STYLEGUIDE.md`).
|
||||
|
||||
## Status
|
||||
|
||||
This repository is currently a stub — the layout, build system, documentation,
|
||||
and a minimal public API (`vlibc_version()`) are in place. Individual library
|
||||
components are added incrementally, each with benchmarks.
|
||||
@@ -0,0 +1,45 @@
|
||||
#ifndef VLIBC_H
|
||||
#define VLIBC_H
|
||||
|
||||
/*
|
||||
* vlibc — public API.
|
||||
*
|
||||
* vlibc is Vox's modern replacement for glibc. This header is the public entry
|
||||
* point for vlibc's own extensions; the C and POSIX standard headers
|
||||
* (<stdio.h>, <string.h>, ...) are provided separately and are gated by the
|
||||
* active compatibility profile.
|
||||
*
|
||||
* Compatibility profiles (build-time; see configure.ac and docs/compatibility.md):
|
||||
* 1 onlyposix pure POSIX, nothing more
|
||||
* 2 muslmimic musl-like, light
|
||||
* 3 muslext musl-extended
|
||||
* 4 spoof glibc replica (drop-in compatibility)
|
||||
* 5 vlibc glibc-extended, the default
|
||||
*/
|
||||
|
||||
#define VLIBC_VERSION_MAJOR 0
|
||||
#define VLIBC_VERSION_MINOR 1
|
||||
#define VLIBC_VERSION_PATCH 0
|
||||
|
||||
#define VLIBC_VERSION_STRING "0.1.0"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Return the vlibc version string ("MAJOR.MINOR.PATCH").
|
||||
*
|
||||
* Declared with __attribute__((const)): the result is a compile-time constant
|
||||
* and the call has no observable side effects. Declaring this intent lets the
|
||||
* compiler fold and eliminate the call, which keeps fully statically linked
|
||||
* binaries small (see docs/overview.md, "Compiler intent").
|
||||
*/
|
||||
__attribute__((const)) const char *
|
||||
vlibc_version(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* VLIBC_H */
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <vlibc.h>
|
||||
|
||||
/*
|
||||
* The version string is defined here, in a single translation unit, rather
|
||||
* than in the header, so that only the library owns the object. Consumers use
|
||||
* the VLIBC_VERSION_STRING macro for compile-time access.
|
||||
*/
|
||||
const char *
|
||||
vlibc_version(void)
|
||||
{
|
||||
return VLIBC_VERSION_STRING;
|
||||
}
|
||||
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
# Third-party
|
||||
|
||||
Third-party libraries are vendored here, per `layouts/C.md`.
|
||||
|
||||
## Policy
|
||||
|
||||
- Vendoring is required to prevent dependency hell: vlibc must build from a
|
||||
checked-out tree with no external downloads.
|
||||
- Every vendored dependency records its upstream source, version, and license
|
||||
in a `README` (or `UPSTREAM`) file alongside its sources.
|
||||
- Vendored code is patched in-tree where necessary; patches are documented.
|
||||
|
||||
This directory is intentionally empty for now — the current stub has no
|
||||
third-party dependencies.
|
||||
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
# vlibc-clang — compile and link against vlibc using Clang.
|
||||
#
|
||||
# Generated by configure from tools/vlibc-clang.in. Do not edit directly.
|
||||
# This is the compiler driver that vlibc ships for its consumers.
|
||||
|
||||
prefix='@prefix@'
|
||||
install_mode='@vlibc_install_mode@'
|
||||
profile='@vlibc_profile@'
|
||||
|
||||
case "$install_mode" in
|
||||
overwrite)
|
||||
vlibc_includedir="$prefix/include"
|
||||
vlibc_libdir="$prefix/lib"
|
||||
;;
|
||||
*)
|
||||
vlibc_includedir="$prefix/lib/vlibc/include"
|
||||
vlibc_libdir="$prefix/lib/vlibc/lib"
|
||||
;;
|
||||
esac
|
||||
|
||||
# TODO: full sysroot handling for `overwrite` installs and cross-compilation,
|
||||
# and -static/-lvlibc wiring once the library exports its full ABI.
|
||||
exec clang -isystem "$vlibc_includedir" -L"$vlibc_libdir" "$@"
|
||||
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
# vlibc-gcc — compile and link against vlibc using GCC.
|
||||
#
|
||||
# Generated by configure from tools/vlibc-gcc.in. Do not edit directly.
|
||||
# This is the compiler driver that vlibc ships for its consumers.
|
||||
|
||||
prefix='@prefix@'
|
||||
install_mode='@vlibc_install_mode@'
|
||||
profile='@vlibc_profile@'
|
||||
|
||||
case "$install_mode" in
|
||||
overwrite)
|
||||
vlibc_includedir="$prefix/include"
|
||||
vlibc_libdir="$prefix/lib"
|
||||
;;
|
||||
*)
|
||||
vlibc_includedir="$prefix/lib/vlibc/include"
|
||||
vlibc_libdir="$prefix/lib/vlibc/lib"
|
||||
;;
|
||||
esac
|
||||
|
||||
# TODO: full sysroot handling for `overwrite` installs and cross-compilation,
|
||||
# and -static/-lvlibc wiring once the library exports its full ABI.
|
||||
exec gcc -isystem "$vlibc_includedir" -L"$vlibc_libdir" "$@"
|
||||
Reference in New Issue
Block a user