From 88d31d1177b58a2b2052a837a095b51834a8babf Mon Sep 17 00:00:00 2001 From: Leo C Date: Sun, 13 Apr 2014 15:29:22 +0200 Subject: [PATCH 1/1] Add non-recursive make system from Andrzej Ostruszka. Copyright (C) 2012 Andrzej Ostruszka URL: http://github.com/aostruszka/nonrec-make --- .gitignore | 4 + Makefile | 1 + Rules.top | 16 + libopencm3.rules.mk | 240 --------- libopencm3.target.mk | 45 -- mk/Makefile | 52 ++ mk/Readme.txt | 469 ++++++++++++++++++ mk/build-debug.mk | 4 + mk/build-profile.mk | 4 + mk/build-release.mk | 4 + mk/config-Cygwin-i686_Cygwin-i686.mk | 10 + mk/config-Cygwin-i686_Linux-ppc.mk | 11 + mk/config-MinGW-i686_MinGW-i686.mk | 8 + mk/config-SunOS-sun4u_SunOS-sun4u.mk | 6 + mk/config-default.mk | 8 + mk/config.mk | 44 ++ mk/def_rules.mk | 123 +++++ mk/footer.mk | 119 +++++ mk/header.mk | 12 + mk/skel.mk | 254 ++++++++++ stm32/.gitignore | 1 + stm32/Makefile | 31 +- stm32/Rules.mk | 144 ++++++ .../stm32vl-discovery.ld | 0 24 files changed, 1295 insertions(+), 315 deletions(-) create mode 100644 .gitignore create mode 120000 Makefile create mode 100644 Rules.top delete mode 100644 libopencm3.rules.mk delete mode 100644 libopencm3.target.mk create mode 100644 mk/Makefile create mode 100644 mk/Readme.txt create mode 100644 mk/build-debug.mk create mode 100644 mk/build-profile.mk create mode 100644 mk/build-release.mk create mode 100644 mk/config-Cygwin-i686_Cygwin-i686.mk create mode 100644 mk/config-Cygwin-i686_Linux-ppc.mk create mode 100644 mk/config-MinGW-i686_MinGW-i686.mk create mode 100644 mk/config-SunOS-sun4u_SunOS-sun4u.mk create mode 100644 mk/config-default.mk create mode 100644 mk/config.mk create mode 100644 mk/def_rules.mk create mode 100644 mk/footer.mk create mode 100644 mk/header.mk create mode 100644 mk/skel.mk create mode 100644 stm32/.gitignore mode change 100644 => 120000 stm32/Makefile create mode 100644 stm32/Rules.mk rename stm32vl-discovery.ld => stm32/stm32vl-discovery.ld (100%) 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 -## Copyright (C) 2010 Piotr Esden-Tempski -## Copyright (C) 2013 Frantisek Burian -## -## 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 . -## - -# 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 -## Copyright (C) 2010 Piotr Esden-Tempski -## -## 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 . -## - -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 # +# # +# 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_$( + which builds all targets in given directory plus its dependencies +2) tree_ + which builds all targets in subtree starting at directory given +3) clean_ + which removes all "products" from the $(OBJDIR) subdirectory of + current directory +4) clean_tree_ + which does clean_ 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. $( -## -## 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 . -## - -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 - diff --git a/stm32/Makefile b/stm32/Makefile new file mode 120000 index 0000000..d0b0e8e --- /dev/null +++ b/stm32/Makefile @@ -0,0 +1 @@ +../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 similarity index 100% rename from stm32vl-discovery.ld rename to stm32/stm32vl-discovery.ld -- 2.39.2