edit: This little project eventually went nowhere as I kept understanding Make better and better. In the end I deemed it good enough for my purposes and decided writing my own replacement wasn't worth the time.
Realizing that I didn't want xmk to miss Make's core feature made me feel a bit silly for trying to reinvent it. Thus I ended up spending a good couple hours trying to come up with a Makefile that could make me feel satisfied. Pretending I was only ever building for one platform without any separate debug buils led me to this:
001 PRJNAME = my_app # name of bin to build 002 SRCD = src # root dir of src files 003 LIBD = lib # root dir of vendor src files 004 SRC := $(shell find $(SRCD) -name '*.c') # recursively get all src files from src dir 005 SRC += $(shell find $(LIBD) -name '*.c') # append those from vendor dir 006 OBJ = $(patsubst %.c, xmk.d/obj/linux/%.o, $(SRC)) # get obj filenames for all src files 007 DEP = $(patsubst %.o, %.d, $(OBJ)) # filenames to save header dependencies to 008 BIN = xmk.d/bin/linux/$(PRJNAME) # where to save the binary... 009 010 CC = gcc 011 CFLAGS = -Isrc/include 012 LDFLAGS = 013 014 015 all: linux win64 # we omit the win64 build for brevity 016 017 018 $(BIN): $(OBJ) # this is run last in the chain, after compiling objects 019 $(CC) $(OBJ) -o $@ 020 021 xmk.d/obj/linux/$(SRCD)/%.o: $(SRCD)/%.c # ugly and unwieldy copy/paste 022 mkdir -p $(@D) # however could be remedied by placing lib/ in src/ 023 $(CC) $(CFLAGS) -MMD -MP -c $< -o $@ 024 xmk.d/obj/linux/$(LIBD)/%.o: $(LIBD)/%.c 025 mkdir -p $(@D) # these create the necessary dirs to hold obj and dep files 026 $(CC) $(CFLAGS) -MMD -MP -c $< -o $@ 027 028 .PHONY: clean linux 029 clean: $(OBJ) $(DEP) # getting rid of all the build files 030 rm $(OBJ) $(DEP) 031 032 linux: $(BIN) # so the user can run the target by specifying the platform 033 034 -include $(DEP) # include dependency files 035
Still this isn't a Makefile one would use in a real project. There's not even an option to create a debug build. I played around with a phony rule
debug that would use
($eval....) to modify variables before running the build process, but it unfortunately didn't work out. The possible solutions I've come across to solve the remaining issues all don't sit well with me and are the main reason I was trying to develop my own build tool. That said, at this point it appears best to redevelop xmk as a build assistant around Make that either adds preprocessing to Makefiles or build Makefiles from config files that describe all the required rules and targets in a hierarchical way.
Right now I'm gravitating towards the latter option, especially since it would allow me to have one build tool for all sorts of programming environments.
So my conclusion remains that Make gets uncomfortable to deal with the moment you plan on using more than one or two simple target binaries in a Makefile.