# Makefile using 'objcopy' and custom Suffix Rules to convert text files to linkable object files

SHELL=sh

# Usage:
# make clean all run

OBJCOPY = objcopy
XXD     = xxd

CFLAGS = -g -Wall -Wextra -Werror -ansi -pedantic

MAKEFILE = Makefile

PRG = webobjects

# Directories
BUILD_DIR=build
WWW_DIR=www

# Generated files
WWW_OBJS_H=wwwmem-objs.h
WWW_OBJS_O=wwwmem-objs.o
WWW_PATHS_C=wwwmem-paths.c
WWW_PAIRS_C=wwwmem-pairs.c

# Files
WEB_PAGES = index.html anotherpage.html

# File objects
TXT_OBJ = $(PRG)-text.o
SRC_OBJ = $(PRG)-main.o

# C objects

.PHONY: all struct run clean demo democlean

all: $(PRG)

demo:
	make -f Makefile.demo clean all run
democlean:
	make -f Makefile.demo clean

$(PRG): struct wwwmem.o $(PRG)-main.o
	$(CC) $(CFLAGS) $(BUILD_DIR)/$(WWW_OBJS_O) wwwmem.o $(PRG)-main.o -o $(PRG)
wwwmem.o: wwwmem.c
$(PRG)-main.o: $(PRG)-main.c

rm-rf: recur-dir.o rm-rf.o
	$(CC) $(CFLAGS) $^ -o $@
#rm-rf-alt: rm-rf-alt.o
#	$(CC) $(CFLAGS) $^ -o $@
rm-rf-apple: rm-rf.o rm-rf-apple.o
	$(CC) $(CFLAGS) $^ -o $@
# traverse-rm: generic version of rm-rf-apple
traverse-rm: traversewfp.o rm-rf.o traverse-rm.o
	$(CC) $(CFLAGS) $^ -o $@
traverse-ls: traversewfp.o traverse-ls.o
	$(CC) $(CFLAGS) $^ -o $@
traverse-count: traversewfp.o traverse-count.o
	$(CC) $(CFLAGS) $^ -o $@

buildwww: mkdir-p.o recur-dir.o find-files.o buildwww.o
	$(CC) $(CFLAGS) $^ -o $@

# Parse all input files in a directory (with subdirectories), detect MIME type, and byte-convert using 'xxd', compile into object files.
# This Makefile rule works, but is really big and not very elegant.
# It is also probably quite slow for a big number of input files.
# Use the 'buildwww' C program instead to speed things up.
struct:
	mkdir -p ${BUILD_DIR}
#	printf "extern char *%s_path;\n" $$symbol >> $(BUILD_DIR)/$(PRG).h; \
#	  printf "extern int *%s;\n" $$len >> $(BUILD_DIR)/$(PRG).h; \
#	  printf "char *%s = 0;\n" $$symbol \
#	  && printf "int %s = 42;\n" $$symbol_len \
#	Loop through all files in WWW_DIR
#	Translate each file into an object file
	@printf "%s\n" "#ifndef _WWWMEM_OBJS_H_" > $(BUILD_DIR)/$(WWW_OBJS_H)
	@printf "%s\n\n" "#define _WWWMEM_OBJS_H_" >> $(BUILD_DIR)/$(WWW_OBJS_H)
	@printf "#define NUM_FILES %s\n\n" `find $(WWW_DIR) -type f|wc -l` >> $(BUILD_DIR)/$(WWW_OBJS_H)
	@printf "%s\n" "const char **wwwmem_get_paths()" > $(BUILD_DIR)/$(WWW_PATHS_C)
	@printf "%s\n" "{" >> $(BUILD_DIR)/$(WWW_PATHS_C)
	@printf "  %s\n" "static const char *paths[] =" >> $(BUILD_DIR)/$(WWW_PATHS_C)
	@printf "  %s\n"  "{" >> $(BUILD_DIR)/$(WWW_PATHS_C)
	@file_index=0; \
	for f in `find $(WWW_DIR) -type f`; do \
	  xxd_output=`$(XXD) -i $$f`; \
	  symbol_len=`printf "%s" "$$xxd_output" | tail -1 | cut -d ' ' -f 3`; \
	  symbol=`echo $$symbol_len | sed 's/_len$$//'`; \
	  mime=`file -b --mime-type $$f`; \
	  symbol_web_path=`echo $$f | sed 's/^$(WWW_DIR)//'`; \
	  printf "www_t wwwmem_get_%s(void);\n" $$symbol >> $(BUILD_DIR)/$(WWW_OBJS_H); \
	  printf "    \"%s\",\n" $$symbol_web_path >> $(BUILD_DIR)/$(WWW_PATHS_C); \
	  file_index=`expr $$file_index + 1`; \
	  ( \
	  printf "%s\n" "#include \"wwwmem-defs.h\"" \
	  && printf "www_t wwwmem_get_%s()\n" $$symbol \
	  && printf "%s\n" "{" \
	  && printf "  %s\n" "$$xxd_output" \
	  && printf "  const char *%s_path = \"%s\";\n" $$symbol $$symbol_web_path \
	  && printf "  const char *%s_mime = \"%s\";\n" $$symbol $$mime \
	  && printf "  %s\n" "static www_t wwwt;" \
	  && printf "  wwwt.body = %s;\n" $$symbol \
	  && printf "  wwwt.len = %s_len;\n" $$symbol \
	  && printf "  wwwt.path = %s_path;\n" $$symbol \
	  && printf "  wwwt.mime = %s_mime;\n" $$symbol \
	  && printf "  %s\n" "return wwwt;" \
	  && printf "%s\n" "}" \
	  ) \
	  | $(CC) -c -xc - -o $(BUILD_DIR)/$$symbol.o; \
	done
	$(CC) -Wl,-r $(BUILD_DIR)/www_*.o -o $(BUILD_DIR)/$(WWW_OBJS_O) -nostdlib
	@echo "Processed `find $(WWW_DIR) -type f|wc -l` files"
	@printf "    %s\n" "0" >> $(BUILD_DIR)/$(WWW_PATHS_C)
	@printf "  %s\n" "};" >> $(BUILD_DIR)/$(WWW_PATHS_C)
	@printf "  %s\n" "return paths;" >> $(BUILD_DIR)/$(WWW_PATHS_C)
	@printf "%s\n" "}" >> $(BUILD_DIR)/$(WWW_PATHS_C)
	@printf "\n%s\n" "#endif /* _WWWMEM_OBJS_H_ */" >> $(BUILD_DIR)/$(WWW_OBJS_H)
#	nm $(BUILD_DIR)/$(PRG).o

run:
	@echo --------------------------------------------------------------------------------
	./$(PRG)
	@echo --------------------------------------------------------------------------------


dltest1: dltest1.c dltest1_plugin.so
	$(CC) -o dltest1 dltest1.c -ldl

dltest1_plugin.so: dltest1_plugin.c
	$(CC) -shared -o dltest1_plugin.so dltest1_plugin.c

.SUFFIXES: .txt .htm .html .css .js .jpg .jpeg .png .gif
.txt.o:
	@echo "$<: $@"
	@echo "    Convert text file '$<' to object file '$@'"
	$(LD) -r -o "$@" $(EXEC_STACK) --format=binary "$<"
	$(OBJCOPY) --rename-section .data=.rodata,alloc,load,readonly,data,contents "$@"
	@echo --------------------------------------------------------------------------------
	@nm $@
	@echo --------------------------------------------------------------------------------
.htm.o:
	@echo "$<: $@"
	@echo "    Convert .htm file '$<' to object file '$@'"
	$(LD) -r -o "$@" $(EXEC_STACK) --format=binary "$<"
	$(OBJCOPY) --rename-section .data=.rodata,alloc,load,readonly,data,contents "$@"
	@echo --------------------------------------------------------------------------------
	@nm $@
	@echo --------------------------------------------------------------------------------
.html.o:
	@echo "$<: $@"
	@echo "    Convert .html file '$<' to object file '$@'"
	$(LD) -r -o "$@" $(EXEC_STACK) --format=binary "$<"
	$(OBJCOPY) --rename-section .data=.rodata,alloc,load,readonly,data,contents "$@"
	@echo --------------------------------------------------------------------------------
	@nm $@
	@echo --------------------------------------------------------------------------------


clean:
	rm -f *.o *.exe
	rm -rf $(BUILD_DIR)
	rm -f dltest1_plugin.so dltest1 dltest1.exe
	rm -f $(PRG)
	rm -f buildwww
	rm -f traverse-rm
