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:
2026-08-31 17:06:01 -04:00
parent 3f63ae1cdd
commit 180c1107b6
25 changed files with 17796 additions and 1 deletions
+37
View File
@@ -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
View File
@@ -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
+19
View 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
View File
@@ -52,3 +52,54 @@ Module.symvers
Mkfile.old Mkfile.old
dkms.conf 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
+76
View File
@@ -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
View File
@@ -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
+70 -1
View File
@@ -1,3 +1,72 @@
# vlibc # 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.
+83
View File
@@ -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
View File
@@ -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 "$@"
+27
View File
@@ -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
+33
View File
@@ -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.
+53
View File
@@ -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;
}
+1
View File
@@ -0,0 +1 @@
# vlibc
+1
View File
@@ -0,0 +1 @@
# vlibc
+57
View File
@@ -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"
}
]
Vendored Executable
+16775
View File
File diff suppressed because it is too large Load Diff
+180
View File
@@ -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
+30
View File
@@ -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.
+43
View File
@@ -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.
+46
View File
@@ -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.
+45
View File
@@ -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
View File
@@ -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;
}
+14
View File
@@ -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.
+24
View File
@@ -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" "$@"
+24
View File
@@ -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" "$@"