summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2019-01-27 18:36:58 -0500
committerJakob Kaivo <jkk@ung.org>2019-01-27 18:36:58 -0500
commit0ca793b65069d8ba9a61f48228ffb982ef233c1a (patch)
treeea462b4de8ba616ee4a6cd6ba2034df857807a7c
parent0bd12f61b7a0213775a0e3d5fbc32bd4213c76e8 (diff)
new utility to generate makefiles with dependencies
-rwxr-xr-xmkmf.sh109
1 files changed, 109 insertions, 0 deletions
diff --git a/mkmf.sh b/mkmf.sh
new file mode 100755
index 00000000..8861a7ad
--- /dev/null
+++ b/mkmf.sh
@@ -0,0 +1,109 @@
+#!/bin/sh
+
+classify_source () {
+ NAME=$(basename $1 .c)
+
+ if grep -q "define ${NAME}[ (]" $1; then
+ echo MACRO
+ elif grep -q "typedef.* ${NAME};" $1; then
+ echo TYPE
+ elif grep -q "typedef.*{$" $1; then
+ echo TYPE_LONG
+ elif grep -q "struct.*${NAME} {" $1; then
+ echo STRUCT
+ elif grep -q "union.* ${NAME} {" $1; then
+ echo UNION
+ elif grep -q "^[A-Za-z_].* ${NAME};" $1; then
+ echo EXTERN
+ else
+ echo FUNCTION
+ fi
+}
+
+STANDARD=${1-9899-1990}
+#STANDARD=${1-POSIX.1-1990}
+
+if [ ! -f .dep/to-build ]; then
+ rm -rf .dep Makefile header.mk
+ mkdir -p .dep
+ echo ${STANDARD} > .dep/to-build
+fi
+
+if [ ! -d std/${STANDARD} ]; then
+ printf "Standard %s not found.\n" "${STANDARD}"
+ exit 1
+fi
+
+if [ -f std/${STANDARD}/INCLUDE ]; then
+ for i in $(cat std/${STANDARD}/INCLUDE); do
+ $0 $i
+ done
+fi
+
+rm -f .dep/${STANDARD}.*
+
+for i in $(find std/${STANDARD} -name \*.c); do
+ NAME=$(basename $i .c)
+ TYPE=$(classify_source $i)
+ HEADER=$(sed -ne 's/.*<\(.*\.h\)>.*/\1/p' $i)
+ LIB=$(grep '^LINK(' $i | m4 -DLINK='lib$1')
+ LIB=${LIB:-libc}
+
+ if [ ! -f .dep/${HEADER}.mk ]; then
+ mkdir -p $(dirname .dep/${HEADER}.mk)
+ printf '$(INCDIR)/%s:' "${HEADER}" > .dep/${HEADER}.mk
+ fi
+ printf ' \\\n\t%s' "$i" >> .dep/${HEADER}.mk
+
+ if [ ${TYPE} = EXTERN -o ${TYPE} = FUNCTION ]; then
+ printf '$(OBJDIR)/%s.o: %s $(INCDIR)/%s' ${NAME} $i ${HEADER}> .dep/${NAME}.o.mk
+ for j in $(grep include $i); do
+ : # TODO: add each header to depends file here
+ done
+ printf '\n\t-@mkdir -p $(OBJDIR)\n\t$(CC) $(CFLAGS) -c %s -o $@\n\n' $i >> .dep/${NAME}.o.mk
+
+ if [ ! -f .dep/${LIB}.a.mk ]; then
+ printf '%s_OBJS =' ${LIB} > .dep/${LIB}.a.mk
+ if [ ${LIB} = libc ]; then
+ printf ' $(OBJDIR)/libc.o $(OBJDIR)/x86-64.o' >> .dep/${LIB}.a.mk
+ fi
+ fi
+ printf ' \\\n\t$(OBJDIR)/%s.o' ${NAME} >> .dep/${LIB}.a.mk
+ fi
+
+done
+
+if [ $(cat .dep/to-build) = ${STANDARD} ]; then
+ printf '.POSIX:\n\n' > Makefile
+ printf 'default: all\n\n' >> Makefile
+ printf 'include config.mk\n\n' >> Makefile
+ printf 'INCLUDES=-I$(INCDIR) -I. -Inonstd/stubs\n' >> Makefile
+ printf 'CFLAGS=$(INCLUDES) -g -fno-builtin -nostdinc -nostdlib -nodefaultlibs -Werror -Wall -Wextra -fPIC\n\n' >> Makefile
+
+ for i in .dep/lib*.a.mk; do
+ LIB=$(basename $i .a.mk)
+ cat $i >> Makefile
+ printf '\n\n%s.a: $(%s_OBJS)\n\t$(AR) r $@ $?\n\n' $LIB $LIB >> Makefile
+ done
+
+ printf '.POSIX:\n\ninclude config.mk\n\n' > headers.mk
+ for i in $(find .dep -name \*.h.mk); do
+ cat $i >> headers.mk
+ printf '\n\t./gen-header $@\n\n' >> headers.mk
+ done
+
+ cat .dep/*.o.mk >> Makefile
+
+ printf '$(OBJDIR)/libc.o: nonstd/libc.c\n\t$(CC) $(CFLAGS) -c $? -o $@\n\n' >> Makefile
+ printf '$(OBJDIR)/x86-64.o: nonstd/x86-64.s\n\t$(CC) $(CFLAGS) -c $? -o $@\n\n' >> Makefile
+
+ printf 'all:' >> Makefile
+ for i in .dep/lib*.a.mk; do
+ printf ' %s' $(basename $i .mk) >> Makefile
+ done
+ printf '\n\n' >> Makefile
+
+ printf 'clean:\n\trm -rf $(OBJDIR) *.a\n\n' >> Makefile
+ printf 'git-clean: clean\n\trm -rf .dep header.mk Makefile\n\n' >> Makefile
+
+fi