Add autotools build system (static-only, C17)
configure.ac enforces C17 and Linux/x86_64, refuses in-tree configure; Makefile.am builds libc.a plus crt0.o; the driver Makefile dispatches out-of-tree builds into bin/release (-O2) and bin/debug (-O0 -g). Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <[email protected]>
This commit is contained in:
@@ -0,0 +1,61 @@
|
|||||||
|
# Driver Makefile — nulsl-libc
|
||||||
|
#
|
||||||
|
# This is the HAND-WRITTEN top-level makefile (committed to git). It never
|
||||||
|
# runs the autotools machinery in-tree; instead it drives two out-of-tree
|
||||||
|
# builds, one per bin/ directory, exactly as the Null Linux guidelines want:
|
||||||
|
#
|
||||||
|
# make release -> ./configure CFLAGS='-O2' into bin/release/
|
||||||
|
# make debug -> ./configure CFLAGS='-O0 -g' into bin/debug/
|
||||||
|
#
|
||||||
|
# Run `./autogen.sh` once after cloning (or just run `make release` — it
|
||||||
|
# regenerates the configure script itself when needed).
|
||||||
|
#
|
||||||
|
# Never run `./configure` at the repository root: configure.ac refuses it.
|
||||||
|
|
||||||
|
.PHONY: all release debug bench check clean distclean compile_commands
|
||||||
|
|
||||||
|
all: release
|
||||||
|
|
||||||
|
# --- bootstrapping ---------------------------------------------------------
|
||||||
|
|
||||||
|
# Regenerates configure (and friends) when autogen.sh is newer.
|
||||||
|
configure: autogen.sh
|
||||||
|
./autogen.sh
|
||||||
|
|
||||||
|
# --- builds ----------------------------------------------------------------
|
||||||
|
|
||||||
|
# Release is ALWAYS -O2 (project guideline #4).
|
||||||
|
bin/release/Makefile: configure
|
||||||
|
@mkdir -p bin/release
|
||||||
|
@cd bin/release && ../../configure CFLAGS='-O2'
|
||||||
|
|
||||||
|
bin/debug/Makefile: configure
|
||||||
|
@mkdir -p bin/debug
|
||||||
|
@cd bin/debug && ../../configure CFLAGS='-O0 -g'
|
||||||
|
|
||||||
|
release: bin/release/Makefile
|
||||||
|
$(MAKE) -C bin/release
|
||||||
|
|
||||||
|
debug: bin/debug/Makefile
|
||||||
|
$(MAKE) -C bin/debug
|
||||||
|
|
||||||
|
# --- developer conveniences -------------------------------------------------
|
||||||
|
|
||||||
|
bench: release
|
||||||
|
$(MAKE) -C bin/release bench
|
||||||
|
|
||||||
|
check: release
|
||||||
|
$(MAKE) -C bin/release check
|
||||||
|
|
||||||
|
# LSP support: compile_commands.json for clangd (requires `bear`).
|
||||||
|
compile_commands: release
|
||||||
|
@command -v bear >/dev/null 2>&1 || { \
|
||||||
|
echo "error: 'bear' is not installed (sudo pacman -S bear, apt install bear, ...)"; exit 1; }
|
||||||
|
@cd bin/release && bear --output ../../compile_commands.json -- $(MAKE) clean all
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@test ! -f bin/release/Makefile || $(MAKE) -C bin/release clean
|
||||||
|
@test ! -f bin/debug/Makefile || $(MAKE) -C bin/debug clean
|
||||||
|
|
||||||
|
distclean: clean
|
||||||
|
rm -rf bin/release bin/debug
|
||||||
+66
@@ -0,0 +1,66 @@
|
|||||||
|
# Makefile.am — nulsl-libc
|
||||||
|
#
|
||||||
|
# This is the AUTOTOOLS makefile. It is only ever instantiated by a configure
|
||||||
|
# run inside bin/release/ or bin/debug/ (never at the repository root).
|
||||||
|
#
|
||||||
|
# Everything is a static library. No libtool, no shared objects, no dynamic
|
||||||
|
# linker. See docs/architecture.md.
|
||||||
|
#
|
||||||
|
# Benchmarks and tests live in one Makefile on purpose: automake orders
|
||||||
|
# targets by dependency, so libc.a (and crt0.o) are guaranteed to exist
|
||||||
|
# before any -nostdlib binary links against them. With SUBDIRS, recursion
|
||||||
|
# builds the subdirectories first and linking breaks.
|
||||||
|
|
||||||
|
AUTOMAKE_OPTIONS = foreign
|
||||||
|
|
||||||
|
AM_CPPFLAGS = -I$(top_srcdir)/include
|
||||||
|
AM_CFLAGS = -std=c17 -ffreestanding -fno-builtin -fno-stack-protector \
|
||||||
|
-Wall -Wextra -Wshadow -Wpointer-arith
|
||||||
|
|
||||||
|
lib_LIBRARIES = libc.a
|
||||||
|
|
||||||
|
libc_a_SOURCES = \
|
||||||
|
src/errno.c \
|
||||||
|
src/stdio.c \
|
||||||
|
src/stdlib.c \
|
||||||
|
src/string.c \
|
||||||
|
src/syscall.c \
|
||||||
|
src/unistd.c
|
||||||
|
|
||||||
|
# The C runtime entry point is deliberately NOT a member of libc.a: nothing
|
||||||
|
# references _start, so the linker would never extract it from an archive.
|
||||||
|
# It is built as a standalone object and linked explicitly by everything
|
||||||
|
# that wants a runnable binary.
|
||||||
|
noinst_DATA = crt0.o
|
||||||
|
crt0.o: $(top_srcdir)/src/crt/crt0.S
|
||||||
|
$(CC) $(AM_CPPFLAGS) $(CFLAGS) -c -o $@ $<
|
||||||
|
CLEANFILES = crt0.o
|
||||||
|
|
||||||
|
EXTRA_DIST = autogen.sh
|
||||||
|
|
||||||
|
# --- benchmarks ------------------------------------------------------------
|
||||||
|
# Fully static, -nostdlib: the numbers reflect exactly what ships.
|
||||||
|
|
||||||
|
noinst_PROGRAMS = benchmarks/bench_strlen benchmarks/bench_syscall
|
||||||
|
|
||||||
|
benchmarks_bench_strlen_SOURCES = benchmarks/bench_strlen.c
|
||||||
|
benchmarks_bench_strlen_LDADD = crt0.o libc.a -lgcc
|
||||||
|
benchmarks_bench_strlen_LDFLAGS = -nostdlib -static -no-pie -Wno-unused-command-line-argument
|
||||||
|
|
||||||
|
benchmarks_bench_syscall_SOURCES = benchmarks/bench_syscall.c
|
||||||
|
benchmarks_bench_syscall_LDADD = crt0.o libc.a -lgcc
|
||||||
|
benchmarks_bench_syscall_LDFLAGS = -nostdlib -static -no-pie -Wno-unused-command-line-argument
|
||||||
|
|
||||||
|
.PHONY: bench
|
||||||
|
bench: all
|
||||||
|
./benchmarks/bench_strlen
|
||||||
|
./benchmarks/bench_syscall
|
||||||
|
|
||||||
|
# --- tests ------------------------------------------------------------------
|
||||||
|
|
||||||
|
check_PROGRAMS = tests/smoke
|
||||||
|
TESTS = tests/smoke
|
||||||
|
|
||||||
|
tests_smoke_SOURCES = tests/smoke.c
|
||||||
|
tests_smoke_LDADD = crt0.o libc.a -lgcc
|
||||||
|
tests_smoke_LDFLAGS = -nostdlib -static -no-pie -Wno-unused-command-line-argument
|
||||||
Executable
+19
@@ -0,0 +1,19 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# autogen.sh — regenerate all autotools machinery.
|
||||||
|
#
|
||||||
|
# Usage: ./autogen.sh (then: make release / make debug / make bench)
|
||||||
|
#
|
||||||
|
# Never run ./configure at the repository root — use the driver Makefile
|
||||||
|
# targets instead, which configure out-of-tree into bin/{release,debug}.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
autoreconf -i -f -v
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "autotools machinery regenerated."
|
||||||
|
echo "next: make release (bin/release/, CFLAGS='-O2')"
|
||||||
|
echo " make debug (bin/debug/, CFLAGS='-O0 -g')"
|
||||||
|
echo " make bench (benchmarks against the release build)"
|
||||||
|
echo " make check (smoke tests)"
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
dnl configure.ac — nulsl-libc, a very lightweight C17 libc for Linux.
|
||||||
|
dnl
|
||||||
|
dnl Static-only on purpose: the dynamic linker is a memory tax we refuse to
|
||||||
|
dnl pay (see docs/architecture.md). libc.a is a plain archive, so no libtool.
|
||||||
|
dnl
|
||||||
|
dnl IMPORTANT: never run ./configure at the repository root. The root holds a
|
||||||
|
dnl hand-written driver Makefile that builds into bin/{release,debug}; the
|
||||||
|
dnl guard below refuses to overwrite it.
|
||||||
|
|
||||||
|
AC_PREREQ([2.71])
|
||||||
|
AC_INIT([nulsl-libc], [0.1.0], [], [nulsl-libc],
|
||||||
|
[https://git.spectoria.dev/The-Null-Linux-Project/nulsl-libc])
|
||||||
|
AC_CONFIG_SRCDIR([include/stdio.h])
|
||||||
|
AC_CONFIG_AUX_DIR([build-aux])
|
||||||
|
AC_CANONICAL_HOST
|
||||||
|
|
||||||
|
AM_INIT_AUTOMAKE([foreign subdir-objects])
|
||||||
|
|
||||||
|
dnl C17, and only C17 (project guideline #1). Modern autoconf ships no
|
||||||
|
dnl AC_PROG_CC_C17 macro, so prove it with a compile test instead.
|
||||||
|
AC_PROG_CC
|
||||||
|
saved_CFLAGS="$CFLAGS"
|
||||||
|
CFLAGS="$CFLAGS -std=c17"
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#if __STDC_VERSION__ < 201710L
|
||||||
|
#error "not C17"
|
||||||
|
#endif
|
||||||
|
], [])],
|
||||||
|
[],
|
||||||
|
[AC_MSG_ERROR([nulsl-libc requires a C17 compiler (GCC >= 8 or Clang >= 6); -std=c17 was rejected])])
|
||||||
|
CFLAGS="$saved_CFLAGS"
|
||||||
|
|
||||||
|
dnl Target validation: Linux on x86_64, for now.
|
||||||
|
AS_CASE([$host_os],
|
||||||
|
[linux*], [],
|
||||||
|
[AC_MSG_ERROR([nulsl-libc currently targets Linux only (configured for $host_os)])])
|
||||||
|
AS_CASE([$host_cpu],
|
||||||
|
[x86_64], [],
|
||||||
|
[AC_MSG_ERROR([nulsl-libc currently targets x86_64 only (configured for $host_cpu); src/arch/ is where new ports go])])
|
||||||
|
|
||||||
|
dnl Plain archives need ar/ranlib; no libtool, no shared objects.
|
||||||
|
AC_CHECK_TOOL([AR], [ar])
|
||||||
|
AC_PROG_RANLIB
|
||||||
|
|
||||||
|
dnl Refuse in-tree configuration: it would clobber the committed driver
|
||||||
|
dnl Makefile that dispatches into bin/{release,debug}.
|
||||||
|
AS_IF([test "x$srcdir" = "x." && test -f Makefile],
|
||||||
|
[AC_MSG_ERROR([in-tree builds are disabled — run 'make release' or 'make debug' from the repository root instead])])
|
||||||
|
|
||||||
|
AC_CONFIG_FILES([Makefile])
|
||||||
|
AC_OUTPUT
|
||||||
Reference in New Issue
Block a user