From 9c59763ad77f095691a67103a1a7af9e64af140d Mon Sep 17 00:00:00 2001
From: Yatis <yann.magnin@epitech.eu>
Date: Wed, 7 Oct 2020 11:37:54 +0200
Subject: [PATCH] update Makefile

---
 .gitignore            |   1 +
 configure             | 160 ++++++++++++++++-----------
 make/Makefile.default | 245 ++++++++++++++++++++++++++++++++----------
 3 files changed, 287 insertions(+), 119 deletions(-)

diff --git a/.gitignore b/.gitignore
index 378eac2..4cf1d8d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
 build
+*.txt
diff --git a/configure b/configure
index 0bd4a17..05d7ac5 100755
--- a/configure
+++ b/configure
@@ -1,4 +1,9 @@
 #! /bin/bash
+#
+# -= TODO =-
+# * check if the wanted lib exist (check lib verion too)!
+# * option to list all installed libraries with their versions
+# * each ABI options define one specific libs (fxlibc-common, fxlibc-vhex, fxlibc-fx9860g, fxlibc-fxcg50)
 
 # output file
 confile='fxlibc.cfg'
@@ -13,38 +18,41 @@ makefile='Makefile.default'
 
 # configuration
 declare -A config
-config[__SUPPORT_VHEX_KERNEL]=false
 config[__DEBUG]=false
 config[__ENABLE_VALGRIND]=false
-config[__SUPPORT_CASIO_ABI_FX9860]=false
-config[__SUPPORT_CASIO_ABI_FXCG50]=false
+config[__SUPPORT_VHEX_KERNEL]=false
+config[__SUPPORT_CASIO_FX9860]=false
+config[__SUPPORT_CASIO_FXCG50]=false
 
-#
+#---
 # Help screen
-#
+#---
 help()
 {
 cat << EOF
-Configuration script for the fx calculator libc.
+Configuration script for the fx calculator standard C library.
 Usage: $0 [OPTION]...
 
 You should build out-of-tree by creating a build directory and configuring from
 there.
 
 Debug the fxlibc
-  --debug        enable valgrind flags (-g3)
-  --unit-test    check C-functoon validity with Criterion
+  --debug        Enable valgrind flags (-g3)
+  --unit-test    Check C-functoon validity with Criterion
 
 Build options:
-  --toolchain=TRIPLET    Build with a different toolchain
-                         [sh-elf-gcc] (or [gcc] when the '--unit_test' flag is set)
-  --cflags=FLAGS         Additional compiler flags at end of command
+  --toolchain=TRIPLET  Build with a different toolchain
+                       [sh-elf-gcc] (or [gcc] when the '--unit_test' flag is set)
+  --cflags=FLAGS       Additional compiler flags at end of command
+  --prefix=PREFIX      Install prefix (PREFIX/lib and PREFIX/include are used)
 
 ABI support:
-  --vhex-support                 Enable the Vhex kernel support
-  --casio-support=fx9860|fxcg50
-    enable the support of the Casio' ABI (used by malloc, free, ...)
-      
+  --support-vhex
+    Enable the Vhex kernel support
+  --support-casio-fx9860,
+  --support-casio-fxcg50
+    Enable the support of the Casio' ABI (used by malloc, free, ...)
+
     fx9860 covers all fx-9860G II-like monochromes models that support add-ins
     or can be flashed with an OS that does. This includes SH3 and SH4 machines.
 
@@ -52,27 +60,25 @@ ABI support:
     fx-CG 10/20. All of these are SH4-only.
 
 The 'ABI support' is used to allow some part of the code, in particular the 'unistd'
-part, I/O management and additionnal feature (process, fs, ...).
+part, I/O management and additionals feature. (like process, fs, ...).
 
 Format:
-    --dyn-lib   generate dynamic librairies (Vhex kernel dependant)
+    --dyn-lib   Generate dynamic librairies (Vhex kernel dependant)
 
-Little note for the generation of dynamic libraries.
-The superH toolchain currently used (GCC) does not support the '--shared' flags
-when the archive is build. So we need to create manually an archive that can be
-used like a shared librairy.
+Little note for the generation of dynamic libraries. The superH toolchain currently
+used (GCC) does not support the '--shared' flags when the archive is build. So we
+need to create manually an archive that can be used like a shared library.
 
 To do this we need to do several steps:
 1) build the sources with the PIE mode as if it were a executable without entry point.
 2) manually extract symbols defined as 'global' from the generated ELF.
-3) we create "stubs": functions that will have the same name than the wanted
-     shared librairies and will call internal VHEX loader primitives with the
-     librairies name, function address and size, etc....Then the loader will
-     load the shared function and override the "user function (stub)" to force
-     it to jump into the "real" function (trampoline)
-4) all generated stubs will be compiled and linked throught a static lib that
-     SHOULD be used in the user program which use the "dynamic librairy"
-
+3) we create "stubs": functions that will have the same name than the wanted shared
+     libraries and will call internal VHEX loader primitives with the libraries
+     name, function address and size, etc....Then the loader will load the shared
+     function and override the "user function (stub)" to force it to jump into
+     the "real" function (trampoline).
+4) all generated stubs will be compiled and linked through a static lib that SHOULD
+     be used in the user program which uses the "dynamic library"
 EOF
   exit 0
 }
@@ -85,8 +91,8 @@ EOF
 #   from there.
 #
 if [ -f 'make/Makefile.default' ]; then
-  echo "error: you should configure from a build directory, like this:" >&2
-  echo "  mkdir build && cd build && ../configure [options..]" >&2
+  echo 'error: you should configure from a build directory, like this:' >&2
+  echo '  mkdir build && cd build && ../configure [options..]' >&2
   exit 1
 fi
 
@@ -95,15 +101,16 @@ fi
 # Parsing arguments
 #
 for arg; do case "$arg" in
-  --help | -h) 
+  --help | -h)
     help;;
 
+  # debug options
   --debug)
     config[__DEBUG]=true;;
   --unit-test)
     makefile='Malefile.unitest';;
 
-  
+  # build options
   --toolchain=*)
     toolchain=${arg#*=};;
   --prefix=*)
@@ -111,68 +118,93 @@ for arg; do case "$arg" in
   --cflags=*)
     cflags=${arg#*=};;
 
-  --vhex-support)
+  # ABI support
+  --support-vhex)
     config[__SUPPORT_VHEX_KERNEL]=true;;
-  --casio-abi=*)
-    case ${arg#*=} in
-      "fx9860g")
-        config[__SUPPORT_CASIO_ABI_FX9860]=true;;
-      "fcg50")
-        config[__SUPPORT_CASIO_ABI_FXCG50]=true;;
-      *)
-        echo -e "\033[1;33merror\033[0m unreconized target '$arg'"
-        exit 1
-    esac;;
+  --support-casio-abi-fx9860)
+    config[__SUPPORT_CASIO_ABI_FX9860]=true;;
+  --support-casio-abi-fxcg50)
+    config[__SUPPORT_CASIO_ABI_FXCG50]=true;;
 
+  # format options
   --dyn-lib)
     makefile='Makefile.dynlib';;
+
+  # error part
   *)
-    echo -e "\033[1;33merror\033[0m unreconized argument '$arg'"
+    echo "error: unreconized argument '$arg', giving up." >&2
     exit 1
 esac; done
 
 
-#
+#---
 # Check error
-#
-if [ ${config[__SUPPORT_CASIO_ABI_FX9860]} = true ] && [ ${config[__SUPPORT_CASIO_ABI_FXCG50]} = true ]; then
-  echo -e "\033[1;33merror\033[0m too many target"
+#---
+# Check ABI support error
+if [ ${config[__SUPPORT_CASIO_ABI_FX9860]} = true ] && [ ${config[__SUPPORT_CASIO_ABI_FXCG50]} = true ] ||
+    [ ${config[__SUPPORT_VHEX_KERNEL]} = true ] && [ ${config[__SUPPORT_CASIO_ABI_FXCG50]} = true ] ||
+    [ ${config[__SUPPORT_VHEX_KERNEL]} = true ] && [ ${config[__SUPPORT_CASIO_ABI_FX9860]} = true ]; then
+  echo "error: too many ABI target" >&2
   exit 1
 fi
 
+# If no prefix is specified, install to the GCC's build folder
+if [[ -z "$prefix" ]]
+then
+  # ask the toolchain where is his installation path
+  echo "No prefix specified, let's ask the compiler:"
+  echo "  Call: \"$toolchain-gcc --print-search-dirs | grep install | sed 's/install: //'\""
+  if ! inst=$("$toolchain"-gcc --print-search-dirs | grep install | sed 's/install: //'); then
+    echo "  Call: returned $?, giving up." >&2
+    exit 1
+  fi
+  echo "  Got '$inst'".
+
+  # check if the directory exist
+  if [[ ! -d $inst ]]; then
+    echo "Directory does not exist (or is not a directory), giving up." >&2
+    exit 1
+  fi
+  prefix=$inst
+fi
+
 
 #
+# TODO: check if the wanted lib exist (check lib verion too)!
+#
+
+#---
 # Dump appropriate Makefile
 # @note:
 # * We have 3 makefile: normal, dynlib, unit_test
-#
+#---
 dst='Makefile'
 src="../make/$makefile"
 if ! test $src; then
-  echo -e "\033[1;33merror\033[0m target makefile ($src) does not exist !"
+  echo "error: target makefile ($src) does not exist !" >&2
   exit 1
 fi
-[ -L $src ] && [ "$(readlink $src)" == $dst ] && rm $dst
+[ $dst ] && [ "$(readlink $dst)" == $src ] && rm $dst
 ln -s $src $dst
 
 
-#
+#---
 # Generate the configuration file
-#
-function generate_config()
+#---
+generate_config()
 {
-  echo "CONFIG.TOOLCHAIN = $toolchain"
-  [ "$prefix" ] && echo "PREFIX = $prefix"
-  [ "$cflags" ] && echo "CONFIG.CFLAGS = $cflags"
+  echo "CONFIG.CFLAGS := "
+  echo "CONFIG.TARGET := "
+  echo "CONFIG.TOOLCHAIN := $toolchain"
+  [ "$prefix" ] && echo "CONFIG.PREFIX := $prefix"
+  [ "$cflags" ] && echo "CONFIG.CFLAGS += $cflags"
 
-  [ ${config[__DEBUG]} = true ] && echo -n '-g3'
-  [ ${config[__SUPPORT_VHEX_KERNEL]} = true ] && echo -n ' -D __SUPPORT_VHEX_KERNEL'
-  [ ${config[__SUPPORT_CASIO_ABI_FX9860]} = true ] && echo -n ' -D ___SUPPORT_CASIO_ABI_FX9860'
-  [ ${config[__SUPPORT_CASIO_ABI_FXCG50]} = true ] && echo -n ' -D ___SUPPORT_CASIO_ABI_FXCG50'
-  echo ''
+  #[ ${config[__DEBUG]} = true ] && echo "CONFIG.CFLAGS += -g3"
+  [ ${config[__SUPPORT_VHEX_KERNEL]} = true ] && echo "CONFIG.TARGET += fxlibc-vhex"
+  [ ${config[__SUPPORT_CASIO_ABI_FX9860]} = true ] && echo "CONFIG.TARGET += fxlibc-fx9860"
+  [ ${config[__SUPPORT_CASIO_ABI_FXCG50]} = true ] && echo "CONFIG.TARGET += fxlibc-fxcg50"
 }
 generate_config > $confile
 
-
 echo "Configuration saved in $confile, ready to make!"
 exit 0
diff --git a/make/Makefile.default b/make/Makefile.default
index 62702b0..ac21371 100644
--- a/make/Makefile.default
+++ b/make/Makefile.default
@@ -23,12 +23,15 @@
 #       |-- 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
@@ -37,11 +40,10 @@ $(error "config file $(CONFIG) does not exist (reconfigure or wipe directory)")
 endif
 include $(CONFIG)
 
-
 # Compiler flags, assembler flags, dependency generation, archiving
-header	:= -I ../include
+header	:= ../include
 cflags	:= $(machine) -ffreestanding -nostdlib -Wall -Wextra -std=c11 -Os \
-		-fstrict-volatile-bitfields $(header) $(CONFIG.CFLAGS)
+		-fstrict-volatile-bitfields -I$(header) $(CONFIG.CFLAGS)
 
 # color definition
 red	:= \033[1;31m
@@ -57,7 +59,8 @@ define n
 endef
 
 # Define all directory used to stored informations
-dir_objects	:= objects
+dir_object	:= object
+dir_output	:= output
 dir_bin		:= bin
 
 # Output configurations
@@ -65,19 +68,14 @@ name		:= fxlibc
 target		:= $(dir_bin)/$(name).a
 
 # automated variable
-src		:=
-directory	:= $(shell find ../src/ -not -path "*/\.*" -type d)
-$(foreach path,$(directory),$(eval		\
-	src	+= $(wildcard $(path)/*.c)	$n\
-	src	+= $(wildcard $(path)/*.S)	$n\
-	src	+= $(wildcard $(path)/*.s)	$n\
-))
-obj	:= $(patsubst .._src_%,$(dir_objects)/%.o,$(subst /,_,$(basename $(src))))
+directory	:= $(shell find ../src -not -path "*/\.*" -type d)
+src 		:= $(foreach path,$(directory), \
+			$(wildcard $(path)/*.c)	\
+			$(wildcard $(path)/*.S) \
+			$(wildcard $(path)/*.s))
+
+
 
-# check if any file have been found
-ifeq ($(obj),)
-$(error "source file does not exist (reconfigure or wipe directory)")
-endif
 
 
 #---
@@ -90,68 +88,117 @@ ar	= $(CONFIG.TOOLCHAIN)-ar
 objcopy	= $(CONFIG.TOOLCHAIN)-objcopy
 
 
+
+
 #---
 #  Version management
 #---
 # TODO
 
 
+
+
 #---
 # Build rules
 #---
-all: $(target)
+# (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
 
-# linker part
-$(target): $(obj) | $(dir_bin)
-	$(ar) crs $@ $^
-
-# Directory management
-$(dir_bin) $(dir_objects):
-	@ printf "Create $(blue)$@$(nocolor) directory\n"
+# Create directory helper
+# @note: Just use "$*" and "$@" to refer to the directory being created.
+%/:
+	@ printf "Create $(blue)$*$(nocolor) directory\n"
 	@ mkdir -p $@
+.PRECIOUS: %/
 
-.PHONY: all
 
 
 #---
 # Automated rules
 #---
-define rule-src
-$(patsubst .._src_%,$(dir_objects)/%.o,$(subst /,_,$(basename $1))): $1 | $(dir_objects)
-	@ printf "compiling $(white)$$<$(nocolor)..."
+# 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
 
-$(foreach source,$(src),$(eval		\
-	$(call rule-src,$(source)))	\
+# 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)) \
+	)) \
 )
 
 
+
 #---
-# Debugging rules
+# Build rule
 #---
-help:
-	@ echo 'make [options]...'
-	@ echo ''
-	@ echo 'Options:'
-	@ 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)'
+all: $(generated-libs)
 
-disasm:
-	@ $(objdump) -D $(target) | less
-
-elf_sec:
-	@ $(objdump) -h $(target) | less
-
-.PHONY: help __debug disasm elf_sec
+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)"
 
 
 #---
@@ -159,10 +206,98 @@ elf_sec:
 #---
 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