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_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
|
||||
|
||||
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@
|
||||
|
||||
# ---- 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
|
||||
|
||||
libvlibc_la_SOURCES = src/vlibc.c src/string/strlen.c src/string/strcmp.c \
|
||||
src/string/memcpy.c src/string/memmove.c src/string/memset.c
|
||||
libvlibc_la_SOURCES = $(VLIBC_CORE_SRCS)
|
||||
if PROFILE_GE_2
|
||||
libvlibc_la_SOURCES += src/string/strlcpy.c src/string/strlcat.c
|
||||
libvlibc_la_SOURCES += $(VLIBC_LEVEL2_SRCS)
|
||||
endif
|
||||
if PROFILE_GE_3
|
||||
libvlibc_la_SOURCES += src/string/strcasestr.c
|
||||
libvlibc_la_SOURCES += $(VLIBC_LEVEL3_SRCS)
|
||||
endif
|
||||
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).
|
||||
if INSTALL_OVERWRITE
|
||||
vlibc_includedir = $(includedir)
|
||||
@@ -38,6 +125,17 @@ nodist_vlibc_features_HEADERS = include/vlibc/features.h
|
||||
# ---- Compiler drivers ----------------------------------------------------
|
||||
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 -------------------------------------------------------------
|
||||
# layouts/C.md requires `make debug`, `make release`, `make bench` and
|
||||
# `make clean`; build outputs land in bin/{release,debug}.
|
||||
@@ -50,6 +148,7 @@ debug:
|
||||
$(MKDIR_P) bin/debug
|
||||
-cp -P .libs/libvlibc.so* bin/debug/
|
||||
-cp .libs/libvlibc.a bin/debug/
|
||||
-cp crt1.o bin/debug/
|
||||
|
||||
release:
|
||||
$(MAKE) clean
|
||||
@@ -57,6 +156,7 @@ release:
|
||||
$(MKDIR_P) bin/release
|
||||
-cp -P .libs/libvlibc.so* bin/release/
|
||||
-cp .libs/libvlibc.a bin/release/
|
||||
-cp crt1.o bin/release/
|
||||
|
||||
bench: all
|
||||
$(MAKE) -C benchmarks bench
|
||||
@@ -68,3 +168,122 @@ compile-commands: clean
|
||||
bear --append -- $(MAKE) -C benchmarks bench_vlibc
|
||||
|
||||
.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).
|
||||
|
||||
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@
|
||||
|
||||
# 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_profile
|
||||
VLIBC_CFLAGS
|
||||
am__fastdepCCAS_FALSE
|
||||
am__fastdepCCAS_TRUE
|
||||
CCASDEPMODE
|
||||
CCASFLAGS
|
||||
CCAS
|
||||
am__fastdepCC_FALSE
|
||||
am__fastdepCC_TRUE
|
||||
CCDEPMODE
|
||||
@@ -806,6 +811,8 @@ CFLAGS
|
||||
LDFLAGS
|
||||
LIBS
|
||||
CPPFLAGS
|
||||
CCAS
|
||||
CCASFLAGS
|
||||
LT_SYS_LIBRARY_PATH'
|
||||
|
||||
|
||||
@@ -1482,6 +1489,8 @@ Some influential environment variables:
|
||||
LIBS libraries to pass to the linker, e.g. -l<library>
|
||||
CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
|
||||
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
|
||||
User-defined run-time library search path.
|
||||
|
||||
@@ -4931,6 +4940,143 @@ else
|
||||
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 "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
|
||||
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 ----------------------------------------------
|
||||
@@ -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.
|
||||
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
||||
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
|
||||
as_fn_error $? "conditional \"PROFILE_GE_2\" was never defined.
|
||||
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.
|
||||
# Verify the compiler is genuinely GCC, not a compatible one.
|
||||
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_COMPILE_IFELSE([AC_LANG_PROGRAM([], [
|
||||
#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])])
|
||||
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 ----------------------------------------------
|
||||
# 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