summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo C2014-04-13 15:29:22 +0200
committerLeo C2014-04-13 15:29:22 +0200
commit88d31d1177b58a2b2052a837a095b51834a8babf (patch)
treeaeae7c27dd388af93a1fa2be383f1acb149c8fac
parente64eba003f92992057c5a1c8b5eff902e4ddaaa5 (diff)
downloadz180-stamp-88d31d1177b58a2b2052a837a095b51834a8babf.zip
Add non-recursive make system from Andrzej Ostruszka.
Copyright (C) 2012 Andrzej Ostruszka <andrzej.ostruszka@gmail.com> URL: http://github.com/aostruszka/nonrec-make
-rw-r--r--.gitignore4
l---------Makefile1
-rw-r--r--Rules.top16
-rw-r--r--libopencm3.rules.mk240
-rw-r--r--libopencm3.target.mk45
-rw-r--r--mk/Makefile52
-rw-r--r--mk/Readme.txt469
-rw-r--r--mk/build-debug.mk4
-rw-r--r--mk/build-profile.mk4
-rw-r--r--mk/build-release.mk4
-rw-r--r--mk/config-Cygwin-i686_Cygwin-i686.mk10
-rw-r--r--mk/config-Cygwin-i686_Linux-ppc.mk11
-rw-r--r--mk/config-MinGW-i686_MinGW-i686.mk8
-rw-r--r--mk/config-SunOS-sun4u_SunOS-sun4u.mk6
-rw-r--r--mk/config-default.mk8
-rw-r--r--mk/config.mk44
-rw-r--r--mk/def_rules.mk123
-rw-r--r--mk/footer.mk119
-rw-r--r--mk/header.mk12
-rw-r--r--mk/skel.mk254
-rw-r--r--stm32/.gitignore1
l---------[-rw-r--r--]stm32/Makefile31
-rw-r--r--stm32/Rules.mk144
-rw-r--r--stm32/stm32vl-discovery.ld (renamed from stm32vl-discovery.ld)0
24 files changed, 1295 insertions, 315 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..68760d7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+Makefiledev
+/.settings
+/.cproject
+/.project
diff --git a/Makefile b/Makefile
new file mode 120000
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
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
index 1896071..0000000
--- a/libopencm3.rules.mk
+++ /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
index a381abb..0000000
--- a/libopencm3.target.mk
+++ /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
index 0000000..7658b42
--- /dev/null
+++ b/mk/Makefile
@@ -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
index 0000000..c341b48
--- /dev/null
+++ b/mk/Readme.txt
@@ -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
index 0000000..adcc04f
--- /dev/null
+++ b/mk/build-debug.mk
@@ -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
index 0000000..e7b14ac
--- /dev/null
+++ b/mk/build-profile.mk
@@ -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
index 0000000..7869bbb
--- /dev/null
+++ b/mk/build-release.mk
@@ -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
index 0000000..ee7880f
--- /dev/null
+++ b/mk/config-Cygwin-i686_Cygwin-i686.mk
@@ -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
index 0000000..6a7c865
--- /dev/null
+++ b/mk/config-Cygwin-i686_Linux-ppc.mk
@@ -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
index 0000000..fc097de
--- /dev/null
+++ b/mk/config-MinGW-i686_MinGW-i686.mk
@@ -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
index 0000000..57db3dc
--- /dev/null
+++ b/mk/config-SunOS-sun4u_SunOS-sun4u.mk
@@ -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
index 0000000..d8db456
--- /dev/null
+++ b/mk/config-default.mk
@@ -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
index 0000000..baaf1f8
--- /dev/null
+++ b/mk/config.mk
@@ -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
index 0000000..9197b03
--- /dev/null
+++ b/mk/def_rules.mk
@@ -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
index 0000000..c6d19d3
--- /dev/null
+++ b/mk/footer.mk
@@ -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
index 0000000..079be59
--- /dev/null
+++ b/mk/header.mk
@@ -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
index 0000000..99547ea
--- /dev/null
+++ b/mk/skel.mk
@@ -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
index 0000000..28a478f
--- /dev/null
+++ b/stm32/.gitignore
@@ -0,0 +1 @@
+/obj
diff --git a/stm32/Makefile b/stm32/Makefile
index 7833b6d..d0b0e8e 100644..120000
--- a/stm32/Makefile
+++ b/stm32/Makefile
@@ -1,30 +1 @@
-##
-## 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
-
+../Makefile \ No newline at end of file
diff --git a/stm32/Rules.mk b/stm32/Rules.mk
new file mode 100644
index 0000000..4751496
--- /dev/null
+++ b/stm32/Rules.mk
@@ -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
+
diff --git a/stm32vl-discovery.ld b/stm32/stm32vl-discovery.ld
index 40de3d3..40de3d3 100644
--- a/stm32vl-discovery.ld
+++ b/stm32/stm32vl-discovery.ld