]> cloudbase.mooo.com Git - z180-stamp.git/blame - mk/Readme.txt
Rename dir Z180 --> z180
[z180-stamp.git] / mk / Readme.txt
CommitLineData
88d31d11
L
1################################################################################
2# Non-recursive make build system #
3# ------------------------------- #
4# Copyright (C) 2012 Andrzej Ostruszka <andrzej.ostruszka@gmail.com> #
5# #
6# URL: http://github.com/aostruszka/nonrec-make #
7# (or older: http://nonrec-make.googlecode.com/) #
8# #
9# Permission is hereby granted, free of charge, to any person obtaining a copy #
10# of this software and associated documentation files (the "Software"), to #
11# deal in the Software without restriction, including without limitation the #
12# rights to use, copy, modify, merge, publish, distribute, sublicense, #
13# and/or sell copies of the Software, and to permit persons to whom the #
14# Software is furnished to do so, subject to the following conditions: #
15# #
16# The above copyright notice and this permission notice shall be included in #
17# all copies or substantial portions of the Software. #
18# #
19# Except as contained in this notice, the name(s) of the above copyright #
20# holders shall not be used in advertising or otherwise to promote the sale, #
21# use or other dealings in this Software without prior written authorization. #
22# #
23# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR #
24# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, #
25# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #
26# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
27# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING #
28# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS #
29# IN THE SOFTWARE. #
30################################################################################
31
32NOTE: This readme _might_ not be up to date. For up to date information
33see the above URL (and accompanying wiki pages).
34
35This is my attempt to implement a non-recursive make build system. For
36the motivation Google for the paper "Recursive make consider harmful" by
37Peter Miller.
38
39I've seen couple of other proposals and decided to have something that
40will be a blend of nice ideas I have seen plus some improvements. If
41you actually use this I'd like to hear from you :) - is it useful, does
42it perform well, do you have any suggestions for the improvements ...
43and so on. This implementation is based on GNU make and its new
44features introduced in 3.80. But don't use that version - these
45features had bugs in that version. Use version 3.81 where everything
46works OK.
47
48Before you keep on reading though, just take a look at the structure of
49the Rules.mk files (Rules.top has exactly the same structure as Rules.mk
50- it just has another name to ease location of the top level project
51directory from its subfolders).
52I've got a feeling that it is much easier to understand how the system
53looks from the user perspective just by looking at the example than
54reading its explanation :D.
55
56OK, now that you have a feeling how the Rules.mk look like let me walk
57you through an example (ex1 in the repository). Consider the project
58that has some source files at the top directory and is depending on two
59libraries in Dir_1 and Dir_2 and another one in Dir_3. The libraries
60themselves are partitioned between several subdirectories and Dir_2 has
61some examples in a separate subfolder (do not pay attention to all *.c
62files).
63
64ex1/
65 Makefile
66 Rules.top <- Just a symlink to Rules.mk to mark where the top level is
67 Rules.mk
68 main.c
69 top_a.c
70 top_b.c
71 cli.c
72 cli_dep.c
73 mk/* <- This is where the mk files from this build system are
74 Dir_1/
75 Makefile
76 Rules.mk
77 dir_1_file1.c
78 dir_1_file2.c
79 dir_1_file3.c
80 Dir_1a/
81 Makefile
82 Rules.mk
83 dir_1a_file1.c
84 dir_1a_file2.c
85 dir_1a_file3.c
86 Dir_1b/
87 Makefile
88 Rules.mk
89 src/
90 dir_1b_file1.c
91 dir_1b_file2.c
92 Dir_2/
93 Makefile
94 Rules.mk
95 dir_2_file1.c
96 dir_2_file2.c
97 Dir_2a/
98 Makefile
99 Rules.mk
100 dir_2a_file1.c
101 dir_2a_file2.c
102 dir_2a_file3.c
103 Dir_2b/
104 Makefile
105 Rules.mk
106 dir_2b_file1.c
107 dir_2b_file2.c
108 dir_2b_file3.c
109 Dir_ex/
110 Makefile
111 Rules.mk
112 ex.c
113 Dir_3/
114 Makefile
115 Rules.mk
116 dir_3_file1.c
117 dir_3_file2.c
118
119There's one top level make file (Rules.top) which eventually includes
120all the makefiles. In addition in each directory there is Makefile
121(which can be a link to the one in the top level directory) which
122searches for the Rules.top includes it with the default goal
123changed to rebuild only targets for the current directory. This allows
124you to run make from each subdirectory and update only part of the
125targets (in contrary to other implementation which usually require
126you to run it at the top level and make full build each time).
127
128This build system was designed to have very simple structure of the
129"user makefiles". The user just has to set the Rules.mk files in each
130directory and some general configuration options. All the "magic" is
131hidden in header.mk, footer.mk and skel.mk which don't have to be
132modified [1].
133
134The structure of the Rules.mk is following (this is from top level
135Rules.top which has the same format as Rules.mk - and in fact it is
136suggested that it should be a symlink to normal Rules.mk file since it
137will allow for this project to act as a subproject of some super project
138treating your whole project tree as a subdirectory[2]):
139
140-8<---Rules.top---------------
1411: TARGETS = app.exe cli.exe
1422: SUBDIRS = Dir_1 Dir_2
1433:
1444: app.exe_DEPS = top_a.o top_b.o main.o $(SUBDIRS_TGTS)
1455: app.exe_LIBS = -lm
1466: # Let's use DEFAULT_MAKECMD for app.exe
1477:
1488: cli.exe_DEPS = cli.o cli_dep.o
1499: cli.exe_CMD = $(LINK.c) $^ $(LDLIBS) -o $@
150-8<---------------------------
151
152Line 1 - this directory has two targets that should be built.
153Line 2 - this directory has two subdirectories that should be scanned
154Line 4 - app.exe depends on ... (SUBDIRS_TGTS is a variable that
155 contains all the targets from the subdirectories mentioned at
156 line 4)
157Line 5 - app.exe should be linked with math library
158Line 6 - app.exe will be built with default "rule"
159Line 8 - cli.exe depends on ... and
160Line 9 - use the following command to build it
161
162You can specify the targets for current directory in two ways:
1631. Give them in TARGETS. Each target can have it's own *_DEPS, *_LIBS
164 and *_CMD which give the dependencies, additional libs needed and
165 a command to run which will update the target. They are explained
166 a bit below.
1672. The targets are simply objects - or in more general files that
168 match patterns in AUTO_TGTS, and have appropriate rules in 'skeleton'.
169 In that case you can list them in OBJS or SRCS like e.g. in Rules.mk
170 from Dir_1a
171
172-8<---Dir_2/Dir_2a/Rules.mk---
1731: SRCS := dir_2a_file1.c dir_2a_file2.c dir_2a_file3.c
174-8<---------------------------
175
176There are "reserved" variables that you should not modify. Most notably:
177- $(d) is the directory of the current Rules.mk [see note 2]
178- $(TOP) is the top level directory of the project tree
179- $(MK) is the directory where the included *.mk makefiles are
180For the full list you have to take a look at the makefiles in mk
181directory (e.g. in the skel.mk there are macros 'include_subdir_rules',
182'save_vars', 'tgt_rule' and 'skeleton' which you should not change [1]).
183
184Going back to the Rules.mk. Normally wildcards in variable assignments
185are not expanded in make but this make system detects wildcards in SRCS
186and expands them (both in directory of the Rules.mk and its SRCS_VPATH
187subdirectories - see below what SRCS_VPATH is used for). Thus you can
188simply say in Rules.mk:
189
190SRCS := *.c
191
192If you have directory with large number of files where simple glob is
193what you want to use in SRCS but there are some files that you'd like to
194exclude just list them in SRCS_EXCLUDES :) - this is a list of makefile
195patterns e.g.
196
197SRCS_EXCLUDES := extra% test%
198
199Of course you can use the built in make wildcards but you should do that
200as follows:
201
202SRCS := $(notdir $(wildcard $(d)/*.c))
203
204Keep in mind that the directory where make is invoked is usually different
205from where given Rules.mk is located.
206
207When supplying the value for *_DEPS you can refer to the object from the
208same directory with no directory prefix. To be specific all
209dependencies that are not absolute paths will be treated as ones from
210the $(OBJDIR) subdirectory of current directory (OBJDIR and OBJPATH are
211"discussed" below). You can use SUBDIRS_TGTS variable which will list
212all targets in subdirectories. You can also name them explicitly like
213$(TARGETS_$(d)/subdir) and so on - see e.g. the Rules.mk in Dir_2
214directory where Dir_ex is mentioned as a subdirectory but is excluded
215from the *_DEPS (this allows you to create folders that "inherit" all
216the setting from the project build system but are not meant to be a part
217of the project itself - like examples). For instance:
218
219dir1_lib.a_DEPS = dir_1_file1.o dir_1_file2.o dir_1_file3.o $(SUBDIRS_TGTS)
220
221tells that dir1_lib.a (which will be created in Dir_1/$(OBJDIR)) depends
222on several object files from the same directory and the targets from all
223subdirectories.
224
225One last thing about the TARGETS/OBJS. By default source files for the
226objects are searched in the directory where Rules.mk is, but if you want
227to have source files in a subdirectory (say 'src') you can do that via
228SRCS_VPATH variable (see skel.mk). E.g.:
229
230SRCS_VPATH := src1 src2
231
232will cause make to first look at the directory where Rules.mk is present
233and then in its src1 and src2 subdirectories.
234
235*_LIBS are appended to the LDLIBS variable when updating the target.
236This variable is used by several make built in rules but if you create
237your own rule or MAKECMD.* (see next paragraph) you can refer to it (see
238the function 'save_vars').
239
240When *_CMD is not present and the target does not match any pattern in
241AUTO_TGTS then either MAKECMD.suff (where .suff is the suffix of the
242target) or DEFAULT_MAKECMD is used - take a look into skel.mk.
243
244If you want to setup special flags for compilation you can do that via
245"directory specific variables". As an example here's what I did for
246compilation of C files. There's a built in rule in make which uses
247COMPILE.c variable for making %.o out of %.c so I added $(DIR_CFLAGS) to
248its default value and DIR_CFLAGS is defined in skel.mk as:
249
250DIR_INCLUDES = $(addprefix -I,$(INCLUDES_$(<D)))
251DIR_CFLAGS = $(CFLAGS_$(<D)) $(DIR_INCLUDES)
252
253So it extracts the directory part of the first prerequisite in the rule
254(that is %.c file - check the section 'automatic variables' in make
255manual for the meaning of $(<) and $(<D)) and refer to variables named
256CFLAGS_the_directory_part and INCLUDES_the_directory_part.
257Thus if you wanted to add special includes for files in Dir_1/Dir_1b you
258could add:
259
260INCLUDES_$(d) := $(TOP)/some/special/include_dir
261
262into its Rules.mk and all files in this directory will be compiled with
263-I$(TOP)/some... switch. The same goes for CFLAGS and CXXFLAGS.
264
265The same goes for the linker flags - quoting from skel.mk:
266
267LDFLAGS = $(addprefix -L,$(LIBDIRS_$(subst /$(OBJDIR),,$(@D))))
268LDLIBS = $(LIBS_$(@))
269
270The above means that if targets in given directory need to be linked
271with special -L switches you can provide them via LIBDIRS_$(d)
272variables. If there are some global -L switches just append them in
273skel.mk. The second line above shows how *_LIBS variable that you can
274give for specific target gets added to the LDLIBS (there's 'save_vars'
275in between if you're curious :)).
276
277You can of course use target specific variables that GNU make supports
278so you have more control (if you don't know what target specific
279variables are take a look into manual). Say you want to compile
280dir_1b_file2.c with an additional flag but all other files in
281Dir_1/Dir_1b directory should not have this flag turned on. All you
282need to do is to add this line into Rules.mk in Dir_1b directory.
283
284$(OBJPATH)/dir_1b_file2.o : CFLAGS += -ansi
285
286OBJPATH is a variable that contains the full directory where the
287resulting object file will be placed. While we are at this, by default
288all targets are compiled into OBJDIR (defined in skel.mk as 'obj')
289subdirectory of the directory where Rules.mk is present. You can use
290this OBJDIR variable (and perhaps some conditional statements) to setup
291the output path according to your current compilation mode. E.g.
292obj/debug for objects with debugging information or obj/ppc_7xx for
293cross compilation to the given Power PC family and so on. There's
294predefined (in config* files) HOST_ARCH variable that you can use for
295this (e.g. set OBJDIR := obj/$(HOST_ARCH) in skel.mk).
296
297Finally let me explain what targets are defined and the way you can run
298them from command line. By default (that is if you have not modified
299anything :)) there are several targets that are "global". It is 'all',
300'clean_all' and 'dist_clean'. If you specify them in the command line
301they will respectively rebuild whole tree, clean everything and clean
302everything together with the removal of OBJDIRs - no matter from which
303directory you started make. BTW if there's something that you want to
304clean up and it's not in the OBJDIR - e.g. you've got file lexer.l out
305of which lexer.c and lexer.h is generated and you want them to be
306removed - you can specify this in the variable CLEAN (this is relative
307to the directory where Rules.mk is).
308In addition to those each dir has "it's own" targets. These are:
309
3101) dir_<directory_path>
311 which builds all targets in given directory plus its dependencies
3122) tree_<directory_path>
313 which builds all targets in subtree starting at directory given
3143) clean_<directory_path>
315 which removes all "products" from the $(OBJDIR) subdirectory of
316 current directory
3174) clean_tree_<directory_path>
318 which does clean_<directory_path> and the same for each its
319 subdirectory
320
321For your convenience there are couple "aliases" defined (see Makefile).
322When no target is given on command line it defaults to dir_$(pwd).
323If you give 'clean' as a target that will result in execution of target
324clean_$(pwd) and the same for 'clean_tree'. E.g. say you're in Dir_1.
325Then:
326
327* 'make' (same as 'make dir_$(pwd)')
328 builds all targets in the Dir_1 which in our example is
329 Dir_1/obj/dir1_lib.a - of course any of its dependencies that are not
330 up to date are updated also. This rule has one exception - if your
331 Rules.mk has no targets and only SUBDIRS (e.g. you have grouped
332 several subdirectories in one directory) then simple 'make' in this
333 directory - instead of doing nothing - will build targets of all its
334 subdirectories.
335* 'make tree' (same as 'make tree_$(pwd)')
336 rebuilds everything in given subtree
337* 'make clean' (same as 'make clean_$(pwd)')
338 removes everything from Dir_1/obj/
339* 'make clean_tree (same as 'make clean_tree_$(pwd)')
340 cleans Dir_1/obj and Dir_1/Dir_1[abc]/obj
341
342You can obviously provide the path by yourself - it does not have to
343be $(pwd) - and as usual you can build particular object files too e.g.
344'make $(pwd)/obj/dir_1_file1.o'
345
346And that would be it. Gee, so much writing for something that is rather
347simple to use - go ahead and take a look again at these Rules.mk in
348various directories. Setting up you project should be simple by now :).
349
350Have fun!
351
352 Andrzej Ostruszka
353
354[1] Unless this build system does not do what you wanted :-P. In that
355case you probably need to spiff it up. So you'll need to
356digest it first and note [3] is my hand at it :).
357
358[2] There is one limitation that you should be aware.
359Prior to commit 070f681 you should not have in your project two "target
360specific" LIBS, LDFLAGS or CMD variables (that is those that are used
361during second phase of make execution) that have the same names! For
362example in one part of your tree you're generating target abc which has
363it's abc_CMD and in the other part another target that has the same name
364and also it's own command. In such case the last assignment to abc_CMD
365will hold and it will be used for both targets. The same goes for LIBS
366and LDFLAGS.
367
368And this also applied to situation when you would like to use two
369subprojects in one larger project. There should be no clash between
370variables from these subprojects.
371
372Starting with commit 070f681 you can have in your (sub)projects two
373LIBS, LDFLAGS or CMD variables. However there is a catch here! Since
374these variables are not mandatory (you don't have to provide them for
375each target) in order to differentiate between case where abc_CMD was
376actually given for this instance of abc target from the situation where
377abc_CMD is still visible from previous instance of abc target those
378abc_(LIBS|LDFLAGS|CMD) variables are cleared once their value is
379used/remembered (see save_vars macro in skel.mk). That means referring
380to these variables outside Rules.mk where they were assigned will not
381work (and even in the same Rules.mk they will work only in case of
382simply expanded variables - not recursive). If you have such need I'd
383advice to introduce your own variable and use this variable in all
384places, e.g.:
385
386MATH_LIBS := -lgsl -lgslcblas -lm
387...
388TARGETS := abc
389
390abc_DEPS = ...
391abc_LIBS = $(MATH_LIBS)
392...
393
394[3] You should know that make works in two phases - first it scans the
395makefiles and then it begins their execution (see discussion of
396'immediate' and 'deferred' in section 'Reading Makefiles' of make
397manual). This implies that the $(d) variable is not valid during
398execution of the commands used for target updates. If you need to refer
399to the directory of the target or prerequisite you should rely on
400automatic variables (@, <, ...) and built in functions (dir, notdir,
401...).
402
403Every Rules.mk (or Rules.top) need to be included in cooperation with
404header.mk and footer.mk. This is now done automatically but in older
405versions this was not so and user had to include them manually.
406The main purpose of header is to clear all variables that you can use
407inside Rules.mk so that values set in one rules file does not propagate
408to other. In addition at the top level it sets the $(d) variable (which
409stands for the directory where the currently included Rules.mk is) and
410includes the skel.mk so the top level Rules.top can have exactly the
411same structure as other Rules.mk.
412
413The skel.mk is a skeleton which defines variables used by make. In
414addition it includes:
415- config.mk - this is a file with the "configuration" for your project
416- def_rules.mk - where to put general rules (e.g. pattern rules). E.g.
417 if you want to add a rule that builds %.o out of %.m4 (by running m4
418 preprocessor before passing the contents of file to CC) just put it in
419 here.
420
421skel.mk also defines some functions like save_vars and tgt_rule
422which are called in the footer.mk. Take a look into make manual for the
423way the functions are defined and called if you're not familiar with it.
424
425include_subdir_rules: This is where I keep track of directory of
426 currently included makefile and include the Rules.mk from the
427 subdirectories. This function is called in footer.mk in foreach
428 loop with a subdirectory name as an argument.
429
430save_vars: This one is very simple it just saves the target specific
431 variables under their "full path" variables. E.g.
432 dir1_lib.a_DEPS will get saved as DEPS_$(TOP)/Dir_1/obj/dir1_lib.a
433 This has two purposes. First it allows you to have targets with
434 the same names in different directories (not that I recommend
435 this :)) and allows for easier definition of tgt_rules :-P
436
437tgt_rule: This is where the rule for given target is created. First
438 I convert all relative dependencies to the absolute ones then
439 I include all dependency files (by default they are created as
440 side effects during compilation - if your compiler does not
441 allow you to do that just make simple shell script that will do
442 this). I also append appropriate libs and then issue the rule
443 for this target. By using the short circuiting 'or' command
444 I give priority to the CMD over MAKECMD.suffix which itself has
445 priority over DEFAULT_MAKECMD.
446
447skeleton: This is just a skeleton for compilation of files in given
448 directory. If you want to add some rule here then also add
449 appropriate pattern to the AUTO_TGTS that will filter out these
450 targets and prevent generation of the specific rules via
451 tgt_rule function.
452
453The footer.mk is where Rules.mk gets translated into the proper
454makefile. There's not much to explain, just take a look in there.
455First I memorize the targets for given directory (either from OBJS/SRCS
456or from TARGETS) with appropriate directory prefix. If there's need to
457save the target specific *_(CMD|DEP|LIB) I do it. Then I include all
458the Rules.mk from the subdirectories. Then I define the targets for
459given directory either explicitly (like clean_all or clean_$(d)) or by
460evaluation of the 'skeleton' mentioned above or by iterating through all
461targets which do not match AUTO_TGTS and evaluating what tgt_rule
462function for this target has returned.
463
464In case you want to play with these settings make sure you understand
465how make works, what are it's phases, when and how the variables are
466expanded and so on. It will save you a lot of time :).
467
468Best regards
469Andrzej