From 2e96fc06f325110af8c7177c0c60694eed5fd245 Mon Sep 17 00:00:00 2001 From: EuAndreh Date: Tue, 2 Jan 2024 17:28:59 -0300 Subject: Fix the build system. The improvements are: - use most of the default "Makefile" for standard packaging; - also use the default ".gitignore" with for the derived assets; - don't impose so many $CFLAGS on the user. GCC still needs to be given the `-ffreestanding` flag explicitly for us to get a good binary; - stop using ad-hoc tools/* scripts, and avoid the code-generation anti-pattern overall on the build. Some of the generated files were checked-in, and some were removed; - remove empty files; - use POSIX make(1) over gmake; - add fuzz targets; - partial "install" and "uninstall" targets; - complete "clean" target. The shortcomings are: - only working on x86_64. More platforms coming soon; - code is still messy: way too many warnings, GNU/BSD specific extensions, inline assembly, and all kinds of unportable code; - still only works with GCC and GCC-like compilers, and completly fails with tcc(1) and cproc(1); - the `deps.mk` file is being maintained manually. As I work on the source files I'll finish automating its generation with `mkdeps.sh`; - still seems to be coupled with Linux; - still is missing tests setup; - still uses `#include <$NAME.h>` instead of the correct `#include "$NAME.h"` form. The generated libgrovel.a did match the previous lib/libc.a 100%. --- Makefile | 424 ++++++++++++++++++++++++++------------------------------------- 1 file changed, 176 insertions(+), 248 deletions(-) (limited to 'Makefile') diff --git a/Makefile b/Makefile index 5bf31622..7a788f02 100644 --- a/Makefile +++ b/Makefile @@ -1,284 +1,212 @@ -# -# Makefile for musl (requires GNU make) -# -# This is how simple every makefile should be... -# No, I take that back - actually most should be less than half this size. -# -# Use config.mak to override any of the following variables. -# Do not make changes here. -# +.POSIX: +DATE = 1970-01-01 +VERSION = 0.1.0 +NAME = grovel +NAME_UC = $(NAME) +MAILING_LIST = public-inbox +LANGUAGES = +## Installation prefix. Defaults to "/usr". +PREFIX = /usr +BINDIR = $(PREFIX)/bin +LIBDIR = $(PREFIX)/lib +INCLUDEDIR = $(PREFIX)/include +SRCDIR = $(PREFIX)/src/$(NAME) +SHAREDIR = $(PREFIX)/share +LOCALEDIR = $(SHAREDIR)/locale +MANDIR = $(SHAREDIR)/man +EXEC = ./ +## Where to store the installation. Empty by default. +DESTDIR = +LDLIBS = + + + +.SUFFIXES: +.SUFFIXES: .in .c .o .to .xa .bin .msg .cat +.SUFFIXES: .s + +.in: + sed \ + -e 's:@VERSION@:$(VERSION):g' \ + -e 's:@DATE@:$(DATE):g' \ + -e 's:@NAME@:$(NAME):g' \ + < $< > $@ + if [ -x $< ]; then chmod +x $@; fi + +.s.o: + $(CC) $(CFLAGS) -o $@ -c $< + +.c.o: + $(CC) $(CFLAGS) -o $@ -c $< + +.c.to: + $(CC) $(CFLAGS) -DTEST -o $@ -c $< + +.xa.bin: + $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS) -srcdir = . -exec_prefix = /usr/local -bindir = $(exec_prefix)/bin - -prefix = /usr/local/musl -includedir = $(prefix)/include -libdir = $(prefix)/lib -syslibdir = /lib - -MALLOC_DIR = mallocng -SRC_DIRS = $(addprefix $(srcdir)/,src/* src/malloc/$(MALLOC_DIR) crt ldso $(COMPAT_SRC_DIRS)) -BASE_GLOBS = $(addsuffix /*.c,$(SRC_DIRS)) -ARCH_GLOBS = $(addsuffix /$(ARCH)/*.[csS],$(SRC_DIRS)) -BASE_SRCS = $(sort $(wildcard $(BASE_GLOBS))) -ARCH_SRCS = $(sort $(wildcard $(ARCH_GLOBS))) -BASE_OBJS = $(patsubst $(srcdir)/%,%.o,$(basename $(BASE_SRCS))) -ARCH_OBJS = $(patsubst $(srcdir)/%,%.o,$(basename $(ARCH_SRCS))) -REPLACED_OBJS = $(sort $(subst /$(ARCH)/,/,$(ARCH_OBJS))) -ALL_OBJS = $(addprefix obj/, $(filter-out $(REPLACED_OBJS), $(sort $(BASE_OBJS) $(ARCH_OBJS)))) - -LIBC_OBJS = $(filter obj/src/%,$(ALL_OBJS)) $(filter obj/compat/%,$(ALL_OBJS)) -LDSO_OBJS = $(filter obj/ldso/%,$(ALL_OBJS:%.o=%.lo)) -CRT_OBJS = $(filter obj/crt/%,$(ALL_OBJS)) - -AOBJS = $(LIBC_OBJS) -LOBJS = $(LIBC_OBJS:.o=.lo) -GENH = obj/include/bits/alltypes.h obj/include/bits/syscall.h -GENH_INT = obj/src/internal/version.h -IMPH = $(addprefix $(srcdir)/, src/internal/stdio_impl.h src/internal/pthread_impl.h src/internal/locale_impl.h src/internal/libc.h) - -LDFLAGS = -LDFLAGS_AUTO = -LIBCC = -lgcc -CPPFLAGS = -CFLAGS = -CFLAGS_AUTO = -Os -pipe -CFLAGS_C99FSE = -std=c99 -ffreestanding -nostdinc - -CFLAGS_ALL = $(CFLAGS_C99FSE) -CFLAGS_ALL += -D_XOPEN_SOURCE=700 -I$(srcdir)/arch/$(ARCH) -I$(srcdir)/arch/generic -Iobj/src/internal -I$(srcdir)/src/include -I$(srcdir)/src/internal -Iobj/include -I$(srcdir)/include -CFLAGS_ALL += $(CPPFLAGS) $(CFLAGS_AUTO) $(CFLAGS) - -LDFLAGS_ALL = $(LDFLAGS_AUTO) $(LDFLAGS) - -AR = $(CROSS_COMPILE)ar -RANLIB = $(CROSS_COMPILE)ranlib -INSTALL = $(srcdir)/tools/install.sh - -ARCH_INCLUDES = $(wildcard $(srcdir)/arch/$(ARCH)/bits/*.h) -GENERIC_INCLUDES = $(wildcard $(srcdir)/arch/generic/bits/*.h) -INCLUDES = $(wildcard $(srcdir)/include/*.h $(srcdir)/include/*/*.h) -ALL_INCLUDES = $(sort $(INCLUDES:$(srcdir)/%=%) $(GENH:obj/%=%) $(ARCH_INCLUDES:$(srcdir)/arch/$(ARCH)/%=include/%) $(GENERIC_INCLUDES:$(srcdir)/arch/generic/%=include/%)) - -EMPTY_LIB_NAMES = m rt pthread crypt util xnet resolv dl -EMPTY_LIBS = $(EMPTY_LIB_NAMES:%=lib/lib%.a) -CRT_LIBS = $(addprefix lib/,$(notdir $(CRT_OBJS))) -STATIC_LIBS = lib/libc.a -SHARED_LIBS = lib/libc.so -TOOL_LIBS = lib/musl-gcc.specs -ALL_LIBS = $(CRT_LIBS) $(STATIC_LIBS) $(SHARED_LIBS) $(EMPTY_LIBS) $(TOOL_LIBS) -ALL_TOOLS = obj/musl-gcc - -WRAPCC_GCC = gcc -WRAPCC_CLANG = clang - -LDSO_PATHNAME = $(syslibdir)/ld-musl-$(ARCH)$(SUBARCH).so.1 - - - - - - - - - - - - - - -# This version of config.mak was generated by: -# ./configure --enable-debug --disable-shared -# Any changes made here will be lost if configure is re-run -AR = $(CROSS_COMPILE)ar -RANLIB = $(CROSS_COMPILE)ranlib -ARCH = x86_64 -SUBARCH = -ASMSUBARCH = -srcdir = . -prefix = /usr/local/musl -exec_prefix = $(prefix) -bindir = $(exec_prefix)/bin -libdir = $(prefix)/lib -includedir = $(prefix)/include -syslibdir = /lib -CC = gcc -CFLAGS = -CFLAGS_AUTO = -g -O2 -fno-align-jumps -fno-align-functions -fno-align-loops -fno-align-labels -fira-region=one -fira-hoist-pressure -freorder-blocks-algorithm=simple -fno-prefetch-loop-arrays -fno-tree-ch -pipe -fno-unwind-tables -fno-asynchronous-unwind-tables -ffunction-sections -fdata-sections -Wno-pointer-to-int-cast -Werror=implicit-function-declaration -Werror=implicit-int -Werror=pointer-sign -Werror=pointer-arith -Werror=int-conversion -Werror=incompatible-pointer-types -Werror=discarded-qualifiers -Werror=discarded-array-qualifiers -Waddress -Warray-bounds -Wchar-subscripts -Wduplicate-decl-specifier -Winit-self -Wreturn-type -Wsequence-point -Wstrict-aliasing -Wunused-function -Wunused-label -Wunused-variable -CFLAGS_C99FSE = -std=c99 -nostdinc -ffreestanding -fexcess-precision=standard -frounding-math -fno-strict-aliasing -Wa,--noexecstack -CFLAGS_MEMOPS = -fno-tree-loop-distribute-patterns -CFLAGS_NOSSP = -fno-stack-protector -CPPFLAGS = -LDFLAGS = -LDFLAGS_AUTO = -Wl,--sort-section,alignment -Wl,--sort-common -Wl,--gc-sections -Wl,--hash-style=both -Wl,--no-undefined -Wl,--exclude-libs=ALL -CROSS_COMPILE = -LIBCC = -lgcc -lgcc_eh -OPTIMIZE_GLOBS = internal/*.c malloc/*.c string/*.c -ALL_TOOLS = obj/musl-gcc -TOOL_LIBS = lib/musl-gcc.specs -ADD_CFI = yes -MALLOC_DIR = mallocng -SHARED_LIBS = -WRAPCC_GCC = $(CC) --include $(srcdir)/arch/$(ARCH)/arch.mak - -ifeq ($(ARCH),) - all: - @echo "Please set ARCH in config.mak before running make." - @exit 1 - -else - -all: $(ALL_LIBS) $(ALL_TOOLS) - -OBJ_DIRS = $(sort $(patsubst %/,%,$(dir $(ALL_LIBS) $(ALL_TOOLS) $(ALL_OBJS) $(GENH) $(GENH_INT))) obj/include) - -$(ALL_LIBS) $(ALL_TOOLS) $(ALL_OBJS) $(ALL_OBJS:%.o=%.lo) $(GENH) $(GENH_INT): | $(OBJ_DIRS) - -$(OBJ_DIRS): - mkdir -p $@ - -obj/include/bits/alltypes.h: $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in $(srcdir)/tools/mkalltypes.sed - sed -f $(srcdir)/tools/mkalltypes.sed $(srcdir)/arch/$(ARCH)/bits/alltypes.h.in $(srcdir)/include/alltypes.h.in > $@ - -obj/include/bits/syscall.h: $(srcdir)/arch/$(ARCH)/bits/syscall.h.in - cp $< $@ - sed -n -e s/__NR_/SYS_/p < $< >> $@ - -obj/src/internal/version.h: $(wildcard $(srcdir)/VERSION $(srcdir)/.git) - printf '#define VERSION "%s"\n' "$$(cd $(srcdir); sh tools/version.sh)" > $@ - -obj/src/internal/version.o obj/src/internal/version.lo: obj/src/internal/version.h - -obj/crt/rcrt1.o obj/ldso/dlstart.lo obj/ldso/dynlink.lo: $(srcdir)/src/internal/dynlink.h $(srcdir)/arch/$(ARCH)/reloc.h +include deps.mk -obj/crt/crt1.o obj/crt/scrt1.o obj/crt/rcrt1.o obj/ldso/dlstart.lo: $(srcdir)/arch/$(ARCH)/crt_arch.h +manpages = $(manpages.in:.in=) +catalogs.cat = $(catalogs.msg:.msg=.cat) -obj/crt/rcrt1.o: $(srcdir)/ldso/dlstart.c +sources.o = $(sources.c:.c=.o) $(sources.s:.s=.o) +sources.to = $(sources.c:.c=.to) +sources.xa = $(sources.c:.c=.xa) +# sources.bin = $(sources.c:.c=.bin) # FIXME +fuzz.o = $(fuzz.c:.c=.o) +fuzz.xa = $(fuzz.c:.c=.xa) +fuzz.bin = $(fuzz.c:.c=.bin) -obj/crt/Scrt1.o obj/crt/rcrt1.o: CFLAGS_ALL += -fPIC +sources = \ + $(sources.c) \ + $(sources.c:.c=.h) \ + src/config.h.in \ + src/config.h \ + src/main.c \ + src/$(NAME).h \ + $(catalogs.msg) \ -OPTIMIZE_SRCS = $(wildcard $(OPTIMIZE_GLOBS:%=$(srcdir)/src/%)) -$(OPTIMIZE_SRCS:$(srcdir)/%.c=obj/%.o) $(OPTIMIZE_SRCS:$(srcdir)/%.c=obj/%.lo): CFLAGS += -O3 +empty-libs.a = \ + libm.a \ + librt.a \ + libpthread.a \ + libcrypt.a \ + libutil.a \ + libxnet.a \ + libresolv.a \ + libdl.a \ -MEMOPS_OBJS = $(filter %/memcpy.o %/memmove.o %/memcmp.o %/memset.o, $(LIBC_OBJS)) -$(MEMOPS_OBJS) $(MEMOPS_OBJS:%.o=%.lo): CFLAGS_ALL += $(CFLAGS_MEMOPS) -NOSSP_OBJS = $(CRT_OBJS) $(LDSO_OBJS) $(filter \ - %/__libc_start_main.o %/__init_tls.o %/__stack_chk_fail.o \ - %/__set_thread_area.o %/memset.o %/memcpy.o \ - , $(LIBC_OBJS)) -$(NOSSP_OBJS) $(NOSSP_OBJS:%.o=%.lo): CFLAGS_ALL += $(CFLAGS_NOSSP) +derived-assets = \ + lib$(NAME).a \ + $(empty-libs.a) \ + libc.a \ + src/config.h \ + $(manpages) \ + $(catalogs.cat) \ + $(sources.o) \ + $(sources.to) \ + $(sources.xa) \ + $(sources.bin) \ + src/main.o \ + src/main.xa \ + src/main.bin \ -$(CRT_OBJS): CFLAGS_ALL += -DCRT +side-assets = \ + $(fuzz.o) \ + $(fuzz.xa) \ + $(fuzz.bin) \ -$(LOBJS) $(LDSO_OBJS): CFLAGS_ALL += -fPIC -CC_CMD = $(CC) $(CFLAGS_ALL) -c -o $@ $< -# Choose invocation of assembler to be used -ifeq ($(ADD_CFI),yes) - AS_CMD = LC_ALL=C awk -f $(srcdir)/tools/add-cfi.common.awk -f $(srcdir)/tools/add-cfi.$(ARCH).awk $< | $(CC) $(CFLAGS_ALL) -x assembler -c -o $@ - -else - AS_CMD = $(CC_CMD) -endif +## Default target. Builds all artifacts required for testing +## and installation. +all: $(derived-assets) -obj/%.o: $(srcdir)/%.s - $(AS_CMD) -obj/%.o: $(srcdir)/%.S - $(CC_CMD) +lib$(NAME).a: $(libc.c:.c=.o) $(libc.s:.s=.o) +src/main.xa: $(sources.o) src/main.o +$(fuzz.bin): lib$(NAME).a +$(manpages) src/config.h: Makefile deps.mk +$(sources.o) $(sources.to): Makefile deps.mk src/config.h -obj/%.o: $(srcdir)/%.c $(GENH) $(IMPH) - $(CC_CMD) -obj/%.lo: $(srcdir)/%.s - $(AS_CMD) +lib$(NAME).a $(sources.xa) src/main.xa $(fuzz.xa) $(empty-libs.a): + $(AR) $(ARFLAGS) $@ $? -obj/%.lo: $(srcdir)/%.S - $(CC_CMD) +src/$(NAME).en.cat: src/i18n.bin + env DUMP_TRANSLATABLE_STRINGS=1 $(EXEC)src/i18n.bin > $*.msg.new + cmp -s $*.msg.new $*.msg || mv $*.msg.new $*.msg + rm -f $*.msg.new + gencat $@ $*.msg + touch $@ -obj/%.lo: $(srcdir)/%.c $(GENH) $(IMPH) - $(CC_CMD) +libc.a: lib$(NAME).a + ln -fs lib$(NAME).a $@ -lib/libc.so: $(LOBJS) $(LDSO_OBJS) - $(CC) $(CFLAGS_ALL) $(LDFLAGS_ALL) -nostdlib -shared \ - -Wl,-e,_dlstart -o $@ $(LOBJS) $(LDSO_OBJS) $(LIBCC) -lib/libc.a: $(AOBJS) - rm -f $@ - $(AR) rc $@ $(AOBJS) - $(RANLIB) $@ -$(EMPTY_LIBS): - rm -f $@ - $(AR) rc $@ +src/catalog.bin-check: src/$(NAME).en.cat -lib/%.o: obj/crt/$(ARCH)/%.o - cp $< $@ -lib/%.o: obj/crt/%.o - cp $< $@ +.SUFFIXES: .bin-check +# sources.bin-check = $(sources.c:.c=.bin-check) +$(sources.bin-check): + $(EXEC)$*.bin -lib/musl-gcc.specs: $(srcdir)/tools/musl-gcc.specs.sh - sh $< "$(includedir)" "$(libdir)" "$(LDSO_PATHNAME)" > $@ +check-unit: $(sources.bin-check) -obj/musl-gcc: - printf '#!/bin/sh\nexec "$${REALGCC:-$(WRAPCC_GCC)}" "$$@" -specs "%s/musl-gcc.specs"\n' "$(libdir)" > $@ - chmod +x $@ -obj/%-clang: $(srcdir)/tools/%-clang.in - sed -e 's!@CC@!$(WRAPCC_CLANG)!g' -e 's!@PREFIX@!$(prefix)!g' -e 's!@INCDIR@!$(includedir)!g' -e 's!@LIBDIR@!$(libdir)!g' -e 's!@LDSO@!$(LDSO_PATHNAME)!g' $< > $@ - chmod +x $@ +## Run all tests. Each test suite is isolated, so that a parallel +## build can run tests at the same time. The required artifacts +## are created if missing. +check: check-unit -$(DESTDIR)$(bindir)/%: obj/% - $(INSTALL) -D $< $@ -$(DESTDIR)$(libdir)/%.so: lib/%.so - $(INSTALL) -D -m 755 $< $@ -$(DESTDIR)$(libdir)/%: lib/% - $(INSTALL) -D -m 644 $< $@ +fuzz.bin-check = $(fuzz.c:.c=.bin-check) +$(fuzz.bin-check): + $(EXEC)$*.bin tests/fuzz/corpus/ $(FUZZFLAGS) -$(DESTDIR)$(includedir)/bits/%: $(srcdir)/arch/$(ARCH)/bits/% - $(INSTALL) -D -m 644 $< $@ +## Run fuzzing targets indefinitely. +fuzz: $(fuzz.bin-check) -$(DESTDIR)$(includedir)/bits/%: $(srcdir)/arch/generic/bits/% - $(INSTALL) -D -m 644 $< $@ -$(DESTDIR)$(includedir)/bits/%: obj/include/bits/% - $(INSTALL) -D -m 644 $< $@ - -$(DESTDIR)$(includedir)/%: $(srcdir)/include/% - $(INSTALL) -D -m 644 $< $@ - -$(DESTDIR)$(LDSO_PATHNAME): $(DESTDIR)$(libdir)/libc.so - $(INSTALL) -D -l $(libdir)/libc.so $@ || true - -install-libs: $(ALL_LIBS:lib/%=$(DESTDIR)$(libdir)/%) $(if $(SHARED_LIBS),$(DESTDIR)$(LDSO_PATHNAME),) - -install-headers: $(ALL_INCLUDES:include/%=$(DESTDIR)$(includedir)/%) - -install-tools: $(ALL_TOOLS:obj/%=$(DESTDIR)$(bindir)/%) - -install: install-libs install-headers install-tools - -musl-git-%.tar.gz: .git - git --git-dir=$(srcdir)/.git archive --format=tar.gz --prefix=$(patsubst %.tar.gz,%,$@)/ -o $@ $(patsubst musl-git-%.tar.gz,%,$@) - -musl-%.tar.gz: .git - git --git-dir=$(srcdir)/.git archive --format=tar.gz --prefix=$(patsubst %.tar.gz,%,$@)/ -o $@ v$(patsubst musl-%.tar.gz,%,$@) - -endif +## Remove *all* derived artifacts produced during the build. +## A dedicated test asserts that this is always true. clean: - rm -rf obj lib - -distclean: clean - rm -f config.mak - -.PHONY: all clean install install-libs install-headers install-tools + rm -rf $(derived-assets) $(side-assets) + + +## Installs into $(DESTDIR)$(PREFIX). Its dependency target +## ensures that all installable artifacts are crafted beforehand. +install: all + mkdir -p \ + '$(DESTDIR)$(BINDIR)' \ + '$(DESTDIR)$(LIBDIR)' \ + '$(DESTDIR)$(INCLUDEDIR)' + cp src/main.bin '$(DESTDIR)$(BINDIR)'/$(NAME) + # FIXME headers in '$(DESTDIR)$(INCLUDEDIR)' + cp -P lib$(NAME).a $(empty-libs.a) libc.a '$(DESTDIR)$(LIBDIR)' + for f in $(FIXME_sources); do \ + dir='$(DESTDIR)$(SRCDIR)'/"`dirname "$${f#src/}"`"; \ + mkdir -p "$$dir"; \ + cp -P "$$f" "$$dir"; \ + done + for l in $(LANGUAGES); do \ + dir='$(DESTDIR)$(LOCALEDIR)'/"$$l"/LC_MESSAGES; \ + mkdir -p "$$dir"; \ + cp src/$(NAME)."$$l".cat "$$dir"/$(NAME).cat; \ + done + sh tools/manpages.sh -ip '$(DESTDIR)$(MANDIR)' $(manpages) + +## Uninstalls from $(DESTDIR)$(PREFIX). This is a perfect mirror +## of the "install" target, and removes *all* that was installed. +## A dedicated test asserts that this is always true. +uninstall: + rm -rf \ + '$(DESTDIR)$(BINDIR)'/$(NAME) \ + '$(DESTDIR)$(LIBDIR)'/lib$(NAME).a \ + '$(DESTDIR)$(INCLUDEDIR)'/$(NAME).h \ + '$(DESTDIR)$(SRCDIR)' + for l in $(empty-libs.a) libc.a; do \ + rm -f '$(DESTDIR)$(LIBDIR)'/"$$l"; \ + done + for l in $(LANGUAGES); do \ + rm -f '$(DESTDIR)$(LOCALEDIR)'/"$$l"/LC_MESSAGES/$(NAME).cat; \ + done + sh tools/manpages.sh -up '$(DESTDIR)$(MANDIR)' $(manpages) + + +MAKEFILE = Makefile +## Show this help. +help: + cat $(MAKEFILE) | sh tools/makehelp.sh + + +ALWAYS: -- cgit v1.2.3