#! /usr/bin/make -f #--- # # fxlibc project Makefile # # This makefile is grandly inspired by the one used for the Gint (unikernel) # project, 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 # `-- ouptut/ # |-- static/ # | |--- libfxlibc.a # | |--- libfxlibc-casio-abi-fx9860.a # | `--- libfxlibc-casio-abi-fxcg50.a # `--- dynamic/ # |--- libfxlibc.so # |--- libfxlibc-casio-abi-fx9860.so # `--- libfxlibc-casio-abi-fxcg50.so # # TODO: # * handle dynamic versioning # * handle verbose option #--- MAJOR := 0 MINOR := 3 PATCH := 2 EXTRAVERSION := #--- # 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 # Define all directories used to stored information dir_object := object dir_output := output # Output configurations name := fxlibc # Automated variables 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 #--- # 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: %/ #--- # Generate building rules #--- # This function will generate compilation rule for each source. # @params: # *1 - source file path # *2 - build directory path (output) # *3 - build flags # TODO: # * handle verbose option define generate-compilation-rule $(patsubst .._src_%,$2%.o,$(subst /,_,$(basename $1))): $1 | $2/ @ printf "$(green)>$(nocolor) $(white)$$@$(nocolor)\n" @ $(gcc) $3 -o $$@ -c $$< -lgcc endef # Function that will generate all rules for building each library. # @params: # * 1 - library name # * 2 - format (dynamic/static) # * 3 - source file list define generate-target # Generate all variables (library name based on the wanted formats, output # directory, ...) used by each rule that will be generated. 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-version) lib-cflags := -fPIC $(cflags) else lib-name := $$(lib-output-dir)lib$1.a lib-cflags := $(cflags) endif # add custom project-specific flags based on the target ABI ifeq ($1,fxlibc-vhex) lib-cflags += -D __SUPPORT_VHEX_KERNEL else ifeq ($1,fxlibc-casio-abi-fx9860g) lib-cflags += -D __SUPPORT_CASIO_ABI_FX9860G else ifeq ($1,fxlibc-casio-abi-fxcf50) lib-cflags += -D __SUPPORT_CASIO_ABI_FXCG50 endif # Generate all file compilation rules $$(foreach source,$3,$$(eval \ $$(call generate-compilation-rule,$$(source),$$(lib-build-dir),$$(lib-cflags)) \ )) # Register the library building rule name # @note: # This rule list (lib-generation-rules) is used by the main compiling rule like # a dependency. And it's this dependency that will involve all generated rules # for building each library. lib-generation-rules += $$(lib-name) # Generate the linking library rule # TODO # * Find better way to generate binary files name dependency $$(lib-name): $$(patsubst .._src_%,$$(lib-build-dir)%.o,$$(subst /,_,$$(basename $3))) | $$(lib-output-dir) ifeq ($2,dynamic) $(gcc) -shared -Wl,-soname=$$@ -o $$@ $$^ -nostdlib -lgcc else $(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 dynamic makecode generation # (generated by the "foreach"). This variable will list all rules generated for # building each library and used like a dependency by the main rule. lib-generation-rules := # Generate the library version (used only by the dynamic library format). lib-version := $(MAJOR).$(MINOR).$(PATCH)$(EXTRAVERSION) # Generate all building rules $(foreach format,$(target-formats), \ $(foreach lib,$(target-libs),$(eval \ $(call generate-target,$(lib),$(format),$(src)) \ )) \ ) #--- # Build rules #--- all: $(lib-generation-rules) version: @ echo "$(lib-version)" #--- # Generate installation rules #--- # Common rules generated for the installation of each libraries. # Basically, it will generate -install and -uninstall rules # @note: # *1 - library pathname define generate-install-rule # get the library name (remove path information) lib-basename := $(notdir $1) # Genetate rules name lib-install-rule := $$(basename $$(lib-basename))-install lib-uninstall-rule := $$(basename $$(lib-basename))-uninstall # Generate the installation rule $$(lib-install-rule): install -d $(CONFIG.PREFIX) install $1 -m 644 $(CONFIG.PREFIX) # Generate the uninstallation rule $$(lib-uninstall-rule): rm -f $(CONFIG.PREFIX)$$(lib-basename) # Register generated rules into their appropriate list lib-installation-rules += $$(lib-install-rule) lib-uninstallation-rules += $$(lib-uninstall-rule) endef # Internal variable used to store all rules about installation/uninstallation lib-installation-rules := lib-uninstallation-rules := # Generate all installation/unstallation rules $(foreach libs,$(lib-generation-rules),$(eval \ $(call generate-install-rule,$(libs)) \ )) # Generate the path where include directory will be installed. lib-install-header-dir := $(CONFIG.PREFIX)include/fxlibc #--- # Installation rules #--- install: $(lib-generation-rules) $(lib-installation-rules) rm -rf $(lib-install-header-dir) cp -r ../include $(lib-install-header-dir) uninstall: $(lib-uninstallation-rules) rm -rf $(lib-install-header-dir) #--- # (internal ) debug rule #--- #DEBUG=$(call generate-target,fxlibc-vhex,static,$(dir_objects),$(src)) DEBUG=$(call generate-install-rule,/output/static/fxlibc.a) export DEBUG debug: @ echo "$$DEBUG" @ echo "target-lib: $(target-libs)" @ echo "generated lib: $(lib-generation-rules)" @ echo "target format: $(target-formats)" @ echo "install-rules: $(lib-installation-rules)" @ echo "uninstall-rules: $(lib-uninstallation-rules)" #--- # cleaning rules #--- clean: rm -rf $(dir_object) fclean: clean rm -rf $(dir_output) re: fclean all .PHONY: clean fclean re