build: wire new src dirs, crt objects, and make check into Autotools
This commit is contained in:
+11
@@ -107,3 +107,14 @@ Makefile.in
|
|||||||
/benchmarks/bench_vlibc
|
/benchmarks/bench_vlibc
|
||||||
/benchmarks/bench_string
|
/benchmarks/bench_string
|
||||||
|
|
||||||
|
# make check outputs: static test binaries + parallel-test logs (todo 6).
|
||||||
|
/test_*
|
||||||
|
/test-suite.log
|
||||||
|
/tests/startup_modes.sh.log
|
||||||
|
/tests/startup_modes.sh.trs
|
||||||
|
|
||||||
|
# make dist outputs.
|
||||||
|
/vlibc-*.tar.gz
|
||||||
|
/vlibc-*/
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+225
-6
@@ -2,23 +2,110 @@
|
|||||||
|
|
||||||
SUBDIRS = benchmarks
|
SUBDIRS = benchmarks
|
||||||
|
|
||||||
AM_CPPFLAGS = -I$(top_srcdir)/include
|
# Build-dir include FIRST: configure generates include/vlibc/features.h
|
||||||
|
# (from the .in template) into the BUILD tree, and a VPATH build must find
|
||||||
|
# the generated header before the source tree's checked-in headers.
|
||||||
|
AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
|
||||||
AM_CFLAGS = @VLIBC_CFLAGS@
|
AM_CFLAGS = @VLIBC_CFLAGS@
|
||||||
|
|
||||||
# ---- Library -------------------------------------------------------------
|
# ---- Library -------------------------------------------------------------
|
||||||
vlibc_include_HEADERS = include/vlibc.h include/stddef.h include/string.h
|
|
||||||
|
# Authoritative source-dir inventory (todo 6). Every directory a later plan
|
||||||
|
# todo creates is enumerated here ONCE, so no area can be forgotten; each is
|
||||||
|
# appended to libvlibc_la_SOURCES WHEN ITS TODO LANDS — the list grows
|
||||||
|
# incrementally and never references a directory that does not exist yet:
|
||||||
|
#
|
||||||
|
# W1 (wired now): src/internal, src/start, src/errno,
|
||||||
|
# src/setjmp/x86_64, src/string, crt/ (crt1.o)
|
||||||
|
# todo 7 src/malloc todo 39-42 src/math todo 50 src/multibyte
|
||||||
|
# todo 11-14 src/stdlib todo 43 src/complex todo 53-54 src/regex
|
||||||
|
# todo 15-18 src/stdio todo 9,51 src/ctype todo 57-58 src/network
|
||||||
|
# todo 19,38 src/unistd todo 55 src/search todo 59 src/mq
|
||||||
|
# todo 20,23,56 src/process todo 66 src/crypt todo 60 src/aio
|
||||||
|
# todo 21 src/fcntl todo 44-48 src/thread todo 61 src/ipc
|
||||||
|
# todo 22,34 src/stat todo 49,52 src/locale todo 62-63 src/ldso
|
||||||
|
# todo 24 src/dirent todo 42 src/fenv/x86_64
|
||||||
|
# todo 25 src/select
|
||||||
|
# todo 26-27 src/time
|
||||||
|
# todo 28 src/signal
|
||||||
|
# todo 29 src/termios
|
||||||
|
# todo 30 src/uio
|
||||||
|
# todo 31 src/resource
|
||||||
|
# todo 32,36,54,61,67 src/misc
|
||||||
|
# todo 33 src/mman
|
||||||
|
# todo 35 src/sys
|
||||||
|
# todo 37 src/passwd
|
||||||
|
# todo 37 src/group
|
||||||
|
#
|
||||||
|
# NOTE: crt/x86_64/crt1.s is NOT a library source — it is assembled into the
|
||||||
|
# standalone crt1.o below (the sole crt owner; todo 64 reuses, never rebuilds).
|
||||||
|
|
||||||
|
# Level-independent L1 core (wired today + the pre-plan string slice).
|
||||||
|
VLIBC_CORE_SRCS = \
|
||||||
|
src/vlibc.c \
|
||||||
|
src/internal/assert_fail.c \
|
||||||
|
src/internal/errno.c \
|
||||||
|
src/internal/syscall_ret.c \
|
||||||
|
src/start/libc_start_main.c \
|
||||||
|
src/start/exit.c \
|
||||||
|
src/start/environ.c \
|
||||||
|
src/start/tls.c \
|
||||||
|
src/errno/strerror.c \
|
||||||
|
src/setjmp/x86_64/setjmp.s \
|
||||||
|
src/setjmp/x86_64/longjmp.s \
|
||||||
|
src/setjmp/x86_64/sigsetjmp.s \
|
||||||
|
src/setjmp/x86_64/siglongjmp.s \
|
||||||
|
src/string/strlen.c \
|
||||||
|
src/string/strcmp.c \
|
||||||
|
src/string/memcpy.c \
|
||||||
|
src/string/memmove.c \
|
||||||
|
src/string/memset.c
|
||||||
|
|
||||||
|
# Profile-gated sources, EXISTING gates preserved (strlcpy/strlcat stay L2
|
||||||
|
# BSD, strcasestr stays L3 GNU — NOT promoted).
|
||||||
|
VLIBC_LEVEL2_SRCS = src/string/strlcpy.c src/string/strlcat.c
|
||||||
|
VLIBC_LEVEL3_SRCS = src/string/strcasestr.c
|
||||||
|
|
||||||
vlibc_lib_LTLIBRARIES = libvlibc.la
|
vlibc_lib_LTLIBRARIES = libvlibc.la
|
||||||
|
|
||||||
libvlibc_la_SOURCES = src/vlibc.c src/string/strlen.c src/string/strcmp.c \
|
libvlibc_la_SOURCES = $(VLIBC_CORE_SRCS)
|
||||||
src/string/memcpy.c src/string/memmove.c src/string/memset.c
|
|
||||||
if PROFILE_GE_2
|
if PROFILE_GE_2
|
||||||
libvlibc_la_SOURCES += src/string/strlcpy.c src/string/strlcat.c
|
libvlibc_la_SOURCES += $(VLIBC_LEVEL2_SRCS)
|
||||||
endif
|
endif
|
||||||
if PROFILE_GE_3
|
if PROFILE_GE_3
|
||||||
libvlibc_la_SOURCES += src/string/strcasestr.c
|
libvlibc_la_SOURCES += $(VLIBC_LEVEL3_SRCS)
|
||||||
endif
|
endif
|
||||||
libvlibc_la_LDFLAGS = -version-info 0:0:0 -no-undefined
|
libvlibc_la_LDFLAGS = -version-info 0:0:0 -no-undefined
|
||||||
|
|
||||||
|
# ---- Public headers ------------------------------------------------------
|
||||||
|
# The whole public header inventory (the 3 scaffold headers plus todo 5's
|
||||||
|
# skeleton); the profile-gated generated features.h is installed separately
|
||||||
|
# below.
|
||||||
|
vlibc_include_HEADERS = \
|
||||||
|
include/vlibc.h \
|
||||||
|
include/stddef.h \
|
||||||
|
include/string.h \
|
||||||
|
include/errno.h \
|
||||||
|
include/setjmp.h \
|
||||||
|
include/assert.h \
|
||||||
|
include/cpio.h \
|
||||||
|
include/float.h \
|
||||||
|
include/iso646.h \
|
||||||
|
include/limits.h \
|
||||||
|
include/stdalign.h \
|
||||||
|
include/stdarg.h \
|
||||||
|
include/stdatomic.h \
|
||||||
|
include/stdbit.h \
|
||||||
|
include/stdbool.h \
|
||||||
|
include/stdckdint.h \
|
||||||
|
include/stdint.h \
|
||||||
|
include/stdnoreturn.h \
|
||||||
|
include/tar.h \
|
||||||
|
include/tgmath.h \
|
||||||
|
include/threads.h \
|
||||||
|
include/uchar.h \
|
||||||
|
include/sys/types.h
|
||||||
|
|
||||||
# Install location depends on the install method (see configure.ac).
|
# Install location depends on the install method (see configure.ac).
|
||||||
if INSTALL_OVERWRITE
|
if INSTALL_OVERWRITE
|
||||||
vlibc_includedir = $(includedir)
|
vlibc_includedir = $(includedir)
|
||||||
@@ -38,6 +125,17 @@ nodist_vlibc_features_HEADERS = include/vlibc/features.h
|
|||||||
# ---- Compiler drivers ----------------------------------------------------
|
# ---- Compiler drivers ----------------------------------------------------
|
||||||
bin_SCRIPTS = tools/vlibc-gcc tools/vlibc-clang
|
bin_SCRIPTS = tools/vlibc-gcc tools/vlibc-clang
|
||||||
|
|
||||||
|
# ---- crt objects ---------------------------------------------------------
|
||||||
|
# crt1.o (from crt/x86_64/crt1.s) is built here and ONLY here: todo 64
|
||||||
|
# reuses these objects for the shared build and must NOT rebuild them.
|
||||||
|
# Built by `make all` via all-local so a static vlibc link always has its
|
||||||
|
# entry object available next to the archive.
|
||||||
|
|
||||||
|
crt1.o: crt/x86_64/crt1.s
|
||||||
|
$(AM_V_GEN)$(CC) $(AM_CPPFLAGS) $(CPPFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
all-local: crt1.o
|
||||||
|
|
||||||
# ---- Targets -------------------------------------------------------------
|
# ---- Targets -------------------------------------------------------------
|
||||||
# layouts/C.md requires `make debug`, `make release`, `make bench` and
|
# layouts/C.md requires `make debug`, `make release`, `make bench` and
|
||||||
# `make clean`; build outputs land in bin/{release,debug}.
|
# `make clean`; build outputs land in bin/{release,debug}.
|
||||||
@@ -50,6 +148,7 @@ debug:
|
|||||||
$(MKDIR_P) bin/debug
|
$(MKDIR_P) bin/debug
|
||||||
-cp -P .libs/libvlibc.so* bin/debug/
|
-cp -P .libs/libvlibc.so* bin/debug/
|
||||||
-cp .libs/libvlibc.a bin/debug/
|
-cp .libs/libvlibc.a bin/debug/
|
||||||
|
-cp crt1.o bin/debug/
|
||||||
|
|
||||||
release:
|
release:
|
||||||
$(MAKE) clean
|
$(MAKE) clean
|
||||||
@@ -57,6 +156,7 @@ release:
|
|||||||
$(MKDIR_P) bin/release
|
$(MKDIR_P) bin/release
|
||||||
-cp -P .libs/libvlibc.so* bin/release/
|
-cp -P .libs/libvlibc.so* bin/release/
|
||||||
-cp .libs/libvlibc.a bin/release/
|
-cp .libs/libvlibc.a bin/release/
|
||||||
|
-cp crt1.o bin/release/
|
||||||
|
|
||||||
bench: all
|
bench: all
|
||||||
$(MAKE) -C benchmarks bench
|
$(MAKE) -C benchmarks bench
|
||||||
@@ -68,3 +168,122 @@ compile-commands: clean
|
|||||||
bear --append -- $(MAKE) -C benchmarks bench_vlibc
|
bear --append -- $(MAKE) -C benchmarks bench_vlibc
|
||||||
|
|
||||||
.PHONY: debug release bench compile-commands
|
.PHONY: debug release bench compile-commands
|
||||||
|
|
||||||
|
# ---- make check ----------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Every test binary is a STATIC VLIBC EXECUTABLE: linked with -nostdlib
|
||||||
|
# -static -no-pie against crt1.o + a dedicated level-2 test archive. No
|
||||||
|
# glibc symbol can resolve, so each test genuinely proves self-hosting.
|
||||||
|
#
|
||||||
|
# The test archive (libvlibc-check.a) is compiled from the FULL source list
|
||||||
|
# (all levels included) at VLIBC_LEVEL=2 — the complete L1+L2 surface —
|
||||||
|
# INDEPENDENT of the configured profile. Rationale: some tests exercise
|
||||||
|
# L2-gated functions (test_strerror calls strerror_r, future tests call
|
||||||
|
# bcopy etc.), which a level-1 configured archive does not provide; the
|
||||||
|
# shipped libvlibc.a keeps the profile gating configured at build time.
|
||||||
|
# Object files are plain `ar` members compiled directly with $(CC) — no
|
||||||
|
# libtool (libtool's build-dir libvlibc.a is a wrapper script, and only
|
||||||
|
# .libs/libvlibc.a is linkable, which is a level-gated profile archive).
|
||||||
|
#
|
||||||
|
# Mechanics (extend here for future tests):
|
||||||
|
# - Add the binary to check_PROGRAMS + TESTS with
|
||||||
|
# `<bin>_SOURCES = tests/test_x.c`,
|
||||||
|
# `<bin>_CFLAGS = $(VLIBC_TEST_CFLAGS)` (renames the object to
|
||||||
|
# `<bin>-<src>.o` automatically),
|
||||||
|
# `<bin>_LINK = $(VLIBC_TEST_LINK)` and
|
||||||
|
# `<bin>_LDADD = $(VLIBC_TEST_LDADD)` (static vlibc link; the crt
|
||||||
|
# object + archive must be in LDADD so they follow the test object).
|
||||||
|
# - Multi-mode tests run through tests/startup_modes.sh (see that file).
|
||||||
|
|
||||||
|
VLIBC_TEST_LEVEL = 2
|
||||||
|
|
||||||
|
VLIBC_CHECK_SRCS = $(VLIBC_CORE_SRCS) $(VLIBC_LEVEL2_SRCS) \
|
||||||
|
$(VLIBC_LEVEL3_SRCS)
|
||||||
|
VLIBC_CHECK_OBJECTS_FROM_C = $(VLIBC_CHECK_SRCS:.c=.check.o)
|
||||||
|
VLIBC_CHECK_OBJECTS = $(VLIBC_CHECK_OBJECTS_FROM_C:.s=.check.o)
|
||||||
|
VLIBC_CHECK_CFLAGS = @VLIBC_CFLAGS@ -DVLIBC_LEVEL=$(VLIBC_TEST_LEVEL) -fno-pic
|
||||||
|
|
||||||
|
# The archive itself (plain ar: members compiled at the test level).
|
||||||
|
libvlibc-check.a: $(VLIBC_CHECK_OBJECTS)
|
||||||
|
$(AR) $(ARFLAGS) $@ $^
|
||||||
|
|
||||||
|
# Library sources compiled at the test level. Deliberately no
|
||||||
|
# -DHAVE_CONFIG_H and no $(DEFS): config.h pins the PROFILE level, which
|
||||||
|
# would override -DVLIBC_LEVEL (last definition wins), so the check objects
|
||||||
|
# must get their level from <vlibc/features.h> alone.
|
||||||
|
%.check.o: %.c
|
||||||
|
$(AM_V_CC)$(CC) $(AM_CPPFLAGS) $(CPPFLAGS) $(VLIBC_CHECK_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
%.check.o: %.s
|
||||||
|
$(AM_V_CCAS)$(CC) $(AM_CPPFLAGS) $(CPPFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
# Static vlibc link for every check program. automake links
|
||||||
|
# "$(<bin>_LINK) $(<bin>_OBJECTS) $(<bin>_LDADD) $(LIBS)", so the entry
|
||||||
|
# object, the level-2 archive and libgcc go in LDADD — they MUST follow the
|
||||||
|
# test object or the archive would see no undefined symbols and stay
|
||||||
|
# unextracted. -nostdlib means -lgcc is not auto-added, so it is spelled
|
||||||
|
# out (permitted libgcc helpers).
|
||||||
|
VLIBC_TEST_LINK = $(CC) -nostdlib -static -no-pie -o $@
|
||||||
|
VLIBC_TEST_LDADD = crt1.o libvlibc-check.a -lgcc
|
||||||
|
|
||||||
|
# Test TUs: no stack protector (the library is protector-free at this stage),
|
||||||
|
# non-PIC, level overridden to the test level so L2 declarations are visible.
|
||||||
|
VLIBC_TEST_CFLAGS = -DVLIBC_LEVEL=$(VLIBC_TEST_LEVEL) -fno-stack-protector \
|
||||||
|
-fno-pic -fno-pie
|
||||||
|
|
||||||
|
check_PROGRAMS = test_syscall test_strerror test_setjmp test_headers \
|
||||||
|
test_startup
|
||||||
|
|
||||||
|
test_syscall_SOURCES = tests/syscall_test.c
|
||||||
|
test_syscall_CFLAGS = $(VLIBC_TEST_CFLAGS)
|
||||||
|
test_syscall_DEPENDENCIES = crt1.o libvlibc-check.a
|
||||||
|
test_syscall_LINK = $(VLIBC_TEST_LINK)
|
||||||
|
test_syscall_LDADD = $(VLIBC_TEST_LDADD)
|
||||||
|
|
||||||
|
test_strerror_SOURCES = tests/test_strerror.c
|
||||||
|
test_strerror_CFLAGS = $(VLIBC_TEST_CFLAGS)
|
||||||
|
test_strerror_DEPENDENCIES = crt1.o libvlibc-check.a
|
||||||
|
test_strerror_LINK = $(VLIBC_TEST_LINK)
|
||||||
|
test_strerror_LDADD = $(VLIBC_TEST_LDADD)
|
||||||
|
|
||||||
|
test_setjmp_SOURCES = tests/test_setjmp.c
|
||||||
|
test_setjmp_CFLAGS = $(VLIBC_TEST_CFLAGS)
|
||||||
|
test_setjmp_DEPENDENCIES = crt1.o libvlibc-check.a
|
||||||
|
test_setjmp_LINK = $(VLIBC_TEST_LINK)
|
||||||
|
test_setjmp_LDADD = $(VLIBC_TEST_LDADD)
|
||||||
|
|
||||||
|
test_headers_SOURCES = tests/test_headers.c
|
||||||
|
test_headers_CFLAGS = $(VLIBC_TEST_CFLAGS)
|
||||||
|
test_headers_DEPENDENCIES = crt1.o libvlibc-check.a
|
||||||
|
test_headers_LINK = $(VLIBC_TEST_LINK)
|
||||||
|
test_headers_LDADD = $(VLIBC_TEST_LDADD)
|
||||||
|
|
||||||
|
test_startup_SOURCES = tests/test_startup.c
|
||||||
|
test_startup_CFLAGS = $(VLIBC_TEST_CFLAGS)
|
||||||
|
test_startup_DEPENDENCIES = crt1.o libvlibc-check.a
|
||||||
|
test_startup_LINK = $(VLIBC_TEST_LINK)
|
||||||
|
test_startup_LDADD = $(VLIBC_TEST_LDADD)
|
||||||
|
|
||||||
|
# test_startup's default mode exits 42 by design, so it is NOT a bare TESTS
|
||||||
|
# entry; tests/startup_modes.sh runs its full mode matrix and the -f failure
|
||||||
|
# scenarios of the other four binaries.
|
||||||
|
TESTS = test_syscall test_strerror test_setjmp test_headers \
|
||||||
|
tests/startup_modes.sh
|
||||||
|
|
||||||
|
CLEANFILES = crt1.o libvlibc-check.a $(VLIBC_CHECK_OBJECTS)
|
||||||
|
|
||||||
|
# Distributed but not installed / not otherwise picked up by automake.
|
||||||
|
# (TESTS scripts are not auto-distributed, so the mode runner is explicit.)
|
||||||
|
EXTRA_DIST = \
|
||||||
|
crt/x86_64/crt1.s \
|
||||||
|
include/vlibc/internal/test.h \
|
||||||
|
tests/conformance/symbols.list \
|
||||||
|
tests/startup_modes.sh \
|
||||||
|
arch/x86_64/syscall_arch.h \
|
||||||
|
src/internal/atomic.h \
|
||||||
|
src/internal/errno.h \
|
||||||
|
src/internal/libc.h \
|
||||||
|
src/internal/syscall.h \
|
||||||
|
src/internal/types.h \
|
||||||
|
src/start/start.h \
|
||||||
|
src/start/tcb.h
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
# vlibc — benchmark harnesses (musts/BENCHMARKING.md).
|
# vlibc — benchmark harnesses (musts/BENCHMARKING.md).
|
||||||
|
|
||||||
AM_CPPFLAGS = -I$(top_srcdir)/include
|
# Build-dir include FIRST (generated features.h lives there in VPATH builds).
|
||||||
|
AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
|
||||||
AM_CFLAGS = @VLIBC_CFLAGS@
|
AM_CFLAGS = @VLIBC_CFLAGS@
|
||||||
|
|
||||||
# Built only on demand (via `make bench`), so `make all` does not need the
|
# Built only on demand (via `make bench`), so `make all` does not need the
|
||||||
|
|||||||
@@ -686,6 +686,11 @@ PROFILE_GE_2_TRUE
|
|||||||
vlibc_level
|
vlibc_level
|
||||||
vlibc_profile
|
vlibc_profile
|
||||||
VLIBC_CFLAGS
|
VLIBC_CFLAGS
|
||||||
|
am__fastdepCCAS_FALSE
|
||||||
|
am__fastdepCCAS_TRUE
|
||||||
|
CCASDEPMODE
|
||||||
|
CCASFLAGS
|
||||||
|
CCAS
|
||||||
am__fastdepCC_FALSE
|
am__fastdepCC_FALSE
|
||||||
am__fastdepCC_TRUE
|
am__fastdepCC_TRUE
|
||||||
CCDEPMODE
|
CCDEPMODE
|
||||||
@@ -806,6 +811,8 @@ CFLAGS
|
|||||||
LDFLAGS
|
LDFLAGS
|
||||||
LIBS
|
LIBS
|
||||||
CPPFLAGS
|
CPPFLAGS
|
||||||
|
CCAS
|
||||||
|
CCASFLAGS
|
||||||
LT_SYS_LIBRARY_PATH'
|
LT_SYS_LIBRARY_PATH'
|
||||||
|
|
||||||
|
|
||||||
@@ -1482,6 +1489,8 @@ Some influential environment variables:
|
|||||||
LIBS libraries to pass to the linker, e.g. -l<library>
|
LIBS libraries to pass to the linker, e.g. -l<library>
|
||||||
CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
|
CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
|
||||||
you have headers in a nonstandard directory <include dir>
|
you have headers in a nonstandard directory <include dir>
|
||||||
|
CCAS assembler compiler command (defaults to CC)
|
||||||
|
CCASFLAGS assembler compiler flags (defaults to CFLAGS)
|
||||||
LT_SYS_LIBRARY_PATH
|
LT_SYS_LIBRARY_PATH
|
||||||
User-defined run-time library search path.
|
User-defined run-time library search path.
|
||||||
|
|
||||||
@@ -4931,6 +4940,143 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# AM_PROG_AS: library sources include raw x86_64 assembly (the setjmp family
|
||||||
|
# in src/setjmp/x86_64/*.s), which automake compiles through CCAS/CCASFLAGS.
|
||||||
|
# By default we simply use the C compiler to build assembly code.
|
||||||
|
|
||||||
|
test "${CCAS+set}" = set || CCAS=$CC
|
||||||
|
test "${CCASFLAGS+set}" = set || CCASFLAGS=$CFLAGS
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
depcc="$CCAS" am_compiler_list=
|
||||||
|
|
||||||
|
{ printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
|
||||||
|
printf %s "checking dependency style of $depcc... " >&6; }
|
||||||
|
if test ${am_cv_CCAS_dependencies_compiler_type+y}
|
||||||
|
then :
|
||||||
|
printf %s "(cached) " >&6
|
||||||
|
else case e in #(
|
||||||
|
e) if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
|
||||||
|
# We make a subdir and do the tests there. Otherwise we can end up
|
||||||
|
# making bogus files that we don't know about and never remove. For
|
||||||
|
# instance it was reported that on HP-UX the gcc test will end up
|
||||||
|
# making a dummy file named 'D' -- because '-MD' means "put the output
|
||||||
|
# in D".
|
||||||
|
rm -rf conftest.dir
|
||||||
|
mkdir conftest.dir
|
||||||
|
# Copy depcomp to subdir because otherwise we won't find it if we're
|
||||||
|
# using a relative directory.
|
||||||
|
cp "$am_depcomp" conftest.dir
|
||||||
|
cd conftest.dir
|
||||||
|
# We will build objects and dependencies in a subdirectory because
|
||||||
|
# it helps to detect inapplicable dependency modes. For instance
|
||||||
|
# both Tru64's cc and ICC support -MD to output dependencies as a
|
||||||
|
# side effect of compilation, but ICC will put the dependencies in
|
||||||
|
# the current directory while Tru64 will put them in the object
|
||||||
|
# directory.
|
||||||
|
mkdir sub
|
||||||
|
|
||||||
|
am_cv_CCAS_dependencies_compiler_type=none
|
||||||
|
if test "$am_compiler_list" = ""; then
|
||||||
|
am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
|
||||||
|
fi
|
||||||
|
am__universal=false
|
||||||
|
|
||||||
|
|
||||||
|
for depmode in $am_compiler_list; do
|
||||||
|
# Setup a source with many dependencies, because some compilers
|
||||||
|
# like to wrap large dependency lists on column 80 (with \), and
|
||||||
|
# we should not choose a depcomp mode which is confused by this.
|
||||||
|
#
|
||||||
|
# We need to recreate these files for each test, as the compiler may
|
||||||
|
# overwrite some of them when testing with obscure command lines.
|
||||||
|
# This happens at least with the AIX C compiler.
|
||||||
|
: > sub/conftest.c
|
||||||
|
for i in 1 2 3 4 5 6; do
|
||||||
|
echo '#include "conftst'$i'.h"' >> sub/conftest.c
|
||||||
|
# Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
|
||||||
|
# Solaris 10 /bin/sh.
|
||||||
|
echo '/* dummy */' > sub/conftst$i.h
|
||||||
|
done
|
||||||
|
echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
|
||||||
|
|
||||||
|
# We check with '-c' and '-o' for the sake of the "dashmstdout"
|
||||||
|
# mode. It turns out that the SunPro C++ compiler does not properly
|
||||||
|
# handle '-M -o', and we need to detect this. Also, some Intel
|
||||||
|
# versions had trouble with output in subdirs.
|
||||||
|
am__obj=sub/conftest.${OBJEXT-o}
|
||||||
|
am__minus_obj="-o $am__obj"
|
||||||
|
case $depmode in
|
||||||
|
gcc)
|
||||||
|
# This depmode causes a compiler race in universal mode.
|
||||||
|
test "$am__universal" = false || continue
|
||||||
|
;;
|
||||||
|
nosideeffect)
|
||||||
|
# After this tag, mechanisms are not by side-effect, so they'll
|
||||||
|
# only be used when explicitly requested.
|
||||||
|
if test "x$enable_dependency_tracking" = xyes; then
|
||||||
|
continue
|
||||||
|
else
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
msvc7 | msvc7msys | msvisualcpp | msvcmsys)
|
||||||
|
# This compiler won't grok '-c -o', but also, the minuso test has
|
||||||
|
# not run yet. These depmodes are late enough in the game, and
|
||||||
|
# so weak that their functioning should not be impacted.
|
||||||
|
am__obj=conftest.${OBJEXT-o}
|
||||||
|
am__minus_obj=
|
||||||
|
;;
|
||||||
|
none) break ;;
|
||||||
|
esac
|
||||||
|
if depmode=$depmode \
|
||||||
|
source=sub/conftest.c object=$am__obj \
|
||||||
|
depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
|
||||||
|
$SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
|
||||||
|
>/dev/null 2>conftest.err &&
|
||||||
|
grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
|
||||||
|
grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
|
||||||
|
grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
|
||||||
|
${MAKE-make} -s -f confmf > /dev/null 2>&1; then
|
||||||
|
# icc doesn't choke on unknown options, it will just issue warnings
|
||||||
|
# or remarks (even with -Werror). So we grep stderr for any message
|
||||||
|
# that says an option was ignored or not supported.
|
||||||
|
# When given -MP, icc 7.0 and 7.1 complain thus:
|
||||||
|
# icc: Command line warning: ignoring option '-M'; no argument required
|
||||||
|
# The diagnosis changed in icc 8.0:
|
||||||
|
# icc: Command line remark: option '-MP' not supported
|
||||||
|
if (grep 'ignoring option' conftest.err ||
|
||||||
|
grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
|
||||||
|
am_cv_CCAS_dependencies_compiler_type=$depmode
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
cd ..
|
||||||
|
rm -rf conftest.dir
|
||||||
|
else
|
||||||
|
am_cv_CCAS_dependencies_compiler_type=none
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
{ printf '%s\n' "$as_me:${as_lineno-$LINENO}: result: $am_cv_CCAS_dependencies_compiler_type" >&5
|
||||||
|
printf '%s\n' "$am_cv_CCAS_dependencies_compiler_type" >&6; }
|
||||||
|
CCASDEPMODE=depmode=$am_cv_CCAS_dependencies_compiler_type
|
||||||
|
|
||||||
|
if
|
||||||
|
test "x$enable_dependency_tracking" != xno \
|
||||||
|
&& test "$am_cv_CCAS_dependencies_compiler_type" = gcc3; then
|
||||||
|
am__fastdepCCAS_TRUE=
|
||||||
|
am__fastdepCCAS_FALSE='#'
|
||||||
|
else
|
||||||
|
am__fastdepCCAS_TRUE='#'
|
||||||
|
am__fastdepCCAS_FALSE=
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
{ printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking whether the compiler is GCC" >&5
|
{ printf '%s\n' "$as_me:${as_lineno-$LINENO}: checking whether the compiler is GCC" >&5
|
||||||
printf %s "checking whether the compiler is GCC... " >&6; }
|
printf %s "checking whether the compiler is GCC... " >&6; }
|
||||||
|
|
||||||
@@ -5186,7 +5332,16 @@ fi
|
|||||||
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
|
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
|
||||||
CFLAGS=$vlibc_save_CFLAGS
|
CFLAGS=$vlibc_save_CFLAGS
|
||||||
|
|
||||||
VLIBC_CFLAGS="-std=$vlibc_cstd -Wall -Wextra"
|
# -fno-stack-protector: distro GCC builds enable -fstack-protector-strong by
|
||||||
|
# default, which would make library objects reference __stack_chk_fail — a
|
||||||
|
# symbol vlibc does not provide yet. Every make-check test binary and every
|
||||||
|
# -nostdlib -static consumer links against the plain archive, and one
|
||||||
|
# undefined __stack_chk_fail in it breaks the whole self-hosting link. A
|
||||||
|
# bootstrap libc must build its own objects without the protector (the stack
|
||||||
|
# protector runtime lands with the hardening work, after which this flag is
|
||||||
|
# revisited). Tests compile with the same flag (tests/Makefile.am wiring in
|
||||||
|
# Makefile.am).
|
||||||
|
VLIBC_CFLAGS="-std=$vlibc_cstd -Wall -Wextra -fno-stack-protector"
|
||||||
|
|
||||||
|
|
||||||
# ---- Compatibility profile ----------------------------------------------
|
# ---- Compatibility profile ----------------------------------------------
|
||||||
@@ -14607,6 +14762,10 @@ if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
|
|||||||
as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
|
as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
|
||||||
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
||||||
fi
|
fi
|
||||||
|
if test -z "${am__fastdepCCAS_TRUE}" && test -z "${am__fastdepCCAS_FALSE}"; then
|
||||||
|
as_fn_error $? "conditional \"am__fastdepCCAS\" was never defined.
|
||||||
|
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
||||||
|
fi
|
||||||
if test -z "${PROFILE_GE_2_TRUE}" && test -z "${PROFILE_GE_2_FALSE}"; then
|
if test -z "${PROFILE_GE_2_TRUE}" && test -z "${PROFILE_GE_2_FALSE}"; then
|
||||||
as_fn_error $? "conditional \"PROFILE_GE_2\" was never defined.
|
as_fn_error $? "conditional \"PROFILE_GE_2\" was never defined.
|
||||||
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
||||||
|
|||||||
+13
-1
@@ -26,6 +26,9 @@ AM_INIT_AUTOMAKE([foreign subdir-objects])
|
|||||||
# (including clang), so it cannot be used to enforce the single-compiler rule.
|
# (including clang), so it cannot be used to enforce the single-compiler rule.
|
||||||
# Verify the compiler is genuinely GCC, not a compatible one.
|
# Verify the compiler is genuinely GCC, not a compatible one.
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
|
# AM_PROG_AS: library sources include raw x86_64 assembly (the setjmp family
|
||||||
|
# in src/setjmp/x86_64/*.s), which automake compiles through CCAS/CCASFLAGS.
|
||||||
|
AM_PROG_AS
|
||||||
AC_MSG_CHECKING([whether the compiler is GCC])
|
AC_MSG_CHECKING([whether the compiler is GCC])
|
||||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [
|
||||||
#if !defined(__GNUC__) || defined(__clang__)
|
#if !defined(__GNUC__) || defined(__clang__)
|
||||||
@@ -58,7 +61,16 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])],
|
|||||||
AC_MSG_ERROR([$CC does not support -std=$vlibc_cstd])])
|
AC_MSG_ERROR([$CC does not support -std=$vlibc_cstd])])
|
||||||
CFLAGS=$vlibc_save_CFLAGS
|
CFLAGS=$vlibc_save_CFLAGS
|
||||||
|
|
||||||
AC_SUBST([VLIBC_CFLAGS], ["-std=$vlibc_cstd -Wall -Wextra"])
|
# -fno-stack-protector: distro GCC builds enable -fstack-protector-strong by
|
||||||
|
# default, which would make library objects reference __stack_chk_fail — a
|
||||||
|
# symbol vlibc does not provide yet. Every make-check test binary and every
|
||||||
|
# -nostdlib -static consumer links against the plain archive, and one
|
||||||
|
# undefined __stack_chk_fail in it breaks the whole self-hosting link. A
|
||||||
|
# bootstrap libc must build its own objects without the protector (the stack
|
||||||
|
# protector runtime lands with the hardening work, after which this flag is
|
||||||
|
# revisited). Tests compile with the same flag (tests/Makefile.am wiring in
|
||||||
|
# Makefile.am).
|
||||||
|
AC_SUBST([VLIBC_CFLAGS], ["-std=$vlibc_cstd -Wall -Wextra -fno-stack-protector"])
|
||||||
|
|
||||||
# ---- Compatibility profile ----------------------------------------------
|
# ---- Compatibility profile ----------------------------------------------
|
||||||
# Exactly one of the five profiles is active. They are mutually exclusive;
|
# Exactly one of the five profiles is active. They are mutually exclusive;
|
||||||
|
|||||||
@@ -0,0 +1,266 @@
|
|||||||
|
#ifndef VLIBC_TEST_H
|
||||||
|
#define VLIBC_TEST_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* vlibc — shared test contract (todo 6).
|
||||||
|
*
|
||||||
|
* Every future per-function test (test_*.c) includes this header and gets:
|
||||||
|
*
|
||||||
|
* - TEST_ASSERT_EQ(actual, expected) integer equality, compared as
|
||||||
|
* signed 64-bit; on failure prints
|
||||||
|
* both values in hex
|
||||||
|
* - TEST_ASSERT_TRUE(cond) boolean check
|
||||||
|
* - TEST_ASSERT_STREQ(actual, expected) NUL-terminated string equality;
|
||||||
|
* NULL-safe (NULL equals only NULL)
|
||||||
|
* - TEST_ASSERT_NULL(p) pointer is NULL
|
||||||
|
* - TEST_MAIN(tests) a main() that runs the array of
|
||||||
|
* struct vlibc_test entries, prints
|
||||||
|
* one "RUN <name>: PASS|FAIL" line
|
||||||
|
* per test and a PASS/FAIL summary,
|
||||||
|
* and returns 0 when everything
|
||||||
|
* passed and 1 otherwise
|
||||||
|
*
|
||||||
|
* Contract:
|
||||||
|
* - Dependency-light: needs only vlibc's own <stddef.h> and the internal
|
||||||
|
* raw-syscall layer (src/internal/syscall.h, via a path-relative
|
||||||
|
* include). It deliberately includes NO host header and does NOT use
|
||||||
|
* vlibc stdio (which does not exist yet). All output goes through raw
|
||||||
|
* SYS_write to fd 1 (progress/summary) and fd 2 (assertion failures).
|
||||||
|
* - Compile tests with -Iinclude -std=c23 -fno-stack-protector
|
||||||
|
* -fno-pic -fno-pie (the make check harness does this; see Makefile.am)
|
||||||
|
* and link statically against the vlibc test archive.
|
||||||
|
* - A test function returns 0 on success, nonzero on failure; TEST_MAIN
|
||||||
|
* aggregates both the return values and any assertion failures.
|
||||||
|
* - The failure counter is per translation unit (one static int); keep
|
||||||
|
* each test binary a single TU.
|
||||||
|
* - Tests that need argc/argv (mode flags like -f) write their own
|
||||||
|
* main() and may still use the TEST_ASSERT_* macros.
|
||||||
|
* - One test function per checked behavior, named for the output.
|
||||||
|
* - All macro arguments are evaluated exactly once.
|
||||||
|
* - Do NOT include host headers in a TU that includes this file: the
|
||||||
|
* -Iinclude path shadows GCC's internal headers (see tests/test_strerror.c).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "../../../src/internal/syscall.h"
|
||||||
|
|
||||||
|
/* One registered test: a name for the runner output and its run function. */
|
||||||
|
struct vlibc_test
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
int (*run)(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Assertion failures recorded in this translation unit. */
|
||||||
|
static int vlibc_test_failures;
|
||||||
|
|
||||||
|
/* ---- Raw output helpers (no stdio: raw SYS_write only) ---- */
|
||||||
|
|
||||||
|
static inline long
|
||||||
|
vlibc_test_strlen(const char *s)
|
||||||
|
{
|
||||||
|
long n = 0;
|
||||||
|
|
||||||
|
while (s[n] != '\0')
|
||||||
|
{
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
vlibc_test_say(int fd, const char *s)
|
||||||
|
{
|
||||||
|
(void)__syscall3(SYS_write, fd, (long)s, vlibc_test_strlen(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The helpers below all take an (fd, value) or (value, name, file, line)
|
||||||
|
* argument shape whose order is a fixed diagnostic convention; the
|
||||||
|
* easily-swappable-parameters warning does not apply.
|
||||||
|
*/
|
||||||
|
// NOLINTBEGIN(bugprone-easily-swappable-parameters)
|
||||||
|
static inline void
|
||||||
|
vlibc_test_say_dec(int fd, unsigned long v)
|
||||||
|
{
|
||||||
|
char buf[24];
|
||||||
|
int i = (int)sizeof(buf);
|
||||||
|
|
||||||
|
buf[--i] = '\0';
|
||||||
|
do
|
||||||
|
{
|
||||||
|
buf[--i] = (char)('0' + (v % 10));
|
||||||
|
v /= 10;
|
||||||
|
} while (v != 0);
|
||||||
|
(void)__syscall3(SYS_write, fd, (long)(buf + i), (long)(sizeof(buf) - 1 - i));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
vlibc_test_say_hex(int fd, unsigned long long v)
|
||||||
|
{
|
||||||
|
char buf[18];
|
||||||
|
int i = (int)sizeof(buf);
|
||||||
|
|
||||||
|
buf[--i] = '\0';
|
||||||
|
do
|
||||||
|
{
|
||||||
|
unsigned int d = (unsigned int)(v & 0xf);
|
||||||
|
|
||||||
|
buf[--i] = (char)(d < 10 ? '0' + d : 'a' + d - 10);
|
||||||
|
v >>= 4;
|
||||||
|
} while (v != 0);
|
||||||
|
(void)__syscall3(SYS_write, fd, (long)(buf + i), (long)(sizeof(buf) - 1 - i));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Assertion machinery (implementation side of the macros) ---- */
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
vlibc_test_fail_header(const char *file, int line)
|
||||||
|
{
|
||||||
|
vlibc_test_failures++;
|
||||||
|
vlibc_test_say(2, "ASSERT FAIL: ");
|
||||||
|
vlibc_test_say(2, file);
|
||||||
|
vlibc_test_say(2, ":");
|
||||||
|
vlibc_test_say_dec(2, (unsigned long)line);
|
||||||
|
vlibc_test_say(2, ": ");
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void // NOLINT(bugprone-easily-swappable-parameters)
|
||||||
|
vlibc_test_check(int ok, const char *what, const char *file, int line)
|
||||||
|
{
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vlibc_test_fail_header(file, line);
|
||||||
|
vlibc_test_say(2, what);
|
||||||
|
vlibc_test_say(2, " is false\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void // NOLINT(bugprone-easily-swappable-parameters)
|
||||||
|
vlibc_test_check_eq(long long actual, long long expected, const char *actual_s,
|
||||||
|
const char *expected_s, const char *file, int line)
|
||||||
|
{
|
||||||
|
if (actual == expected)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vlibc_test_fail_header(file, line);
|
||||||
|
vlibc_test_say(2, "TEST_ASSERT_EQ(");
|
||||||
|
vlibc_test_say(2, actual_s);
|
||||||
|
vlibc_test_say(2, ", ");
|
||||||
|
vlibc_test_say(2, expected_s);
|
||||||
|
vlibc_test_say(2, "): got 0x");
|
||||||
|
vlibc_test_say_hex(2, (unsigned long long)actual);
|
||||||
|
vlibc_test_say(2, ", want 0x");
|
||||||
|
vlibc_test_say_hex(2, (unsigned long long)expected);
|
||||||
|
vlibc_test_say(2, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
vlibc_test_str_eq(const char *a, const char *b)
|
||||||
|
{
|
||||||
|
if (a == b)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (a == NULL || b == NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
while (*a != '\0' && *a == *b)
|
||||||
|
{
|
||||||
|
a++;
|
||||||
|
b++;
|
||||||
|
}
|
||||||
|
return *a == *b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void // NOLINT(bugprone-easily-swappable-parameters)
|
||||||
|
vlibc_test_check_streq(const char *actual, const char *expected,
|
||||||
|
const char *actual_s, const char *expected_s,
|
||||||
|
const char *file, int line)
|
||||||
|
{
|
||||||
|
if (vlibc_test_str_eq(actual, expected))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
vlibc_test_fail_header(file, line);
|
||||||
|
vlibc_test_say(2, "TEST_ASSERT_STREQ(");
|
||||||
|
vlibc_test_say(2, actual_s);
|
||||||
|
vlibc_test_say(2, ", ");
|
||||||
|
vlibc_test_say(2, expected_s);
|
||||||
|
vlibc_test_say(2, "): got \"");
|
||||||
|
vlibc_test_say(2, actual == NULL ? "(null)" : actual);
|
||||||
|
vlibc_test_say(2, "\", want \"");
|
||||||
|
vlibc_test_say(2, expected == NULL ? "(null)" : expected);
|
||||||
|
vlibc_test_say(2, "\"\n");
|
||||||
|
}
|
||||||
|
// NOLINTEND(bugprone-easily-swappable-parameters)
|
||||||
|
|
||||||
|
/* ---- Public assertion macros ---- */
|
||||||
|
|
||||||
|
#define TEST_ASSERT_TRUE(cond) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
vlibc_test_check((cond) != 0, #cond, __FILE__, __LINE__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define TEST_ASSERT_EQ(actual, expected) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
vlibc_test_check_eq((long long)(actual), (long long)(expected), \
|
||||||
|
#actual, #expected, __FILE__, __LINE__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define TEST_ASSERT_NULL(p) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
vlibc_test_check((p) == NULL, #p " == NULL", __FILE__, __LINE__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define TEST_ASSERT_STREQ(actual, expected) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
vlibc_test_check_streq((actual), (expected), #actual, #expected, \
|
||||||
|
__FILE__, __LINE__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/* ---- Runner ---- */
|
||||||
|
|
||||||
|
#define TEST_MAIN(tests) \
|
||||||
|
int \
|
||||||
|
main(void) \
|
||||||
|
{ \
|
||||||
|
const size_t vlibc_test_count = sizeof(tests) / sizeof((tests)[0]); \
|
||||||
|
size_t vlibc_test_i; \
|
||||||
|
size_t vlibc_test_passed = 0; \
|
||||||
|
for (vlibc_test_i = 0; vlibc_test_i < vlibc_test_count; vlibc_test_i++) \
|
||||||
|
{ \
|
||||||
|
int vlibc_test_before = vlibc_test_failures; \
|
||||||
|
vlibc_test_say(1, "RUN "); \
|
||||||
|
vlibc_test_say(1, (tests)[vlibc_test_i].name); \
|
||||||
|
vlibc_test_say(1, ": "); \
|
||||||
|
if ((tests)[vlibc_test_i].run() == 0 && \
|
||||||
|
vlibc_test_failures == vlibc_test_before) \
|
||||||
|
{ \
|
||||||
|
vlibc_test_say(1, "PASS\n"); \
|
||||||
|
vlibc_test_passed++; \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
vlibc_test_say(1, "FAIL\n"); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
vlibc_test_say(1, "SUMMARY: "); \
|
||||||
|
vlibc_test_say_dec(1, (unsigned long)vlibc_test_passed); \
|
||||||
|
vlibc_test_say(1, "/"); \
|
||||||
|
vlibc_test_say_dec(1, (unsigned long)vlibc_test_count); \
|
||||||
|
vlibc_test_say(1, " passed, "); \
|
||||||
|
vlibc_test_say_dec(1, (unsigned long)vlibc_test_failures); \
|
||||||
|
vlibc_test_say(1, " assertion failure(s)\n"); \
|
||||||
|
return vlibc_test_passed == vlibc_test_count ? 0 : 1; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* VLIBC_TEST_H */
|
||||||
File diff suppressed because it is too large
Load Diff
Executable
+95
@@ -0,0 +1,95 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# vlibc — make check mode matrix (todo 6).
|
||||||
|
#
|
||||||
|
# Runs every scenario that a single "run the binary once" TESTS entry cannot
|
||||||
|
# cover: the -f failure modes of the four syscall/errno/setjmp/headers tests
|
||||||
|
# and the full test_startup mode matrix. Every scenario pins its exact exit
|
||||||
|
# status and (where load-bearing) its exact stdout; see tests/test_startup.c
|
||||||
|
# and the individual tests for the mode contracts.
|
||||||
|
#
|
||||||
|
# The binaries are the static vlibc executables built by make check next to
|
||||||
|
# the top-level Makefile. make check executes this script with the build
|
||||||
|
# directory root as the working directory (in-tree and VPATH builds alike),
|
||||||
|
# so the binaries resolve as plain ./<name> paths relative to the CWD, NOT
|
||||||
|
# relative to this script's location.
|
||||||
|
|
||||||
|
fail=0
|
||||||
|
|
||||||
|
# run_rc <binary> <want_rc> <description> [args...]
|
||||||
|
# Runs the binary with the given args and checks the exit status only (the
|
||||||
|
# -f modes print diagnostics, whose text is not part of the contract).
|
||||||
|
run_rc()
|
||||||
|
{
|
||||||
|
bin=$1
|
||||||
|
want_rc=$2
|
||||||
|
desc=$3
|
||||||
|
shift 3
|
||||||
|
"$bin" "$@" >/dev/null 2>&1
|
||||||
|
rc=$?
|
||||||
|
if [ "$rc" -ne "$want_rc" ]; then
|
||||||
|
echo "FAIL: $desc: rc=$rc want=$want_rc"
|
||||||
|
fail=1
|
||||||
|
else
|
||||||
|
echo "ok: $desc"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# run <binary> <want_rc> <want_stdout> <description> [args...]
|
||||||
|
# Like run_rc but also compares the exact stdout (stderr discarded). An
|
||||||
|
# empty want_stdout matches an empty stdout.
|
||||||
|
run()
|
||||||
|
{
|
||||||
|
bin=$1
|
||||||
|
want_rc=$2
|
||||||
|
want_out=$3
|
||||||
|
desc=$4
|
||||||
|
shift 4
|
||||||
|
out=$("$bin" "$@" 2>/dev/null)
|
||||||
|
rc=$?
|
||||||
|
if [ "$rc" -ne "$want_rc" ]; then
|
||||||
|
echo "FAIL: $desc: rc=$rc want=$want_rc"
|
||||||
|
fail=1
|
||||||
|
elif [ "$out" != "$want_out" ]; then
|
||||||
|
echo "FAIL: $desc: stdout [$out] want [$want_out]"
|
||||||
|
fail=1
|
||||||
|
else
|
||||||
|
echo "ok: $desc"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
bindir=.
|
||||||
|
|
||||||
|
# -f failure scenarios of the four arg-mode tests (exit status is the
|
||||||
|
# contract; the diagnostics on stdout are not pinned).
|
||||||
|
run_rc "./test_syscall" 0 "syscall -f: ENOENT via fake TCB slot" -f
|
||||||
|
run_rc "./test_strerror" 0 "strerror -f: unknown errno formats" -f
|
||||||
|
run_rc "./test_setjmp" 0 "setjmp -f: longjmp(env,0) coerced to 1" -f
|
||||||
|
run_rc "./test_headers" 132 "headers -f: assert(0) traps (SIGILL)" -f
|
||||||
|
|
||||||
|
# test_startup mode matrix (each mode pins its own exit status; the default
|
||||||
|
# mode exits 42 on success, which is why it is not a bare TESTS entry).
|
||||||
|
run "./test_startup" 42 "C
|
||||||
|
B
|
||||||
|
A" "startup default: atexit LIFO CBA, status 42"
|
||||||
|
run "./test_startup" 5 "Q" "startup -q: quick_exit runs only at_quick_exit" -q
|
||||||
|
run "./test_startup" 7 "" "startup -z: _exit runs no handlers" -z
|
||||||
|
run "./test_startup" 0 "" "startup -t: main-thread TLS + errno TCB slot" -t
|
||||||
|
run "./test_startup" 0 "" "startup -x: handler-list limits" -x
|
||||||
|
|
||||||
|
# -e needs VLIBC_TEST_VAR=hello in environ (checked by the test itself).
|
||||||
|
out=$(VLIBC_TEST_VAR=hello "./test_startup" -e extraarg 2>/dev/null)
|
||||||
|
rc=$?
|
||||||
|
if [ "$rc" -ne 0 ]; then
|
||||||
|
echo "FAIL: startup -e: argv/env plumbing rc=$rc want=0"
|
||||||
|
fail=1
|
||||||
|
elif [ "$out" != "argc=3
|
||||||
|
argv0=./test_startup
|
||||||
|
argv1=-e
|
||||||
|
argv2=extraarg" ]; then
|
||||||
|
echo "FAIL: startup -e: unexpected stdout [$out]"
|
||||||
|
fail=1
|
||||||
|
else
|
||||||
|
echo "ok: startup -e: argv/env plumbing"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit $fail
|
||||||
Reference in New Issue
Block a user