vxKernel/Makefile

372 lines
9.1 KiB
Makefile

#!/usr/bin/make -f
# ---
# Project: vxKernek - Vhex project kernel
# Author: yann.magnin@protonmail.com
#
# TODO:
# <> proper clean rule
# ---
#---
# environment check
#---
ifeq ($(VXSDK_PREFIX_BUILD),)
$(error "The vxKernel sould be build using the vxSDK")
endif
#---
# Build rules
#---
# Make selects the first rule set when you type "make" but, in our case, we are
# going to generate most of the rules. So, we set a placeholder to force the
# "all" rule to be the "first" rule
first: all
# display the library version
version:
@echo "$(VXSDK_PKG_VERSION)"
# Display helper
help:
@ echo 'Rules listing:'
@ echo '... all the default, if no target is provided'
@ echo '... clean remove build object'
@ echo '... fclean remove all generated object'
@ echo '... re same as `make fclean all`'
@ echo '... version display version'
@ echo '... install install the library'
@ echo '... uninstall uninstall the library'
.PHONY: help version first
#---
# Check build validity
#---
CONFIG := $(VXSDK_PREFIX_BUILD)/kernel.cfg
ifeq "$(wildcard $(CONFIG))" ""
$(error "config file $(CONFIG) does not exist (you should use `../configure`")
endif
include $(CONFIG)
#---
# Variables definition
#---
# Many variables will be provided by the "kernel.cfg" file (generated during
# the configuration part). It will defines:
# <> BOARD - indicate the target board list
# <> {BOARD}-SRC-MODULE-PATH - list of all sources path for a specific board
# <> {BOARD}-TOOLCHAIN-PREFIX - toolchain prefix for a board (sh-elf, ...)
# <> FORMAT - format for the kernel (static, dynamic)
# color definition, for swagg :D
red := \033[1;31m
green := \033[1;32m
blue := \033[1;34m
white := \033[1;37m
nocolor := \033[1;0m
#---
# Rules definition
#
# The objectif is to generate a building this build tree:
#
# <VXSDK_BUILD_PREFIX>/:
# |-- kernel.cfg
# |-- <board_name>/:
# | |-- <format>/:
# | | |-- obj/:
# | | | |-- main.o
# ...
# | | | `-- initialize.o
# | | `-- map
# | |-- <board_name>.ld
# | `-- libvxkernel-<format>.[so/a]
# `-- Makefile
#---
# Function that will generate a rule for one object file
# @param
# *1 - GCC name (with specific prefix if needed)
# *2 - CFLAGS list
# *3 - source file path
# *4 - build root directory path
# *5 - object file compilation rule list
# *6 - dependencies file compilation rule list
# *7 - unique id (used to generate unique variable name (workaround))
define generate-compile-file-rule
# generate the object file path
# @note
# <> This is alse the generated rule name
# <> step:
# 1) ../board/path/file.c -> ../board/path/file
# 2) .._board_path_file -> board_path_file
# 3) board_path_file.o -> {build path}/board_path_file.o
tname := $(strip $7)
obj-$(tname)-name := $$(basename $3)
obj-$(tname)-name := $$(subst /,_,$$(obj-$(tname)-name))
obj-$(tname)-name := $$(patsubst %,$4/%.o,$$(obj-$(tname)-name))
# generate the building rule
$$(obj-$(tname)-name): $3
@ mkdir -p $$(dir $$@)
ifeq ($(CONFIG.VERBOSE),false)
@ printf "$(green)>$(nocolor) $(white)$$@$(nocolor)\n"
@ $1 $2 -o $$@ -c $$< -MMD -MT $$@ -MF $$@.d -MP
else
$1 $2 -o $$@ -c $$< -MMD -MT $$@ -MF $$@.d -MP
endif
# register the build rules and dependencies file name
$5 += $$(obj-$(tname)-name)
$6 += $$(obj-$(tname)-name).d
endef
# Function that will generate all rules for a specific board and format
# @params
# *1 - board name
# *2 - format name (static or dynamic)
# *3 - rules list variable name
define generate-target-lib
# generate common information
# @note:
# Because we generate rule "on-the-fly" we need to create unique variable
# definition because make is not a "scoped" language. (therefore, when a
# variable is created, it will never be destroyed until the end of the script)
t-$1-$2-build := $(VXSDK_PREFIX_BUILD)/$1/$2
# generate compilation flags
t-$1-$2-ar := $$(CONFIG.$1.TOOLCHAIN.PREFIX)ar
t-$1-$2-ld := $$(CONFIG.$1.TOOLCHAIN.PREFIX)ld
t-$1-$2-gcc := $$(CONFIG.$1.TOOLCHAIN.PREFIX)gcc
t-$1-$2-ldflags := $$(CONFIG.$1.TOOLCHAIN.LDFLAGS)
t-$1-$2-cflags := $$(CONFIG.$1.TOOLCHAIN.CFLAGS)
# generate compiler information (used to find some library like libgcc.a)
t-$1-$2-gcc-base := $$(shell $$(CONFIG.$1.TOOLCHAIN.PREFIX)gcc --print-search-dirs | grep install | sed 's/install: //')
t-$1-$2-gcc-header := -I$$(t-$1-$2-gcc-base)/include -I$$(t-$1-$2-gcc-base)/include/openlibm
t-$1-$2-cflags += -Iinclude -I. -Isrc $$(t-$1-$2-gcc-header)
t-$1-$2-cflags += -Llib -L. -L$$(t-$1-$2-gcc-base)
# generate file's sources list, based on the configuration step
t-$1-$2-src := $$(foreach path,$$(CONFIG.$1.SRC-MODULE-PATH),\
$$(wildcard $$(path)/*.c) \
$$(wildcard $$(path)/*.S) \
$$(wildcard $$(path)/*.s))
# generate format-specific flags
t-$1-$2-exec :=
ifeq ($2,static)
t-$1-$2-exec := $(VXSDK_PREFIX_BUILD)/libvhex-$1.a
endif
ifeq ($2,dynamic)
t-$1-$2-ldflags += -shared
t-$1-$2-ldflags += -soname=libvhex-$1-$(VXSDK_PKG_VERSION).so
t-$1-$2-ldflags += -Map=$$(t-$1-$2-build)/map
t-$1-$2-exec := $(VXSDK_PREFIX_BUILD)/libvhex-$1.so
t-$1-$2-src := $(wildcard fake/*.c)
endif
# generate file's compilation rules and all object filename into an object
# list variable, this will be used by the `main` rule
t-$1-$2-obj :=
t-$1-$2-dep :=
$$(foreach source,$$(t-$1-$2-src),$$(eval \
$$(call generate-compile-file-rule,\
$$(t-$1-$2-gcc),\
$$(t-$1-$2-cflags),\
$$(source),\
$$(t-$1-$2-build),\
t-$1-$2-obj,\
t-$1-$2-dep,\
$1-$2\
))\
)
# asset generation
t-$1-$2-asset := $(patsubst \
$(VXSDK_ASSETS_SRC)/%,\
$(VXSDK_ASSETS_BUILD)/$1/$2/%.o,\
$(wildcard $(VXSDK_ASSETS_SRC)/*.c) \
)
$(VXSDK_ASSETS_BUILD)/$1/$2/%.o: $(VXSDK_ASSETS_SRC)/%
ifeq ($(CONFIG.VERBOSE),true)
@ mkdir -p $$(dir $$@)
$$(CONFIG.$1.TOOLCHAIN.PREFIX)gcc $$(t-$1-$2-cflags) -o $$@ -c $$<
else
@ mkdir -p $$(dir $$@)
@ printf "$(green)>$(nocolor) $(white)$@$(nocolor)\n"
@ $$(CONFIG.$1.TOOLCHAIN.PREFIX)gcc $$(t-$1-$2-cflags) -o $$@ -c $$<
endif
# generate the "main" rule for this lib
$$(t-$1-$2-exec): $$(t-$1-$2-obj) $$(t-$1-$2-asset)
@ mkdir -p $$(dir $$@)
@ echo "dep : $$(t-$1-$2-dep)"
@ printf "$(blue)Create the library $(red)$$@$(nocolor)\n"
ifeq ($2,dynamic)
$$(t-$1-$2-gcc) -shared $$(t-$1-$2-cflags) $$(t-$1-$2-gcc-libs) -o $$@ $$^
else
$$(t-$1-$2-ar) crs $$@ $$^
endif
# register the "main" building rule for the lib
$3 += $$(t-$1-$2-exec)
# import dependencies rules
-include $$(t-$1-$2-dep)
$$(t-$1-$2-dep): ;
.PRECIOUS: $$(t-$1-$2-dep)
endef
# Generate the "main" rules list
target-lib-list :=
$(foreach board,$(CONFIG.BOARD-LIST),\
$(foreach format,$(CONFIG.FORMAT-LIST),$(eval\
$(call generate-target-lib,$(board),$(format),target-lib-list)\
))\
)
#---
# Build rules
#---
all: $(target-lib-list)
.PHONY: all
#---
# Generate installation rules
#---
# Common rules generated for the installation of each libraries.
# Basically, it will generate <libname>-install and <libname>-uninstall rules
# @note:
# *1 - library pathname
# *2 - variable name (installation rules list)
# *3 - variable name (uninstallation rules list)
define generate-install-rule
# Generate the installation rule
$(basename $(notdir $1))-install:
install -d $(VXSDK_PREFIX_LIB)
install $1 -m 644 $(VXSDK_PREFIX_LIB)
# Generate the uninstallation rule
$(basename $(notdir $1))-uninstall:
rm -f $(VXSDK_PREFIX_LIB)/$(notdir $1)
# Register generated rules into their appropriate list
$2 += $(basename $(notdir $1))-install
$3 += $(basename $(notdir $1))-uninstall
endef
# Common rules generated for the installation of board-specific linker script
# @note:
# $1 - board name
# $2 - variable name (installation rules list)
# $3 - variable name (uninstallation rules list)
define generate-board-install-rule
$1-install:
install -d $(VXSDK_PREFIX_LIB)
install board/$(strip $1)/*.ld -m 644 $(VXSDK_PREFIX_LIB)
$1-uninstall:
rm -f $(VXSDK_PREFIX_LIB)/$(strip $1).ld
rm -f $(VXSDK_PREFIX_LIB)/$(strip $1)-dynamic.ld
$2 += $1-install
$3 += $1-uninstall
endef
# Generate all installation/uninstallation rules
target-install-rules :=
target-uninstall-rules :=
$(foreach target,$(target-lib-list),$(eval \
$(call generate-install-rule, \
$(target), \
target-install-rules, \
target-uninstall-rules \
) \
))
$(foreach board,$(CONFIG.BOARD-LIST),$(eval \
$(call generate-board-install-rule, \
$(board), \
target-install-rules, \
target-uninstall-rules \
) \
))
# Generate the path where include directory will be installed.
target-install-hdr-dir := $(VXSDK_PREFIX_LIB)/include/
ifeq ($(wildcard $(target-install-header-dir)vhex/.*),)
target-install-hdr-dir := $(target-install-hdr-dir)vhex
endif
#---
# Installation rules
#---
install: $(target-install-rules)
mkdir -p $(dir $(target-install-hdr-dir))
cp -r include/vhex $(target-install-hdr-dir)
unsintall: $(target-uninstall_rules)
rm -rf $(VXSDK_PREFIX_LIB)/include/vhex
.PHONY: install uninstall
#---
# cleaning rules
#---
#clean: TODO: generate clean rule list
fclean: clean
rm -rf $(target-lib-list)
re: fclean all
.PHONY: clean fclean re all