]> cloudbase.mooo.com Git - z180-stamp.git/commitdiff
Add non-recursive make system from Andrzej Ostruszka.
authorLeo C <erbl259-lmu@yahoo.de>
Sun, 13 Apr 2014 13:29:22 +0000 (15:29 +0200)
committerLeo C <erbl259-lmu@yahoo.de>
Sun, 13 Apr 2014 13:29:22 +0000 (15:29 +0200)
Copyright (C) 2012 Andrzej Ostruszka <andrzej.ostruszka@gmail.com>
URL: http://github.com/aostruszka/nonrec-make

24 files changed:
.gitignore [new file with mode: 0644]
Makefile [new symlink]
Rules.top [new file with mode: 0644]
libopencm3.rules.mk [deleted file]
libopencm3.target.mk [deleted file]
mk/Makefile [new file with mode: 0644]
mk/Readme.txt [new file with mode: 0644]
mk/build-debug.mk [new file with mode: 0644]
mk/build-profile.mk [new file with mode: 0644]
mk/build-release.mk [new file with mode: 0644]
mk/config-Cygwin-i686_Cygwin-i686.mk [new file with mode: 0644]
mk/config-Cygwin-i686_Linux-ppc.mk [new file with mode: 0644]
mk/config-MinGW-i686_MinGW-i686.mk [new file with mode: 0644]
mk/config-SunOS-sun4u_SunOS-sun4u.mk [new file with mode: 0644]
mk/config-default.mk [new file with mode: 0644]
mk/config.mk [new file with mode: 0644]
mk/def_rules.mk [new file with mode: 0644]
mk/footer.mk [new file with mode: 0644]
mk/header.mk [new file with mode: 0644]
mk/skel.mk [new file with mode: 0644]
stm32/.gitignore [new file with mode: 0644]
stm32/Makefile [changed from file to symlink]
stm32/Rules.mk [new file with mode: 0644]
stm32/stm32vl-discovery.ld [moved from stm32vl-discovery.ld with 100% similarity]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..68760d7
--- /dev/null
@@ -0,0 +1,4 @@
+Makefiledev
+/.settings
+/.cproject
+/.project
diff --git a/Makefile b/Makefile
new file mode 120000 (symlink)
index 0000000..1c96c03
--- /dev/null
+++ b/Makefile
@@ -0,0 +1 @@
+mk/Makefile
\ No newline at end of file
diff --git a/Rules.top b/Rules.top
new file mode 100644 (file)
index 0000000..c475b19
--- /dev/null
+++ b/Rules.top
@@ -0,0 +1,16 @@
+
+SUBDIRS = stm32
+
+
+
+.PHONY : tar tar-%
+# To get ID from a tar archive just run:
+#   zcat nonrec-make.tgz | git get-tar-commit-id
+tar : tar-HEAD
+tar-% :
+       commit=$(subst tar-,,$@);\
+       tarname=z180-stamp-$$(git describe --tags $$commit).tgz;\
+       echo Archiving $$commit to $$tarname;\
+       git archive $$commit mk | gzip > $$tarname
+
+# vim: set ft=make :
diff --git a/libopencm3.rules.mk b/libopencm3.rules.mk
deleted file mode 100644 (file)
index 1896071..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-##
-## This file is part of the libopencm3 project.
-##
-## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
-## Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
-## Copyright (C) 2013 Frantisek Burian <BuFran@seznam.cz>
-##
-## This library is free software: you can redistribute it and/or modify
-## it under the terms of the GNU Lesser General Public License as published by
-## the Free Software Foundation, either version 3 of the License, or
-## (at your option) any later version.
-##
-## This library is distributed in the hope that it will be useful,
-## but WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-## GNU Lesser General Public License for more details.
-##
-## You should have received a copy of the GNU Lesser General Public License
-## along with this library.  If not, see <http://www.gnu.org/licenses/>.
-##
-
-# Be silent per default, but 'make V=1' will show all compiler calls.
-ifneq ($(V),1)
-Q              := @
-NULL           := 2>/dev/null
-endif
-
-###############################################################################
-# Executables
-
-PREFIX         ?= arm-none-eabi
-
-CC             := $(PREFIX)-gcc
-CXX            := $(PREFIX)-g++
-LD             := $(PREFIX)-gcc
-AR             := $(PREFIX)-ar
-AS             := $(PREFIX)-as
-OBJCOPY                := $(PREFIX)-objcopy
-OBJDUMP                := $(PREFIX)-objdump
-GDB            := $(PREFIX)-gdb
-STFLASH                = $(shell which st-flash)
-STYLECHECK     := /checkpatch.pl
-STYLECHECKFLAGS        := --no-tree -f --terse --mailback
-STYLECHECKFILES        := $(shell find . -name '*.[ch]')
-
-
-###############################################################################
-# Source files
-
-LDSCRIPT       ?= $(BINARY).ld
-
-OBJS           += $(BINARY).o
-
-
-ifeq ($(strip $(OPENCM3_DIR)),)
-# user has not specified the library path, so we try to detect it
-
-# where we search for the library
-LIBPATHS := ./libopencm3 ../../../../libopencm3 ../../../../../libopencm3
-
-OPENCM3_DIR := $(wildcard $(LIBPATHS:=/locm3.sublime-project))
-OPENCM3_DIR := $(firstword $(dir $(OPENCM3_DIR)))
-
-ifeq ($(strip $(OPENCM3_DIR)),)
-$(warning Cannot find libopencm3 library in the standard search paths.)
-$(error Please specify it through OPENCM3_DIR variable!)
-endif
-endif
-
-ifeq ($(V),1)
-$(info Using $(OPENCM3_DIR) path to library)
-endif
-
-INCLUDE_DIR    = $(OPENCM3_DIR)/include
-LIB_DIR                = $(OPENCM3_DIR)/lib
-SCRIPT_DIR     = $(OPENCM3_DIR)/scripts
-
-###############################################################################
-# C flags
-
-CFLAGS         += -Os -g
-CFLAGS         += -Wextra -Wshadow -Wimplicit-function-declaration
-CFLAGS         += -Wredundant-decls -Wstrict-prototypes
-CFLAGS         += -fno-common -ffunction-sections -fdata-sections
-CFLAGS         += -std=c99
-
-###############################################################################
-# C++ flags
-
-CXXFLAGS       += -Os -g
-CXXFLAGS       += -Wextra -Wshadow -Wredundant-decls  -Weffc++
-CXXFLAGS       += -fno-common -ffunction-sections -fdata-sections
-
-###############################################################################
-# C & C++ preprocessor common flags
-
-CPPFLAGS       += -MD
-CPPFLAGS       += -Wall -Wundef
-CPPFLAGS       += -I$(INCLUDE_DIR) $(DEFS)
-
-###############################################################################
-# Linker flags
-
-LDFLAGS                += --static -nostartfiles
-LDFLAGS                += -L$(LIB_DIR)
-LDFLAGS                += -T$(LDSCRIPT)
-LDFLAGS                += -Wl,-Map=$(*).map
-LDFLAGS                += -Wl,--gc-sections
-ifeq ($(V),1)
-LDFLAGS                += -Wl,--print-gc-sections
-endif
-
-###############################################################################
-# Used libraries
-
-LDLIBS         += -l$(LIBNAME)
-LDLIBS         += -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group
-
-###############################################################################
-###############################################################################
-###############################################################################
-
-.SUFFIXES: .elf .bin .hex .srec .list .map .images
-.SECONDEXPANSION:
-.SECONDARY:
-
-all: elf
-
-elf: $(BINARY).elf
-bin: $(BINARY).bin
-hex: $(BINARY).hex
-srec: $(BINARY).srec
-list: $(BINARY).list
-
-images: $(BINARY).images
-flash: $(BINARY).flash
-
-%.images: %.bin %.hex %.srec %.list %.map
-       @#printf "*** $* images generated ***\n"
-
-%.bin: %.elf
-       @#printf "  OBJCOPY $(*).bin\n"
-       $(Q)$(OBJCOPY) -Obinary $(*).elf $(*).bin
-
-%.hex: %.elf
-       @#printf "  OBJCOPY $(*).hex\n"
-       $(Q)$(OBJCOPY) -Oihex $(*).elf $(*).hex
-
-%.srec: %.elf
-       @#printf "  OBJCOPY $(*).srec\n"
-       $(Q)$(OBJCOPY) -Osrec $(*).elf $(*).srec
-
-%.list: %.elf
-       @#printf "  OBJDUMP $(*).list\n"
-       $(Q)$(OBJDUMP) -S $(*).elf > $(*).list
-
-%.elf: $(OBJS) $(LDSCRIPT) $(LIB_DIR)/lib$(LIBNAME).a
-       @#printf "  LD      $(*).elf\n"
-       $(Q)$(LD) $(LDFLAGS) $(ARCH_FLAGS) $(OBJS) $(LDLIBS) -o $(*).elf
-
-%.o: %.c
-       @#printf "  CC      $(*).c\n"
-       $(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -o $(*).o -c $(*).c
-
-%.o: %.cxx
-       @#printf "  CXX     $(*).cxx\n"
-       $(Q)$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -o $(*).o -c $(*).cxx
-
-%.o: %.cpp
-       @#printf "  CXX     $(*).cpp\n"
-       $(Q)$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -o $(*).o -c $(*).cpp
-
-clean:
-       @#printf "  CLEAN\n"
-       $(Q)$(RM) *.o *.d *.elf *.bin *.hex *.srec *.list *.map
-
-stylecheck: $(STYLECHECKFILES:=.stylecheck)
-styleclean: $(STYLECHECKFILES:=.styleclean)
-
-# the cat is due to multithreaded nature - we like to have consistent chunks of text on the output
-%.stylecheck: %
-       $(Q)$(SCRIPT_DIR)$(STYLECHECK) $(STYLECHECKFLAGS) $* > $*.stylecheck; \
-               if [ -s $*.stylecheck ]; then \
-                       cat $*.stylecheck; \
-               else \
-                       rm -f $*.stylecheck; \
-               fi;
-
-%.styleclean:
-       $(Q)rm -f $*.stylecheck;
-
-
-%.stlink-flash: %.bin
-       @printf "  FLASH  $<\n"
-       $(Q)$(STFLASH) write $(*).bin 0x8000000
-
-ifeq ($(STLINK_PORT),)
-ifeq ($(BMP_PORT),)
-ifeq ($(OOCD_SERIAL),)
-%.flash: %.hex
-       @printf "  FLASH   $<\n"
-       @# IMPORTANT: Don't use "resume", only "reset" will work correctly!
-       $(Q)$(OOCD) -f interface/$(OOCD_INTERFACE).cfg \
-                   -f board/$(OOCD_BOARD).cfg \
-                   -c "init" -c "reset init" \
-                   -c "flash write_image erase $(*).hex" \
-                   -c "reset" \
-                   -c "shutdown" $(NULL)
-else
-%.flash: %.hex
-       @printf "  FLASH   $<\n"
-       @# IMPORTANT: Don't use "resume", only "reset" will work correctly!
-       $(Q)$(OOCD) -f interface/$(OOCD_INTERFACE).cfg \
-                   -f board/$(OOCD_BOARD).cfg \
-                   -c "ft2232_serial $(OOCD_SERIAL)" \
-                   -c "init" -c "reset init" \
-                   -c "flash write_image erase $(*).hex" \
-                   -c "reset" \
-                   -c "shutdown" $(NULL)
-endif
-else
-%.flash: %.elf
-       @printf "  GDB   $(*).elf (flash)\n"
-       $(Q)$(GDB) --batch \
-                  -ex 'target extended-remote $(BMP_PORT)' \
-                  -x $(SCRIPT_DIR)/black_magic_probe_flash.scr \
-                  $(*).elf
-endif
-else
-%.flash: %.elf
-       @printf "  GDB   $(*).elf (flash)\n"
-       $(Q)$(GDB) --batch \
-                  -ex 'target extended-remote $(STLINK_PORT)' \
-                  -x $(SCRIPT_DIR)/stlink_flash.scr \
-                  $(*).elf
-endif
-
-.PHONY: images clean stylecheck styleclean elf bin hex srec list
-
--include $(OBJS:.o=.d)
diff --git a/libopencm3.target.mk b/libopencm3.target.mk
deleted file mode 100644 (file)
index a381abb..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-##
-## This file is part of the libopencm3 project.
-##
-## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
-## Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
-##
-## This library is free software: you can redistribute it and/or modify
-## it under the terms of the GNU Lesser General Public License as published by
-## the Free Software Foundation, either version 3 of the License, or
-## (at your option) any later version.
-##
-## This library is distributed in the hope that it will be useful,
-## but WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-## GNU Lesser General Public License for more details.
-##
-## You should have received a copy of the GNU Lesser General Public License
-## along with this library.  If not, see <http://www.gnu.org/licenses/>.
-##
-
-LIBNAME                = opencm3_stm32f1
-DEFS           = -DSTM32F1
-
-FP_FLAGS       ?= -msoft-float
-ARCH_FLAGS     = -mthumb -mcpu=cortex-m3 $(FP_FLAGS) -mfix-cortex-m3-ldrd
-
-################################################################################
-# OpenOCD specific variables
-
-OOCD           ?= openocd
-OOCD_INTERFACE ?= stlink-v1
-OOCD_BOARD     ?= stm32vldiscovery
-
-################################################################################
-# Black Magic Probe specific variables
-# Set the BMP_PORT to a serial port and then BMP is used for flashing
-BMP_PORT       ?=
-
-################################################################################
-# texane/stlink specific variables
-#STLINK_PORT   ?= :4242
-
-
-include ../libopencm3.rules.mk
-
diff --git a/mk/Makefile b/mk/Makefile
new file mode 100644 (file)
index 0000000..7658b42
--- /dev/null
@@ -0,0 +1,52 @@
+SHELL := /bin/bash
+RUNDIR := $(CURDIR)
+ifndef TOP
+TOP := $(shell \
+       top=$(RUNDIR); \
+       while [ ! -r "$$top/Rules.top" ] && [ "$$top" != "" ]; do \
+           top=$${top%/*}; \
+       done; \
+       echo $$top)
+endif
+
+MK := $(TOP)/mk
+
+.PHONY: dir tree all clean clean_all clean_tree dist_clean
+
+# Default target when nothing is given on the command line.  Reasonable
+# options are:
+# "dir"  - updates only targets from current directory and its dependencies
+# "tree" - updates targets (and their dependencies) in whole subtree
+#          starting at current directory
+# "all"  - updates all targets in the project
+.DEFAULT_GOAL := dir
+
+dir : dir_$(RUNDIR)
+tree : tree_$(RUNDIR)
+
+clean : clean_$(RUNDIR)
+clean_tree : clean_tree_$(RUNDIR)
+
+# $(d) keeps the path of "current" directory during tree traversal and
+# $(dir_stack) is used for backtracking during traversal
+d := $(TOP)
+dir_stack :=
+
+include $(MK)/header.mk
+include $(MK)/footer.mk
+
+# Automatic inclusion of the skel.mk at the top level - that way
+# Rules.top has exactly the same structure as other Rules.mk
+include $(MK)/skel.mk
+
+.SECONDEXPANSION:
+$(eval $(value HEADER))
+include $(TOP)/Rules.top
+$(eval $(value FOOTER))
+
+# Optional final makefile where you can specify additional targets
+-include $(TOP)/final.mk
+
+# This is just a convenience - to let you know when make has stopped
+# interpreting make files and started their execution.
+$(info Rules generated $(if $(BUILD_MODE),for "$(BUILD_MODE)" mode,)...)
diff --git a/mk/Readme.txt b/mk/Readme.txt
new file mode 100644 (file)
index 0000000..c341b48
--- /dev/null
@@ -0,0 +1,469 @@
+################################################################################
+#                  Non-recursive make build system                             #
+#                  -------------------------------                             #
+#     Copyright (C) 2012 Andrzej Ostruszka <andrzej.ostruszka@gmail.com>       #
+#                                                                              #
+#          URL: http://github.com/aostruszka/nonrec-make                       #
+#          (or older: http://nonrec-make.googlecode.com/)                      #
+#                                                                              #
+# Permission is hereby granted, free of charge, to any person obtaining a copy #
+# of this software and associated documentation files (the "Software"), to     #
+# deal in the Software without restriction, including without limitation the   #
+# rights to use, copy, modify, merge, publish, distribute, sublicense,         #
+# and/or sell copies of the Software, and to permit persons to whom the        #
+# Software is furnished to do so, subject to the following conditions:         #
+#                                                                              #
+# The above copyright notice and this permission notice shall be included in   #
+# all copies or substantial portions of the Software.                          #
+#                                                                              #
+# Except as contained in this notice, the name(s) of the above copyright       #
+# holders shall not be used in advertising or otherwise to promote the sale,   #
+# use or other dealings in this Software without prior written authorization.  #
+#                                                                              #
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR   #
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,     #
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  #
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER       #
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      #
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS #
+# IN THE SOFTWARE.                                                             #
+################################################################################
+
+NOTE: This readme _might_ not be up to date.  For up to date information
+see the above URL (and accompanying wiki pages).
+
+This is my attempt to implement a non-recursive make build system.  For
+the motivation Google for the paper "Recursive make consider harmful" by
+Peter Miller.
+
+I've seen couple of other proposals and decided to have something that
+will be a blend of nice ideas I have seen plus some improvements.  If
+you actually use this I'd like to hear from you :) - is it useful, does
+it perform well, do you have any suggestions for the improvements ...
+and so on.  This implementation is based on GNU make and its new
+features introduced in 3.80.  But don't use that version - these
+features had bugs in that version.  Use version 3.81 where everything
+works OK.
+
+Before you keep on reading though, just take a look at the structure of
+the Rules.mk files (Rules.top has exactly the same structure as Rules.mk
+- it just has another name to ease location of the top level project
+directory from its subfolders).
+I've got a feeling that it is much easier to understand how the system
+looks from the user perspective just by looking at the example than
+reading its explanation :D.
+
+OK, now that you have a feeling how the Rules.mk look like let me walk
+you through an example (ex1 in the repository).  Consider the project
+that has some source files at the top directory and is depending on two
+libraries in Dir_1 and Dir_2 and another one in Dir_3.  The libraries
+themselves are partitioned between several subdirectories and Dir_2 has
+some examples in a separate subfolder (do not pay attention to all *.c
+files).
+
+ex1/
+  Makefile
+  Rules.top <- Just a symlink to Rules.mk to mark where the top level is
+  Rules.mk
+  main.c
+  top_a.c
+  top_b.c
+  cli.c
+  cli_dep.c
+  mk/* <- This is where the mk files from this build system are
+  Dir_1/
+    Makefile
+    Rules.mk
+    dir_1_file1.c
+    dir_1_file2.c
+    dir_1_file3.c
+    Dir_1a/
+      Makefile
+      Rules.mk
+      dir_1a_file1.c
+      dir_1a_file2.c
+      dir_1a_file3.c
+    Dir_1b/
+      Makefile
+      Rules.mk
+      src/
+        dir_1b_file1.c
+        dir_1b_file2.c
+  Dir_2/
+    Makefile
+    Rules.mk
+    dir_2_file1.c
+    dir_2_file2.c
+    Dir_2a/
+      Makefile
+      Rules.mk
+      dir_2a_file1.c
+      dir_2a_file2.c
+      dir_2a_file3.c
+    Dir_2b/
+      Makefile
+      Rules.mk
+      dir_2b_file1.c
+      dir_2b_file2.c
+      dir_2b_file3.c
+    Dir_ex/
+      Makefile
+      Rules.mk
+      ex.c
+  Dir_3/
+    Makefile
+    Rules.mk
+    dir_3_file1.c
+    dir_3_file2.c
+
+There's one top level make file (Rules.top) which eventually includes
+all the makefiles.  In addition in each directory there is Makefile
+(which can be a link to the one in the top level directory) which
+searches for the Rules.top includes it with the default goal
+changed to rebuild only targets for the current directory.  This allows
+you to run make from each subdirectory and update only part of the
+targets (in contrary to other implementation which usually require
+you to run it at the top level and make full build each time).
+
+This build system was designed to have very simple structure of the
+"user makefiles".  The user just has to set the Rules.mk files in each
+directory and some general configuration options.  All the "magic" is
+hidden in header.mk, footer.mk and skel.mk which don't have to be
+modified [1].
+
+The structure of the Rules.mk is following (this is from top level
+Rules.top which has the same format as Rules.mk - and in fact it is
+suggested that it should be a symlink to normal Rules.mk file since it
+will allow for this project to act as a subproject of some super project
+treating your whole project tree as a subdirectory[2]):
+
+-8<---Rules.top---------------
+1:  TARGETS = app.exe cli.exe
+2:  SUBDIRS = Dir_1 Dir_2
+3:
+4:  app.exe_DEPS = top_a.o top_b.o main.o $(SUBDIRS_TGTS)
+5:  app.exe_LIBS = -lm
+6:  # Let's use DEFAULT_MAKECMD for app.exe
+7:
+8:  cli.exe_DEPS = cli.o cli_dep.o
+9:  cli.exe_CMD = $(LINK.c) $^ $(LDLIBS) -o $@
+-8<---------------------------
+
+Line 1 - this directory has two targets that should be built.
+Line 2 - this directory has two subdirectories that should be scanned
+Line 4 - app.exe depends on ... (SUBDIRS_TGTS is a variable that
+        contains all the targets from the subdirectories mentioned at
+        line 4)
+Line 5 - app.exe should be linked with math library
+Line 6 - app.exe will be built with default "rule"
+Line 8 - cli.exe depends on ... and
+Line 9 - use the following command to build it
+
+You can specify the targets for current directory in two ways:
+1. Give them in TARGETS.  Each target can have it's own *_DEPS, *_LIBS
+  and *_CMD which give the dependencies, additional libs needed and
+  a command to run which will update the target.  They are explained
+  a bit below.
+2. The targets are simply objects - or in more general files that
+  match patterns in AUTO_TGTS, and have appropriate rules in 'skeleton'.
+  In that case you can list them in OBJS or SRCS like e.g. in Rules.mk
+  from Dir_1a
+
+-8<---Dir_2/Dir_2a/Rules.mk---
+1: SRCS := dir_2a_file1.c dir_2a_file2.c dir_2a_file3.c
+-8<---------------------------
+
+There are "reserved" variables that you should not modify.  Most notably:
+- $(d) is the directory of the current Rules.mk [see note 2]
+- $(TOP) is the top level directory of the project tree
+- $(MK) is the directory where the included *.mk makefiles are
+For the full list you have to take a look at the makefiles in mk
+directory (e.g. in the skel.mk there are macros 'include_subdir_rules',
+'save_vars', 'tgt_rule' and 'skeleton' which you should not change [1]).
+
+Going back to the Rules.mk.  Normally wildcards in variable assignments
+are not expanded in make but this make system detects wildcards in SRCS
+and expands them (both in directory of the Rules.mk and its SRCS_VPATH
+subdirectories - see below what SRCS_VPATH is used for).  Thus you can
+simply say in Rules.mk:
+
+SRCS := *.c
+
+If you have directory with large number of files where simple glob is
+what you want to use in SRCS but there are some files that you'd like to
+exclude just list them in SRCS_EXCLUDES :) - this is a list of makefile
+patterns e.g.
+
+SRCS_EXCLUDES := extra% test%
+
+Of course you can use the built in make wildcards but you should do that
+as follows:
+
+SRCS := $(notdir $(wildcard $(d)/*.c))
+
+Keep in mind that the directory where make is invoked is usually different
+from where given Rules.mk is located.
+
+When supplying the value for *_DEPS you can refer to the object from the
+same directory with no directory prefix.  To be specific all
+dependencies that are not absolute paths will be treated as ones from
+the $(OBJDIR) subdirectory of current directory (OBJDIR and OBJPATH are
+"discussed" below).  You can use SUBDIRS_TGTS variable which will list
+all targets in subdirectories.  You can also name them explicitly like
+$(TARGETS_$(d)/subdir) and so on - see e.g. the Rules.mk in Dir_2
+directory where Dir_ex is mentioned as a subdirectory but is excluded
+from the *_DEPS (this allows you to create folders that "inherit" all
+the setting from the project build system but are not meant to be a part
+of the project itself - like examples).  For instance:
+
+dir1_lib.a_DEPS = dir_1_file1.o dir_1_file2.o dir_1_file3.o $(SUBDIRS_TGTS)
+
+tells that dir1_lib.a (which will be created in Dir_1/$(OBJDIR)) depends
+on several object files from the same directory and the targets from all
+subdirectories.
+
+One last thing about the TARGETS/OBJS.  By default source files for the
+objects are searched in the directory where Rules.mk is, but if you want
+to have source files in a subdirectory (say 'src') you can do that via
+SRCS_VPATH variable (see skel.mk).  E.g.:
+
+SRCS_VPATH := src1 src2
+
+will cause make to first look at the directory where Rules.mk is present
+and then in its src1 and src2 subdirectories.
+
+*_LIBS are appended to the LDLIBS variable when updating the target.
+This variable is used by several make built in rules but if you create
+your own rule or MAKECMD.* (see next paragraph) you can refer to it (see
+the function 'save_vars').
+
+When *_CMD is not present and the target does not match any pattern in
+AUTO_TGTS then either MAKECMD.suff (where .suff is the suffix of the
+target) or DEFAULT_MAKECMD is used - take a look into skel.mk.
+
+If you want to setup special flags for compilation you can do that via
+"directory specific variables".  As an example here's what I did for
+compilation of C files.  There's a built in rule in make which uses
+COMPILE.c variable for making %.o out of %.c so I added $(DIR_CFLAGS) to
+its default value and DIR_CFLAGS is defined in skel.mk as:
+
+DIR_INCLUDES = $(addprefix -I,$(INCLUDES_$(<D)))
+DIR_CFLAGS = $(CFLAGS_$(<D)) $(DIR_INCLUDES)
+
+So it extracts the directory part of the first prerequisite in the rule
+(that is %.c file - check the section 'automatic variables' in make
+manual for the meaning of $(<) and $(<D)) and refer to variables named
+CFLAGS_the_directory_part and INCLUDES_the_directory_part.
+Thus if you wanted to add special includes for files in Dir_1/Dir_1b you
+could add:
+
+INCLUDES_$(d) := $(TOP)/some/special/include_dir
+
+into its Rules.mk and all files in this directory will be compiled with
+-I$(TOP)/some...  switch.  The same goes for CFLAGS and CXXFLAGS.
+
+The same goes for the linker flags - quoting from skel.mk:
+
+LDFLAGS = $(addprefix -L,$(LIBDIRS_$(subst /$(OBJDIR),,$(@D))))
+LDLIBS = $(LIBS_$(@))
+
+The above means that if targets in given directory need to be linked
+with special -L switches you can provide them via LIBDIRS_$(d)
+variables.  If there are some global -L switches just append them in
+skel.mk.  The second line above shows how *_LIBS variable that you can
+give for specific target gets added to the LDLIBS (there's 'save_vars'
+in between if you're curious :)).
+
+You can of course use target specific variables that GNU make supports
+so you have more control (if you don't know what target specific
+variables are take a look into manual).  Say you want to compile
+dir_1b_file2.c with an additional flag but all other files in
+Dir_1/Dir_1b directory should not have this flag turned on.  All you
+need to do is to add this line into Rules.mk in Dir_1b directory.
+
+$(OBJPATH)/dir_1b_file2.o : CFLAGS += -ansi
+
+OBJPATH is a variable that contains the full directory where the
+resulting object file will be placed.  While we are at this, by default
+all targets are compiled into OBJDIR (defined in skel.mk as 'obj')
+subdirectory of the directory where Rules.mk is present.  You can use
+this OBJDIR variable (and perhaps some conditional statements) to setup
+the output path according to your current compilation mode.  E.g.
+obj/debug for objects with debugging information or obj/ppc_7xx for
+cross compilation to the given Power PC family and so on.  There's
+predefined (in config* files) HOST_ARCH variable that you can use for
+this (e.g. set OBJDIR := obj/$(HOST_ARCH) in skel.mk).
+
+Finally let me explain what targets are defined and the way you can run
+them from command line.  By default (that is if you have not modified
+anything :)) there are several targets that are "global".  It is 'all',
+'clean_all' and 'dist_clean'.  If you specify them in the command line
+they will respectively rebuild whole tree, clean everything and clean
+everything together with the removal of OBJDIRs - no matter from which
+directory you started make.  BTW if there's something that you want to
+clean up and it's not in the OBJDIR - e.g. you've got file lexer.l out
+of which lexer.c and lexer.h is generated and you want them to be
+removed - you can specify this in the variable CLEAN (this is relative
+to the directory where Rules.mk is).
+In addition to those each dir has "it's own" targets.  These are:
+
+1) dir_<directory_path>
+   which builds all targets in given directory plus its dependencies
+2) tree_<directory_path>
+   which builds all targets in subtree starting at directory given
+3) clean_<directory_path>
+   which removes all "products" from the $(OBJDIR) subdirectory of
+   current directory
+4) clean_tree_<directory_path>
+   which does clean_<directory_path> and the same for each its
+   subdirectory
+
+For your convenience there are couple "aliases" defined (see Makefile).
+When no target is given on command line it defaults to dir_$(pwd).
+If you give 'clean' as a target that will result in execution of target
+clean_$(pwd) and the same for 'clean_tree'.  E.g. say you're in Dir_1.
+Then:
+
+* 'make' (same as 'make dir_$(pwd)')
+   builds all targets in the Dir_1 which in our example is
+   Dir_1/obj/dir1_lib.a - of course any of its dependencies that are not
+   up to date are updated also.  This rule has one exception - if your
+   Rules.mk has no targets and only SUBDIRS (e.g. you have grouped
+   several subdirectories in one directory) then simple 'make' in this
+   directory - instead of doing nothing - will build targets of all its
+   subdirectories.
+* 'make tree' (same as 'make tree_$(pwd)')
+   rebuilds everything in given subtree
+* 'make clean' (same as 'make clean_$(pwd)')
+   removes everything from Dir_1/obj/
+* 'make clean_tree (same as 'make clean_tree_$(pwd)')
+   cleans Dir_1/obj and Dir_1/Dir_1[abc]/obj
+
+You can obviously provide the path by yourself - it does not have to
+be $(pwd) - and as usual you can build particular object files too e.g.
+'make $(pwd)/obj/dir_1_file1.o'
+
+And that would be it.  Gee, so much writing for something that is rather
+simple to use - go ahead and take a look again at these Rules.mk in
+various directories.  Setting up you project should be simple by now :).
+
+Have fun!
+
+                                       Andrzej Ostruszka
+
+[1] Unless this build system does not do what you wanted :-P.  In that
+case you probably need to spiff it up.  So you'll need to
+digest it first and note [3] is my hand at it :).
+
+[2] There is one limitation that you should be aware.
+Prior to commit 070f681 you should not have in your project two "target
+specific" LIBS, LDFLAGS or CMD variables (that is those that are used
+during second phase of make execution) that have the same names!  For
+example in one part of your tree you're generating target abc which has
+it's abc_CMD and in the other part another target that has the same name
+and also it's own command.  In such case the last assignment to abc_CMD
+will hold and it will be used for both targets.  The same goes for LIBS
+and LDFLAGS.
+
+And this also applied to situation when you would like to use two
+subprojects in one larger project.  There should be no clash between
+variables from these subprojects.
+
+Starting with commit 070f681 you can have in your (sub)projects two
+LIBS, LDFLAGS or CMD variables.  However there is a catch here! Since
+these variables are not mandatory (you don't have to provide them for
+each target) in order to differentiate between case where abc_CMD was
+actually given for this instance of abc target from the situation where
+abc_CMD is still visible from previous instance of abc target those
+abc_(LIBS|LDFLAGS|CMD) variables are cleared once their value is
+used/remembered (see save_vars macro in skel.mk). That means referring
+to these variables outside Rules.mk where they were assigned will not
+work (and even in the same Rules.mk they will work only in case of
+simply expanded variables - not recursive). If you have such need I'd
+advice to introduce your own variable and use this variable in all
+places, e.g.:
+
+MATH_LIBS := -lgsl -lgslcblas -lm
+...
+TARGETS := abc
+
+abc_DEPS = ...
+abc_LIBS = $(MATH_LIBS)
+...
+
+[3] You should know that make works in two phases - first it scans the
+makefiles and then it begins their execution (see discussion of
+'immediate' and 'deferred' in section 'Reading Makefiles' of make
+manual).  This implies that the $(d) variable is not valid during
+execution of the commands used for target updates.  If you need to refer
+to the directory of the target or prerequisite you should rely on
+automatic variables (@, <, ...) and built in functions (dir, notdir,
+...).
+
+Every Rules.mk (or Rules.top) need to be included in cooperation with
+header.mk and footer.mk.  This is now done automatically but in older
+versions this was not so and user had to include them manually.
+The main purpose of header is to clear all variables that you can use
+inside Rules.mk so that values set in one rules file does not propagate
+to other.  In addition at the top level it sets the $(d) variable (which
+stands for the directory where the currently included Rules.mk is) and
+includes the skel.mk so the top level Rules.top can have exactly the
+same structure as other Rules.mk.
+
+The skel.mk is a skeleton which defines variables used by make.  In
+addition it includes:
+- config.mk - this is a file with the "configuration" for your project
+- def_rules.mk - where to put general rules (e.g. pattern rules).  E.g.
+  if you want to add a rule that builds %.o out of %.m4 (by running m4
+  preprocessor before passing the contents of file to CC) just put it in
+  here.
+
+skel.mk also defines some functions like save_vars and tgt_rule
+which are called in the footer.mk.  Take a look into make manual for the
+way the functions are defined and called if you're not familiar with it.
+
+include_subdir_rules: This is where I keep track of directory of
+       currently included makefile and include the Rules.mk from the
+       subdirectories.  This function is called in footer.mk in foreach
+       loop with a subdirectory name as an argument.
+
+save_vars: This one is very simple it just saves the target specific
+       variables under their "full path" variables.  E.g.
+       dir1_lib.a_DEPS will get saved as DEPS_$(TOP)/Dir_1/obj/dir1_lib.a
+       This has two purposes.  First it allows you to have targets with
+       the same names in different directories (not that I recommend
+       this :)) and allows for easier definition of tgt_rules :-P
+
+tgt_rule: This is where the rule for given target is created.  First
+       I convert all relative dependencies to the absolute ones then
+       I include all dependency files (by default they are created as
+       side effects during compilation - if your compiler does not
+       allow you to do that just make simple shell script that will do
+       this).  I also append appropriate libs and then issue the rule
+       for this target.  By using the short circuiting 'or' command
+       I give priority to the CMD over MAKECMD.suffix which itself has
+       priority over DEFAULT_MAKECMD.
+
+skeleton: This is just a skeleton for compilation of files in given
+       directory.  If you want to add some rule here then also add
+       appropriate pattern to the AUTO_TGTS that will filter out these
+       targets and prevent generation of the specific rules via
+       tgt_rule function.
+
+The footer.mk is where Rules.mk gets translated into the proper
+makefile.  There's not much to explain, just take a look in there.
+First I memorize the targets for given directory (either from OBJS/SRCS
+or from TARGETS) with appropriate directory prefix.  If there's need to
+save the target specific *_(CMD|DEP|LIB) I do it.  Then I include all
+the Rules.mk from the subdirectories.  Then I define the targets for
+given directory either explicitly (like clean_all or clean_$(d)) or by
+evaluation of the 'skeleton' mentioned above or by iterating through all
+targets which do not match AUTO_TGTS and evaluating what tgt_rule
+function for this target has returned.
+
+In case you want to play with these settings make sure you understand
+how make works, what are it's phases, when and how the variables are
+expanded and so on.  It will save you a lot of time :).
+
+Best regards
+Andrzej
diff --git a/mk/build-debug.mk b/mk/build-debug.mk
new file mode 100644 (file)
index 0000000..adcc04f
--- /dev/null
@@ -0,0 +1,4 @@
+CFLAGS   += -ggdb
+CXXFLAGS += -ggdb
+CPPFLAGS += -DDEBUG
+LDFLAGS  += -ggdb
diff --git a/mk/build-profile.mk b/mk/build-profile.mk
new file mode 100644 (file)
index 0000000..e7b14ac
--- /dev/null
@@ -0,0 +1,4 @@
+CFLAGS   += -ggdb -pg $(OPT_FLAGS)
+CXXFLAGS += -ggdb -pg $(OPT_FLAGS)
+CPPFLAGS += -DPROFILE
+LDFLAGS  += -ggdb -pg
diff --git a/mk/build-release.mk b/mk/build-release.mk
new file mode 100644 (file)
index 0000000..7869bbb
--- /dev/null
@@ -0,0 +1,4 @@
+CFLAGS   += $(OPT_FLAGS)
+CXXFLAGS += $(OPT_FLAGS)
+CPPFLAGS += -DRELEASE
+#LDFLAGS  +=
diff --git a/mk/config-Cygwin-i686_Cygwin-i686.mk b/mk/config-Cygwin-i686_Cygwin-i686.mk
new file mode 100644 (file)
index 0000000..ee7880f
--- /dev/null
@@ -0,0 +1,10 @@
+include $(MK)/config-default.mk
+
+CPPFLAGS += -DCYGWIN
+# There's no rt lib on Cygwin
+LDLIBS := $(subst -lrt,,$(LDLIBS))
+
+# On cygwin shared libraries have dll extension
+SOEXT := dll
+# and by default executables have .exe appended
+EXE := .exe
diff --git a/mk/config-Cygwin-i686_Linux-ppc.mk b/mk/config-Cygwin-i686_Linux-ppc.mk
new file mode 100644 (file)
index 0000000..6a7c865
--- /dev/null
@@ -0,0 +1,11 @@
+# How the "cross tools" should be invoked
+CC := powerpc-750-linux-gnu-gcc
+CXX := powerpc-750-linux-gnu-g++
+AR := powerpc-750-linux-gnu-ar
+RANLIB := powerpc-750-linux-gnu-ranlib
+
+# Since we are compiling for a "remote target" we have to set this manually
+ENDIAN := big
+
+# Any other target specific settings
+CPPFLAGS += -DLINUX_PPC
diff --git a/mk/config-MinGW-i686_MinGW-i686.mk b/mk/config-MinGW-i686_MinGW-i686.mk
new file mode 100644 (file)
index 0000000..fc097de
--- /dev/null
@@ -0,0 +1,8 @@
+include $(MK)/config-default.mk
+
+CPPFLAGS += -DMINGW
+
+# On mingw shared libraries have dll extension
+SOEXT := dll
+
+OPEN_GL_LIBS := -lopengl32 -lglu32
diff --git a/mk/config-SunOS-sun4u_SunOS-sun4u.mk b/mk/config-SunOS-sun4u_SunOS-sun4u.mk
new file mode 100644 (file)
index 0000000..57db3dc
--- /dev/null
@@ -0,0 +1,6 @@
+include $(MK)/config-default.mk
+
+# These two settings are the reason for a separate config
+CPPFLAGS += -DSPARC
+# On Sun the sockets are in a separate library
+#LDLIBS += -lsocket
diff --git a/mk/config-default.mk b/mk/config-default.mk
new file mode 100644 (file)
index 0000000..d8db456
--- /dev/null
@@ -0,0 +1,8 @@
+CC := gcc
+CXX := g++
+
+# AR is a make default but won't hurt spelling it out :)
+AR := ar
+RANLIB := ranlib
+
+OPEN_GL_LIBS := -lGL -lGLU
diff --git a/mk/config.mk b/mk/config.mk
new file mode 100644 (file)
index 0000000..baaf1f8
--- /dev/null
@@ -0,0 +1,44 @@
+# Fill BUILD_ARCH with appropriate value automatically (with some
+# cosmetics in case of Cygwin/MinGW :)).
+BUILD_ARCH := $(patsubst MINGW32_%,MinGW,$(patsubst CYGWIN_%,Cygwin,$(shell uname -s)))-$(shell uname -m)
+
+# Target platform (where the code will be executed).  I'm not using
+# TARGET_ARCH for this since this variable is already used in builtin
+# make rules and I want to be able to use those built in rules.  By
+# default we are running on the same machine we are building.
+HOST_ARCH := $(BUILD_ARCH)
+
+# Build mode e.g. debug, profile, release.  Build specific mode flags
+# can be entered in $(MK)/build-$(BUILD_MODE).mk file e.g. for debug
+# following seems to be a reasonable contents
+#CFLAGS   += -ggdb
+#CXXFLAGS += -ggdb
+#CPPFLAGS += -DDEBUG
+#LDFLAGS  += -ggdb
+# If you don't plan on having different build modes then just comment
+# below or set it to empty.
+#BUILD_MODE := $(or $(BUILD_MODE),debug)
+
+# To have some per directory setting automatically propagated to all
+# subdirs then uncomment below.  That way you can have all project
+# compiled with "global" settings and easily switch flags for some
+# subtree just by setting per directory settings at the top dir of the
+# subtree.  You may of course overwrite inherited values and you can
+# turn inheritance in some part by just clearing INHERIT_DIR_VARS_$(d)
+# This is a global inheritance flag - you might want to turn it on only
+# in some directory (just set INHERIT_DIR_VARS_$(d) there).
+#INHERIT_DIR_VARS := CPPFLAGS INCLUDES CFLAGS CXXFLAGS
+
+# Again, by default we are running on the same architecture we are
+# building - if you're cross compiling then you should set this manually
+ENDIAN := $(shell perl -le 'print unpack(N,pack(L,0x01020304)) == 0x01020304 ? big : little')
+
+# Make the compiler invocation lines verbose - if it is not defined or
+# set to value other then "true" you'll see just indication of what is
+# being compiled (without details about options)
+#VERBOSE := true
+
+# Uncomment if you don't like coloring of the output
+#COLOR_TTY := false
+
+# Any additional settings should go here
diff --git a/mk/def_rules.mk b/mk/def_rules.mk
new file mode 100644 (file)
index 0000000..9197b03
--- /dev/null
@@ -0,0 +1,123 @@
+# For now I depend on flex and bison - I want to generate source files
+# in the same directory as their lex/yacc inputs.
+%.c %.h : %.y
+       bison -d -o $*.c $<
+
+%.c : %.l
+       flex -o$@ $<
+
+# "Pretty printing" stuff
+#
+# The value of the variable VERBOSE decides whether to output only
+# a short note what is being done (e.g. "CC foobar.c") or a full
+# command line.
+#
+# Sometimes you have a code that you're not in charge of and which gives
+# a lot of warnings.  In that case you can use colors so that you find
+# easily what is being compiled.  By default I check terminal
+# capabilities and use colors only when the terminal support them but you
+# can suppress coloring by setting COLOR_TTY to something else than
+# 'true' (see config.mk).
+# Please don't argue about this choice of colors - I'm always using black
+# background so yellow on black it is :-D - background is specified
+# below just for those using bright background :-P
+COLOR := \033[33;40m
+NOCOLOR := \033[0m
+
+ifndef COLOR_TTY
+ifdef TERM
+COLOR_TTY := $(shell [ `tput colors` -gt 2 ] && echo true)
+endif
+endif
+
+ifneq ($(VERBOSE),true)
+ifneq ($(strip $(TOP_BUILD_DIR)),)
+  strip_top = $(subst $(TOP)/,,$(subst $(TOP_BUILD_DIR)/,,$(1)))
+else
+  strip_top = $(subst $(TOP)/,,$(1))
+endif
+ifeq ($(COLOR_TTY),true)
+echo_prog := $(shell if echo -e | grep -q -- -e; then echo echo; else echo echo -e; fi)
+echo_cmd = @$(echo_prog) "$(COLOR)$(call strip_top,$(1))$(NOCOLOR)";
+else
+echo_cmd = @echo "$(call strip_top,$(1))";
+endif
+else # Verbose output
+echo_cmd =
+endif
+
+COMPILE.c = $(call echo_cmd,CC $<) $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
+COMPILE.cc = $(call echo_cmd,CXX $<) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
+LINK.c = $(call echo_cmd,LINK $@) $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
+LINK.cc = $(call echo_cmd,LINK $@) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
+
+# This rule is just for running C/C++ preprocessor and saving the output
+# into the file with .E appended - sometimes this can be handy.
+# Suffix E comes from -E option to gcc.  Make sure you invoke this rule
+# via full path (e.g.: make $(pwd)/foobar.c.E) if you want to have per
+# directory preprocessor flags included.
+%.E : %
+       $(call echo_cmd,CPP $<) $(CPP) $(CPPFLAGS) -o $@ $<
+
+# Special rule to get easily CPP options for given file.  This can be
+# handy for your code "assistant" (e.g. clang) that needs to know
+# preprocessor options in order to parse file properly.  In that case
+# you can run: make /path/to/foobar.c.CPPFLAGS | tail -1
+# to get effective flags for foobar.c
+%.CPPFLAGS : %
+       @echo $(CPPFLAGS)
+
+# Create the output directory for build targets.
+%/$(OBJDIR):
+       @mkdir -p $@
+
+# Automatic rules.  Again, since the output is in different directory
+# than source files I cannot count on the built in make rules.  So
+# I keep them in a "macro" (see 'skeleton' below) that is expanded for
+# every directory with Rules.mk (and its SRCS_VPATH subdirectories).
+# Below setting means that %.o are made from %.cpp and the same for .cc
+# and .c - this is just the list of mappings.
+# You can add your own here.  For example to add support for Fortran you
+# would just append ".o:.f" and set COMPILE.f (actually make already
+# defines it - just take a look at output of "make -p")
+AUTO_RULES := .o:.cpp .o:.cc .o:.c
+# Additional mapping together with corresponding variables can be specified
+# in user_rules.mk
+-include $(MK)/user_rules.mk
+
+# This compile command should be generic for most compilers - you should
+# just define appropriate COMPILE.suffix variable.
+COMPILECMD = $(COMPILE$(suffix $<)) -o $@ $<
+
+# In cases where from one source different types of objects can be
+# generated I have added COMPILECMD_TD (TD stands for "target
+# dependent").  So e.g. for OCaml one could use:
+# CAML := ocamlc
+# CAMLOPT := ocamlopt
+# AUTO_TGTS += %.cmo %.cmx # or modify its value in skel.mk
+# COMPILE.cmo.ml = $(call echo_cmd,CAML $<) $(CAML) -c
+# COMPILE.cmx.ml = $(call echo_cmd,CAMLOPT $<) $(CAMLOPT) -c
+# AUTO_TD_RULES := .cmo&.cmx:.ml
+# The syntax for AUTO_TD_RULES is similar to AUTO_RULES but instead of
+# single output suffix (e.g. ".o") you have to list them all separated
+# by "&" (sorry, comma gives me problems since it is part of normal make
+# syntax for functions :P).  The above setting means that %.cmo and %.cmx
+# can be generated from %.ml via their respective COMPILE commands
+# expanded in COMPILECMD_TD (see below).
+
+# Again this should be generic enough so that you won't have to touch it
+COMPILECMD_TD = $(COMPILE$(suffix $@)$(suffix $<)) -o $@ $<
+
+# Definition of variable ${\n} containing just new-line character
+define \n
+
+
+endef
+
+# Definition of 'skeleton' macro used in generation of recipes.  This
+# definition is itself computed so you should not modify it (unless you
+# know what you are doing :D).  It should be enough for you to add new
+# mappings to AUTO_RULES and AUTO_TD_RULES above and define/change
+# corresponding COMPILE.suffix and COMPILE.outsuffix.insuffix variables.
+$(eval define skeleton$(foreach rule,$(AUTO_RULES),${\n}$$(OBJPATH)/%$(subst :,: $$(1)/%,$(rule)) | $$(OBJPATH); $$(value COMPILECMD))${\n}\
+                      $(foreach rule,$(AUTO_TD_RULES),${\n}$$(OBJPATH)/%$(subst :,: $$(1)/%,$(subst &, $$(OBJPATH)/%,$(rule))) | $$(OBJPATH); $$(value COMPILECMD_TD))${\n}endef)
diff --git a/mk/footer.mk b/mk/footer.mk
new file mode 100644 (file)
index 0000000..c6d19d3
--- /dev/null
@@ -0,0 +1,119 @@
+define FOOTER
+SUBDIRS_$(d) := $(patsubst %/,%,$(addprefix $(d)/,$(SUBDIRS)))
+
+ifneq ($(strip $(OBJS)),)
+OBJS_$(d) := $(addprefix $(OBJPATH)/,$(OBJS))
+else # Populate OBJS_ from SRCS
+
+# Expand wildcards in SRCS if they are given
+ifneq ($(or $(findstring *,$(SRCS)),$(findstring ?,$(SRCS)),$(findstring ],$(SRCS))),)
+  SRCS := $(notdir $(foreach sd,. $(SRCS_VPATH),$(wildcard $(addprefix $(d)/$(sd)/,$(SRCS)))))
+  SRCS := $(filter-out $(SRCS_EXCLUDES), $(SRCS))
+endif
+
+OBJS_$(d) := $(addprefix $(OBJPATH)/,$(addsuffix .o,$(basename $(SRCS))))
+endif
+
+CLEAN_$(d) := $(CLEAN_$(d)) $(filter /%,$(CLEAN) $(TARGETS)) $(addprefix $(d)/,$(filter-out /%,$(CLEAN)))
+
+ifdef TARGETS
+abs_tgts := $(filter /%, $(TARGETS))
+rel_tgts := $(filter-out /%,$(TARGETS))
+TARGETS_$(d) := $(abs_tgts) $(addprefix $(OBJPATH)/,$(rel_tgts))
+$(foreach tgt,$(filter-out $(AUTO_TGTS),$(rel_tgts)),$(eval $(call save_vars,$(OBJPATH)/,$(tgt))))
+# Absolute targets are entry points for external (sub)projects which
+# have their own build system - what is really interesting is only CMD
+# and possibly DEPS however I use this general save_vars (two more vars
+# that are not going to be used should not be a problem :P).
+$(foreach tgt,$(abs_tgts),$(eval $(call save_vars,,$(tgt))))
+else
+TARGETS_$(d) := $(OBJS_$(d))
+endif
+
+# Save user defined vars
+$(foreach v,$(VERB_VARS),$(eval $(v)_$(d) := $($v)))
+$(foreach v,$(OBJ_VARS),$(eval $(v)_$(d) := $(addprefix $(OBJPATH)/,$($v))))
+$(foreach v,$(DIR_VARS),$(eval $(v)_$(d) := $(filter /%,$($v)) $(addprefix $(d)/,$(filter-out /%,$($v)))))
+
+# Update per directory variables that are automatically inherited
+ifeq ($(origin INHERIT_DIR_VARS_$(d)),undefined)
+  INHERIT_DIR_VARS_$(d) := $(or $(INHERIT_DIR_VARS_$(parent_dir)), $(INHERIT_DIR_VARS))
+endif
+$(foreach v,$(INHERIT_DIR_VARS_$(d)),$(if $($(v)_$(d)),,$(eval $(v)_$(d) := $($(v)_$(parent_dir)))))
+
+########################################################################
+# Inclusion of subdirectories rules - only after this line one can     #
+# refer to subdirectory targets and so on.                             #
+########################################################################
+$(foreach sd,$(SUBDIRS),$(eval $(call include_subdir_rules,$(sd))))
+
+.PHONY: dir_$(d) clean_$(d) clean_extra_$(d) clean_tree_$(d) dist_clean_$(d)
+.SECONDARY: $(OBJPATH)
+
+# Whole tree targets
+all :: $(TARGETS_$(d))
+
+clean_all :: clean_$(d)
+
+# dist_clean is optimized in skel.mk if we are building in out of project tree
+ifeq ($(strip $(TOP_BUILD_DIR)),)
+dist_clean :: dist_clean_$(d)
+
+# No point to enforce clean_extra dependency if CLEAN is empty
+ifeq ($(strip $(CLEAN_$(d))),)
+dist_clean_$(d) :
+else
+dist_clean_$(d) : clean_extra_$(d)
+endif
+       rm -rf $(DIST_CLEAN_DIR)
+endif
+
+########################################################################
+#                        Per directory targets                         #
+########################################################################
+
+# Again - no point to enforce clean_extra dependency if CLEAN is empty
+ifeq ($(strip $(CLEAN_$(d))),)
+clean_$(d) :
+else
+clean_$(d) : clean_extra_$(d)
+endif
+       rm -f $(CLEAN_DIR)/*
+
+# clean_extra is meant for the extra output that is generated in source
+# directory (e.g. generated source from lex/yacc) so I'm not using
+# TOP_BUILD_DIR below
+clean_extra_$(d) :
+       rm -rf $(filter %/,$(CLEAN_$(subst clean_extra_,,$@))); rm -f $(filter-out %/,$(CLEAN_$(subst clean_extra_,,$@)))
+
+clean_tree_$(d) : clean_$(d) $(foreach sd,$(SUBDIRS_$(d)),clean_tree_$(sd))
+
+# Skip the target rules generation and inclusion of the dependencies
+# when we just want to clean up things :)
+ifeq ($(filter clean clean_% dist_clean,$(MAKECMDGOALS)),)
+
+SUBDIRS_TGTS := $(foreach sd,$(SUBDIRS_$(d)),$(TARGETS_$(sd)))
+
+# Use the skeleton for the "current dir"
+$(eval $(call skeleton,$(d)))
+# and for each SRCS_VPATH subdirectory of "current dir"
+$(foreach vd,$(SRCS_VPATH),$(eval $(call skeleton,$(d)/$(vd))))
+
+# Target rules for all "non automatic" targets
+$(foreach tgt,$(filter-out $(AUTO_TGTS),$(TARGETS_$(d))),$(eval $(call tgt_rule,$(tgt))))
+
+# Way to build all targets in given subtree (not just current dir as via
+# dir_$(d) - see below)
+tree_$(d) : $(TARGETS_$(d)) $(foreach sd,$(SUBDIRS_$(d)),tree_$(sd))
+
+# If the directory is just for grouping its targets will be targets from
+# all subdirectories
+ifeq ($(strip $(TARGETS_$(d))),)
+TARGETS_$(d) := $(SUBDIRS_TGTS)
+endif
+
+# This is a default rule - see Makefile
+dir_$(d) : $(TARGETS_$(d))
+
+endif
+endef
diff --git a/mk/header.mk b/mk/header.mk
new file mode 100644 (file)
index 0000000..079be59
--- /dev/null
@@ -0,0 +1,12 @@
+# Clear vars used by this make system
+define HEADER
+SRCS :=
+SRCS_EXCLUDES :=
+OBJS :=
+CLEAN :=
+TARGETS :=
+SUBDIRS :=
+
+# Clear user vars
+$(foreach v,$(VERB_VARS) $(OBJ_VARS) $(DIR_VARS),$(eval $(v) := ))
+endef
diff --git a/mk/skel.mk b/mk/skel.mk
new file mode 100644 (file)
index 0000000..99547ea
--- /dev/null
@@ -0,0 +1,254 @@
+# For the reference here are some automatic variables defined by make.
+# There are also their D/F variants e.g. $(<D) - check the manual.
+#
+# $@ - file name of the target of the rule
+# $% - target member name when the target is archive member
+# $< - the name of the first dependency
+# $? - the names of all dependencies that are newer then the target
+# $^ - the names of all dependencies
+
+########################################################################
+#                        User defined variables                        #
+########################################################################
+
+# VERB_VARS is a list of variables that you'd like to record on per
+# directory level.  So if you set it to say AUTOTEST then each each
+# directory will have it's own AUTOTEST_$(dir) variable with value taken
+# from appropriate Rules.mk
+VERB_VARS :=
+
+# OBJ_VARS - like VERB_VARS but all values taken from Rules.mk have
+# $(OBJPATH) prepended so instead of saying:
+#   INSTALL_$d := $(OBJPATH)/some_target
+# you can say simply
+#   INSTALL := some_target
+OBJ_VARS := INSTALL_BIN INSTALL_LIB
+
+# DIR_VARS - like VERB_VARS but all values taken from Rules.mk have $(d)
+# prepended (unless value is an absolute path) so you can say:
+#   INSTALL_DOC := Readme.txt
+# instead of:
+#   INSTALL_DOC_$d := $(d)/Readme.txt
+DIR_VARS := INSTALL_DOC INSTALL_INC
+
+# NOTE: There is generic macro defined below with which you can get all
+# values of given variable from some subtree e.g.:
+#   $(call get_subtree,INSTALL,dir)
+# will give you value of all INSTALL variables from tree starting at
+# 'dir'
+
+########################################################################
+#                       Directory specific flags                       #
+########################################################################
+
+# You just define in Rules.mk say
+# INCLUDES_$(d) := ....
+# and this will get expanded properly during compilation (see e.g. COMPILE.c)
+# Of course you can still use the target specific variables if you want
+# to have special setting for just one target and not the whole
+# directory.  See below for definition of @RD variable.
+DIR_INCLUDES = $(addprefix -I,$(INCLUDES_$(@RD)))
+DIR_CPPFLAGS = $(CPPFLAGS_$(@RD))
+DIR_CFLAGS = $(CFLAGS_$(@RD))
+DIR_CXXFLAGS = $(CXXFLAGS_$(@RD))
+
+########################################################################
+#                       Global flags/settings                          #
+########################################################################
+
+CFLAGS = -g -W -Wall $(DIR_CFLAGS)
+CXXFLAGS = -g -W -Wall $(DIR_CXXFLAGS)
+
+OPT_FLAGS := -O3
+
+# List of includes that all (or at least majority) needs
+INCLUDES :=
+
+# Here's an example of settings for preprocessor.  -MMD is to
+# automatically build dependency files as a side effect of compilation.
+# This has some drawbacks (e.g. when you move/rename a file) but it is
+# good enough for me.  You can improve this by using a special script
+# that builds the dependency files (one can find examples on the web).
+# Note that I'm adding DIR_INCLUDES before INCLUDES so that they have
+# precedence.
+CPPFLAGS = -MMD -D_REENTRANT -D_POSIX_C_SOURCE=200112L -D__EXTENSIONS__ \
+          $(DIR_CPPFLAGS) $(DIR_INCLUDES) $(addprefix -I,$(INCLUDES))
+
+# Linker flags.  The values below will use what you've specified for
+# particular target or directory but if you have some flags or libraries
+# that should be used for all targets/directories just append them at end.
+LDFLAGS = $(LDFLAGS_$(@)) $(addprefix -L,$(LIBDIRS_$(@RD)))
+
+# List of libraries that all targets need (either with specific command
+# generated by this makefile system or for which make has built in rules
+# since LDLIBS is a variable that implicit make rules are using).
+# LDLIBS can be either simple or recursive, but simpler version is
+# suggested :).
+LDLIBS :=
+
+########################################################################
+#                       The end of generic flags                       #
+########################################################################
+
+# Now we suck in configuration ...
+include $(MK)/config.mk
+
+# ... optional build mode specific flags ...
+ifdef BUILD_MODE
+  -include $(MK)/build-$(BUILD_MODE).mk
+endif
+
+# ... host and build specific settings ...
+ifneq ($(wildcard $(MK)/config-$(BUILD_ARCH)_$(HOST_ARCH).mk),)
+  include $(MK)/config-$(BUILD_ARCH)_$(HOST_ARCH).mk
+else
+  include $(MK)/config-default.mk
+endif
+
+# ... and here's a good place to translate some of these settings into
+# compilation flags/variables.  As an example a preprocessor macro for
+# target endianess
+ifeq ($(ENDIAN),big)
+  CPPFLAGS += -DBIG_ENDIAN
+else
+  CPPFLAGS += -DLITTLE_ENDIAN
+endif
+
+# Use host/build specific config files to override default extension
+# for shared libraries 
+SOEXT := $(or $(SOEXT),so)
+
+########################################################################
+#         A more advanced part - if you change anything below          #
+#         you should have at least vague idea how this works :D        #
+########################################################################
+
+# I define these for convenience - you can use them in your command for
+# updating the target.
+DEP_OBJS = $(filter %.o, $^)
+DEP_ARCH = $(filter %.a, $^)
+DEP_LIBS = $(addprefix -L,$(dir $(filter %.$(SOEXT), $^))) $(patsubst lib%.$(SOEXT),-l%,$(notdir $(filter %.$(SOEXT), $^)))
+
+# Kept for backward compatibility - you should stop using these since
+# I'm now not dependent on $(OBJDIR)/.fake_file any more
+?R = $?
+^R = $^
+
+# Targets that match this pattern (make pattern) will use rules defined
+# in:
+# - def_rules.mk included below (explicit or via `skeleton' macro)
+# - built in make rules
+# Other targets will have to use _DEPS (and so on) variables which are
+# saved in `save_vars' and used in `tgt_rule' (see below).
+AUTO_TGTS := %.o
+
+# Where to put the compiled objects.  You can e.g. make it different
+# depending on the target platform (e.g. for cross-compilation a good
+# choice would be OBJDIR := obj/$(HOST_ARCH)) or debugging being on/off.
+OBJDIR := $(if $(BUILD_MODE),obj/$(BUILD_MODE),obj)
+
+# Convenience function to convert from a build directory back to the
+# "real directory" of a target
+define build_to_real_dir
+$(if $(strip $(TOP_BUILD_DIR)),$(patsubst $(TOP_BUILD_DIR)%/$(OBJDIR),$(TOP)%,$(1)),$(patsubst %/$(OBJDIR),%,$(1)))
+endef
+
+# Convenience function to convert from the "real directory" to the build
+# directory
+define real_to_build_dir
+$(if $(strip $(TOP_BUILD_DIR)),$(TOP_BUILD_DIR)$(subst $(TOP),,$(1))/$(OBJDIR),$(1)/$(OBJDIR))
+endef
+
+# By default OBJDIR is relative to the directory of the corresponding Rules.mk
+# however you can use TOP_BUILD_DIR to build all objects outside of your
+# project tree.  This should be an absolute path.  Note that it can be
+# also inside your project like example below.
+#TOP_BUILD_DIR := $(TOP)/build_dir
+OBJPATH = $(call real_to_build_dir,$(d))
+CLEAN_DIR = $(call real_to_build_dir,$(subst clean_,,$@))
+DIST_CLEAN_DIR = $(patsubst %/$(OBJDIR),%/$(firstword $(subst /, ,$(OBJDIR))),\
+                                $(call real_to_build_dir,$(subst dist_clean_,,$@)))
+
+# This variable contains a list of subdirectories where to look for
+# sources.  That is if you have some/dir/Rules.mk where you name object
+# say client.o this object will be created in some/dir/$(OBJDIR)/ and
+# corresponding source file will be searched in some/dir and in
+# some/dir/{x,y,z,...} where "x y z ..." is value of this variable.
+SRCS_VPATH := src
+
+# Target "real directory" - this is used above already and is most
+# reliable way to refer to "per directory flags".  In theory one could
+# use automatic variable already defined by make "<D" but this will not
+# work well when somebody uses SRCS_VPATH variable.
+@RD = $(call build_to_real_dir,$(@D))
+
+# These are commands that are used to update the target.  If you have
+# a target that make handles with built in rules just add its pattern to
+# the AUTO_TGTS below.  Otherwise you have to supply the command and you
+# can either do it explicitly with _CMD variable or based on the
+# target's suffix and corresponding MAKECMD variable.  For example %.a
+# are # updated by MAKECMD.a (exemplary setting below).  If the target
+# is not filtered out by AUTO_TGTS and there's neither _CMD nor suffix
+# specific command to build the target DEFAULT_MAKECMD is used.
+MAKECMD.a = $(call echo_cmd,AR $@) $(AR) $(ARFLAGS) $@ $(DEP_OBJS) && $(RANLIB) $@
+MAKECMD.$(SOEXT) = $(LINK.cc) $(DEP_OBJS) $(DEP_ARCH) $(DEP_LIBS) $(LIBS_$(@)) $(LDLIBS) -shared -o $@
+DEFAULT_MAKECMD = $(LINK.cc) $(DEP_OBJS) $(DEP_ARCH) $(DEP_LIBS) $(LIBS_$(@)) $(LDLIBS) -o $@
+
+########################################################################
+# Below is a "Blood sugar sex^H^H^Hmake magik" :) - don't touch it     #
+# unless you know what you are doing.                                  #
+########################################################################
+
+# This can be useful.  E.g. if you want to set INCLUDES_$(d) for given
+# $(d) to the same value as includes for its parent directory plus some
+# add ons then: INCLUDES_$(d) := $(INCLUDES_$(parent_dir)) ...
+parent_dir = $(patsubst %/,%,$(dir $(d)))
+
+define include_subdir_rules
+dir_stack := $(d) $(dir_stack)
+d := $(d)/$(1)
+$$(eval $$(value HEADER))
+include $(addsuffix /Rules.mk,$$(d))
+$$(eval $$(value FOOTER))
+d := $$(firstword $$(dir_stack))
+dir_stack := $$(wordlist 2,$$(words $$(dir_stack)),$$(dir_stack))
+endef
+
+define save_vars
+DEPS_$(1)$(2) = $(value $(2)_DEPS)
+LIBS_$(1)$(2) = $(value $(2)_LIBS)
+LDFLAGS_$(1)$(2) = $(value $(2)_LDFLAGS)
+CMD_$(1)$(2) = $(value $(2)_CMD)
+$(2)_DEPS =
+$(2)_LIBS =
+$(2)_LDFLAGS =
+$(2)_CMD =
+endef
+
+define tgt_rule
+abs_deps := $$(foreach dep,$$(DEPS_$(1)),$$(if $$(or $$(filter /%,$$(dep)),$$(filter $$$$%,$$(dep))),$$(dep),$$(addprefix $(OBJPATH)/,$$(dep))))
+-include $$(addsuffix .d,$$(basename $$(abs_deps)))
+$(1): $$(abs_deps) $(if $(findstring $(OBJDIR),$(1)),| $(OBJPATH),)
+       $$(or $$(CMD_$(1)),$$(MAKECMD$$(suffix $$@)),$$(DEFAULT_MAKECMD))
+endef
+
+# subtree_tgts is now just a special case of a more general get_subtree
+# macro since $(call get_subtree,TARGETS,dir) has the same effect but
+# I'm keeping it for backward compatibility
+define subtree_tgts
+$(TARGETS_$(1)) $(foreach sd,$(SUBDIRS_$(1)),$(call subtree_tgts,$(sd)))
+endef
+
+define get_subtree
+$($(1)_$(2)) $(foreach sd,$(SUBDIRS_$(2)),$(call get_subtree,$(1),$(sd)))
+endef
+
+# if we are using out of project build tree then there is no need to
+# have dist_clean on per directory level and the one below is enough
+ifneq ($(strip $(TOP_BUILD_DIR)),)
+dist_clean :
+       rm -rf $(TOP_BUILD_DIR)
+endif
+
+# Suck in the default rules
+include $(MK)/def_rules.mk
diff --git a/stm32/.gitignore b/stm32/.gitignore
new file mode 100644 (file)
index 0000000..28a478f
--- /dev/null
@@ -0,0 +1 @@
+/obj
deleted file mode 100644 (file)
index 7833b6dc8c5f1fd9fb714abea2e52acbe95841da..0000000000000000000000000000000000000000
+++ /dev/null
@@ -1,30 +0,0 @@
-##
-## This file is part of the libopencm3 project.
-##
-## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
-##
-## This library is free software: you can redistribute it and/or modify
-## it under the terms of the GNU Lesser General Public License as published by
-## the Free Software Foundation, either version 3 of the License, or
-## (at your option) any later version.
-##
-## This library is distributed in the hope that it will be useful,
-## but WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-## GNU Lesser General Public License for more details.
-##
-## You should have received a copy of the GNU Lesser General Public License
-## along with this library.  If not, see <http://www.gnu.org/licenses/>.
-##
-
-BINARY = z180-stamp-stm32
-
-OBJS = z80-if.o hdrom.o
-
-PREFIX = /usr/local/gcc-arm-none-eabi-4_8-2014q1/bin/arm-none-eabi
-
-OPENCM3_DIR = ../libopencm3
-LDSCRIPT = ../stm32vl-discovery.ld
-
-include ../libopencm3.target.mk
-
new file mode 120000 (symlink)
index 0000000000000000000000000000000000000000..d0b0e8e0086f68062b2b427755eb137285993ed3
--- /dev/null
@@ -0,0 +1 @@
+../Makefile
\ No newline at end of file
diff --git a/stm32/Rules.mk b/stm32/Rules.mk
new file mode 100644 (file)
index 0000000..4751496
--- /dev/null
@@ -0,0 +1,144 @@
+
+BINARY         := z180-stamp-stm32
+P_BINARY       := $(OBJPATH)/$(BINARY)
+
+TARGETS                := $(BINARY).elf #$(BINARY).bin
+
+SRCS := z180-stamp-stm32.c z80-if.c hdrom.c
+
+
+LIBNAME                = opencm3_stm32f1
+DEFS           = -DSTM32F1
+OPENCM3_DIR    := $(TOP)/libopencm3
+LDSCRIPT       := $(d)/stm32vl-discovery.ld
+
+FP_FLAGS       ?= -msoft-float
+ARCH_FLAGS     = -mthumb -mcpu=cortex-m3 $(FP_FLAGS) -mfix-cortex-m3-ldrd
+
+STLINK_PORT = :3333 
+
+###############################################################################
+# Executables
+
+TOOLCHAINDIR   := /usr/local/gcc-arm-none-eabi-4_8-2014q1/bin
+TOOLCHAIN      := $(TOOLCHAINDIR)/arm-none-eabi
+
+CC             := $(TOOLCHAIN)-gcc
+LD             := $(TOOLCHAIN)-gcc
+AR             := $(TOOLCHAIN)-ar
+AS             := $(TOOLCHAIN)-as
+OBJCOPY        := $(TOOLCHAIN)-objcopy
+OBJDUMP        := $(TOOLCHAIN)-objdump
+GDB            := $(TOOLCHAIN)-gdb
+
+###############################################################################
+# Source files
+
+
+
+ifeq ($(VERBOSE),true)
+$(info Using $(OPENCM3_DIR) path to library)
+endif
+
+INCLUDES_$(d) := $(OPENCM3_DIR)/include
+LIBDIRS_$(d)  := $(OPENCM3_DIR)/lib
+
+SCRIPT_DIR     = $(OPENCM3_DIR)/scripts
+
+###############################################################################
+# C flags
+
+CFLAGS_$(d)    := -Os -g
+CFLAGS_$(d)    += -Wextra -Wshadow -Wimplicit-function-declaration
+CFLAGS_$(d)    += -Wredundant-decls #-Wstrict-prototypes
+CFLAGS_$(d)    += -fno-common -ffunction-sections -fdata-sections
+CFLAGS_$(d)    += -std=c99
+CFLAGS_$(d)    += $(ARCH_FLAGS)
+
+###############################################################################
+# C & C++ preprocessor common flags
+
+CPPFLAGS_$(d) := $(DEFS)
+
+###############################################################################
+# Linker flags
+
+LDFLAGS                += --static -nostartfiles
+LDFLAGS                += -T$(LDSCRIPT)
+LDFLAGS                += -Wl,-Map=$(*).map
+LDFLAGS                += -Wl,--gc-sections
+
+#ifeq ($(VERBOSE),true)
+#LDFLAGS               += -Wl,--print-gc-sections
+#endif
+
+###############################################################################
+# Used libraries
+
+LDLIBS         += -l$(LIBNAME)
+LDLIBS         += -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group
+
+
+###############################################################################
+###############################################################################
+
+
+$(BINARY).elf_DEPS = z180-stamp-stm32.o z80-if.o hdrom.o
+$(BINARY).elf_CMD = $(call echo_cmd,LINK $@) $(LD) $(LDFLAGS) $(ARCH_FLAGS) $^ $(LDLIBS) -o $@
+
+.SUFFIXES: .elf .bin .hex .srec .list .map .images
+.SECONDEXPANSION:
+
+elf: $(P_BINARY).elf
+bin: $(P_BINARY).bin
+hex: $(P_BINARY).hex
+srec: $(P_BINARY).srec
+list: $(P_BINARY).list
+
+images: $(P_BINARY).images
+flash: $(P_BINARY).flash
+
+%.images: %.bin %.hex %.srec %.list
+       $(call echo_cmd,Images generated: $*)
+
+%.bin: %.elf
+       $(call echo_cmd,OBJCOPY $@) $(OBJCOPY) -Obinary $< $@
+
+%.hex: %.elf
+       $(call echo_cmd,OBJCOPY $@) $(OBJCOPY) -Oihex $< $@
+
+%.srec: %.elf
+       $(call echo_cmd,OBJCOPY $@) $(OBJCOPY) -Osrec $< $@
+
+%.list: %.elf
+       $(call echo_cmd,OBJDUMP $@) $(OBJDUMP) -S $< > $@
+
+#$(OBJPATH)/%.elf: $(OBJS) $(LDSCRIPT) $(LIB_DIR)/lib$(LIBNAME).a
+#      @#printf "  LD      $(*).elf\n"
+#      $(LD) $(LDFLAGS) $(ARCH_FLAGS) $(OBJS_$(d)) $(LDLIBS) -o $(*).elf
+
+#%.o: %.c
+#      @#printf "  CC      $(*).c\n"
+#      $(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -o $(*).o -c $(*).c
+#
+#%.o: %.cxx
+#      @#printf "  CXX     $(*).cxx\n"
+#      $(Q)$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -o $(*).o -c $(*).cxx
+#
+#%.o: %.cpp
+#      @#printf "  CXX     $(*).cpp\n"
+#      $(Q)$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -o $(*).o -c $(*).cpp
+
+#clean:
+#      @#printf "  CLEAN\n"
+#      $(Q)$(RM) *.o *.d *.elf *.bin *.hex *.srec *.list *.map
+
+
+%.flash: %.elf
+       $(call echo_cmd,GDB $< (flash)) $(GDB) --batch \
+                  -ex 'target extended-remote $(STLINK_PORT)' \
+                  -x $(SCRIPT_DIR)/stlink_flash.scr \
+                  $<
+
+.PHONY: images elf bin hex srec list flash
+