#! /usr/bin/make -f #--- # # fxlibc project Makefile # # This makefile is grandly inspired by the Gint unikernel # projet, many thanks to Lephenixnoir ! # # Build architecture: # build/ # |-- objects/ # | |-- string_strlen.o # | |-- string_strcmp.o # | ... # | `-- signal_kill.o # |-- debug/ # | |-- fxlibc.map (ELF link map informations) # | ... # | `-- otherinfo.txt # |-- Makefile # |-- fxlibc.cfg # `-- bin/ # |-- fxlibc_stubs.a (workaround for the shared librairie, see documentation note) # |-- fxlibc.so (shared librairy) # `-- fxlibc.a (static librairy) # # TODO: # * generate all libraries for all ABI by default ? # * handle versionning #--- #--- # Build configuration #--- # Require configuration file (if you want to clean up and lost the file, you # can either reconfigure or just delete the build directory) CONFIG := fxlibc.cfg ifeq "$(wildcard $(CONFIG))" "" $(error "config file $(CONFIG) does not exist (reconfigure or wipe directory)") endif include $(CONFIG) # Compiler flags, assembler flags, dependency generation, archiving header := ../include cflags := $(machine) -ffreestanding -nostdlib -Wall -Wextra -std=c11 -Os \ -fstrict-volatile-bitfields -I$(header) $(CONFIG.CFLAGS) # color definition red := \033[1;31m green := \033[1;32m blue := \033[1;34m white := \033[1;37m nocolor := \033[1;0m # This is a workaround to force a newline when the "eval" keyword is involved define n # Force newline character endef # Define all directory used to stored informations dir_object := object dir_output := output dir_bin := bin # Output configurations name := fxlibc target := $(dir_bin)/$(name).a # automated variable directory := $(shell find ../src -not -path "*/\.*" -type d) src := $(foreach path,$(directory), \ $(wildcard $(path)/*.c) \ $(wildcard $(path)/*.S) \ $(wildcard $(path)/*.s)) #--- # Toolchain #--- gcc = $(CONFIG.TOOLCHAIN)-gcc as = $(CONFIG.TOOLCHAIN)-as ld = $(CONFIG.TOOLCHAIN)-ld ar = $(CONFIG.TOOLCHAIN)-ar objcopy = $(CONFIG.TOOLCHAIN)-objcopy #--- # Version management #--- # TODO #--- # Build rules #--- # (Make selects the first rule when you type "make" and I don't want the first # rule to be "%/" so here's a placeholder) first: all # Create directory helper # @note: Just use "$*" and "$@" to refer to the directory being created. %/: @ printf "Create $(blue)$*$(nocolor) directory\n" @ mkdir -p $@ .PRECIOUS: %/ #--- # Automated rules #--- # common part used to compile source file # @params: # *1 - source file path # *2 - build directory path (output) # TODO: # * handle custom cflags (format, abi management) # * handle verbose option define compile-src $(patsubst .._src_%,$2/%.o,$(subst /,_,$(basename $1))): $1 | $2/ @ printf "compiling $(white)$$@$(nocolor)..." @ $(gcc) $(cflags) -o $$@ -c $$< -lgcc @ printf "$(green)[ok]$(nocolor)\n" endef # common part used by all library geneation # @params: # * 1 - library name # * 2 - format (dynamic/static) # * 3 - source file list define generate-target # generate the library name based on the wanted formats lib-output-dir := $(dir_output)/$2/ lib-build-dir := $(dir_object)/$2/$1/ ifeq ($2,dynamic) lib-name := $$(lib-output-dir)/lib$1.so lib-cflags := -pic $(cflags) else lib-name := $$(lib-output-dir)/lib$1.a lib-cflags := $(cflags) endif # indicate the new lib that will be ouputed generated-libs += $$(lib-name) # generate all file object name $$(foreach source,$3,$$(eval \ $$(call compile-src,$$(source),$$(lib-build-dir)) \ )) # link the library # @note: based on the wanted format ifeq ($2,shared) $$(lib-name): $$(patsubst .._src_%,$$(lib-build-dir)/%.o,$$(subst /,_,$$(basename $3))) | $$(lib-output-dir) $(gcc) -shared -o $$@ $$^ -nostdlib -lgcc else $$(lib-name): $$(patsubst .._src_%,$$(lib-build-dir)/%.o,$$(subst /,_,$$(basename $3))) | $$(lib-output-dir) $(ar) crs $$@ $$^ endif endef # create all "target" variable used to determine which format # and which libraries will be generated. # @note: # * we force default variable if nothing is set target-formats := $(if $(CONFIG.FORMAT),$(CONFIG.FORMAT),static) target-libs := $(if $(CONFIG.TARGET),$(CONFIG.TARGET),fxlibc) # create a variable that will be updated during the generation of # the dynamic make code generation (generated by the "foreach") generated-libs := # Generate all targets $(foreach format,$(target-formats), \ $(foreach lib,$(target-libs),$(eval \ $(call generate-target,$(lib),$(format),$(src)) \ )) \ ) #--- # Build rule #--- all: $(generated-libs) DEBUG=$(call generate-target,fxlibc,static,$(dir_objects),$(src)) export DEBUG debug: @ echo "$$DEBUG" @ echo "target-lib: $(target-libs)" @ echo "generated lib: $(generated-libs)" @ echo "target format: $(target-formats)" #--- # clean rules #--- clean: rm -rf $(dir_objects) fclean: clean rm -rf $(dir_bin) re: fclean clean .PHONY: clean fclean re #--- # Build rules #--- #all: $(target) # ## linker part #$(target): $(obj) | $(dir_bin) # $(ar) crs $@ $^ # ## installation part #install: $(target) # install -d $(CONFIG.PREFIX) # install $(target) -m 644 $(CONFIG.PREFIX) # cp -r $(header) $(CONFIG.PREFIX)/include/fxlibc #uninstall: # rm -f $(CONFIG.PREFIX)/$(target) # rm -rf $(CONFIG.PREFIX)/include/fxlibc # ## Directory management #$(dir_bin) $(dir_objects): # @ printf "Create $(blue)$@$(nocolor) directory\n" # @ mkdir -p $@ # #.PHONY: all install uninstall # # # ##define rule-src ##$(patsubst .._src_%,$(dir_objects)/%.o,$(subst /,_,$(basename $1))): $1 | $(dir_objects) ## @ printf "compiling $(white)$$<$(nocolor)..." ## @ $(gcc) $(cflags) -o $$@ -c $$< -lgcc ## @ printf "$(green)[ok]$(nocolor)\n" ##endef ## ##$(foreach source,$(src),$(eval \ ## $(call rule-src,$(source))) \ ##) # # ##--- ## Debugging rules ##--- #help: # @ echo 'make [options]...' # @ echo '' # @ echo 'Options:' # @ echo ' * install install the library and headers to the PREFIX' # @ echo ' * uninstall uninstall the library and headers of the PREFIX' # @ echo ' * disasm use objdump to display the content of the archive' # @ echo ' * debug display source files name and objects name' # @ echo ' * elf_sec display ELF section of the archive' #__debug: # @ echo 'src: $(src)' # @ echo '' # @ echo 'obj: $(obj)' # @ echo '' # @ echo 'directory: $(dir_bin) $(dir_output) $(dir_objects)' # #disasm: # @ $(objdump) -D $(target) | less # #elf_sec: # @ $(objdump) -h $(target) | less # #.PHONY: help __debug disasm elf_sec # # ##--- ## clean rules ##--- #clean: # rm -rf $(dir_objects) # #fclean: clean # rm -rf $(dir_bin) # #re: fclean clean # #.PHONY: clean fclean re