/
makefile.lib
216 lines (176 loc) · 9.77 KB
/
makefile.lib
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
#-----------------------------------------------------------------------
# Copyright (c) 2003 2004 Daan Leijen.
# This file is distributed under the wxWindows library license.
# See "license.txt" for more details.
#
# This file contains helper functions for the makefile.
#-----------------------------------------------------------------------
#--------------------------------------------------------------------------
# Dependencies are handled (almost) automatically: no need for "make depend" :-)
#
# Makefile implementation notes:
#
# The dependency (.d) files are generated together with object files using
# the compiler -M switch. Such dependency file is later processed
# by sed to prepend the proper directory to the target and to move it
# into the proper (imports) directory. The way dependency files are handled
# was 'discovered' by Tom Tromey, and described by Paul Smith,
# see "advanced auto-dependency generation" at:
# "http://make.paulandlesley.org/autodep.html"
#
# (Unfortunately, there are situations where this method doesn't work for Haskell
# modules -- but these situations are exteremely rare in practice, nothing that
# can't be solved by a "make clean; make" command. I believe that in the end
# this method is much more robust than "make depend".)
#
# We use a single makefile in order to correctly resolve dependencies
# between the different projects -- a recursive make fails to do that,
# see "recursive make considered harmfull" at:
# "http://www.tip.net.au/~millerp/rmch/recu-make-cons-harm.html"
# (We might use include files in the future to split this file in smaller chunks.)
#
# We don't use implicit rules (i.e. "%.o: %.c") as the VPATH mechanism can't
# deal with modules with the same name in different directories :-(
#
# We edit (sed) the haskell dependency files to change dependencies on .hi
# files to .o files. We just disregard .hi files and assume they are always
# generated together with the .o file. This allows us to leave out the implicit
# rule for interface files ("%.hi: %.o").
#--------------------------------------------------------------------------
#--------------------------------------------------------------------------
# Support DESTDIR
#--------------------------------------------------------------------------
# append a trailing "/" if DESTDIR is not empty
ifneq ($(DESTDIR),)
DESTDIR=$(patsubst %/,%,$(DESTDIR))/
endif
#--------------------------------------------------------------------------
# Functions on files and directories
#--------------------------------------------------------------------------
# create derived file from base name
# usage: $(call make-hs,<source root path>,<file base names>)
# usage: $(call make-objs,<object root path>,<file base names>)
make-hs =$(patsubst %,$(1)/%.hs,$(2))
make-objs =$(patsubst %,$(1)/%.o,$(2))
make-deps =$(patsubst %,$(1)/%.d,$(2))
make-his =$(patsubst %,$(1)/%.hi,$(2))
# usage: $(call run-silent,<command>)
run-silent =$(1) 1> /dev/null 2> /dev/null
run-with-echo =echo "$(1)" && $(1)
# usage: $(call relative-to,<root-dir>,<relative files>)
relative-to =$(patsubst $(1)/%,%,$(2))
# usage: $(call relative-fromto,<old-root-dir>,<new-root-dir>,<files>)
relative-fromto =$(patsubst $(1)%,$(2)%,$(3))
# get directories of files (using 'sort' to get rid of duplicates)
dirs-of-files =$(sort $(foreach file,$(1),$(dir $(file))))
# usage: $(call ensure-dir,<directory>)
# usage: $(call ensure-dirs-of-files,<files>)
ensure-dir =if test -d "$(1)" -o "$(1)" = "./"; then :; else $(MKDIR) $(1); fi
ensure-dirs =$(foreach dir,$(1),$(call ensure-dir,$(dir)) &&) :
ensure-dirs-of-files=$(call ensure-dirs,$(call dirs-of-files,$(1)))
# full-remove-dir
# safe-remove-dir
safe-remove-dir =if test -d $(1); then $(call run-with-echo,$(RMDIR) $(1)); fi
safe-remove-dir-contents = if test -d $(1); then $(call run-with-echo,$(RM) -r $(1)/*); fi
full-remove-dir =$(call safe-remove-dir-contents,$(1)); $(call safe-remove-dir,$(1))
# safe-move-file(<source>,<destination (directory)>)
# safe-remove-file(<file>)
safe-move-file =if test -f $(1); then $(call run-with-echo,$(MV) $(1) $(2)); fi
safe-remove-file=if test -f $(1); then $(call run-with-echo,$(RM) $(1)); fi
safe-remove-files=$(foreach file,$(1),$(call safe-remove-file,$(file)) &&) :
# silent-move-file
silent-move-file=if test -f $(1); then $(MV) $(1) $(2); fi
silent-remove-file=if test -f $(1); then $(RM) $(1); fi
#--------------------------------------------------------------------------
# C compilation
#--------------------------------------------------------------------------
# make-c-obj(<output .o>,<input .c>,<compile flags>)
make-c-obj =$(call run-with-echo,$(CXX) -c $(2) -o $(1) $(3))
# compile-c(<output .o>,<input .c>,<compile flags>)
compile-c =$(call make-c-obj,$(1),$(2),-MD $(3)) && \
$(call silent-move-file,$(notdir $(basename $(1))).d,$(dir $(1)))
#--------------------------------------------------------------------------
# Haskell compilation
#--------------------------------------------------------------------------
# silent-move-stubs(<output .o>,<input .c>)
silent-move-stubs =$(call silent-move-file,$(basename $(2))_stub.h,$(dir $(1))) && \
$(call silent-move-file,$(basename $(2))_stub.c,$(dir $(1)))
# make-hs-obj(<output .o>,<input .hs>,<compile flags>)
make-hs-obj =$(call run-with-echo,$(HC) -c $(2) -o $(1) -ohi $(basename $(1)).hi -odir $(dir $(1)) $(3))
# make-hs-deps(<output .o>,<input .hs>,<compile flags>)
make-hs-deps =$(HC) $(2) $(3) -M -optdep-f -optdep$(basename $(1)).d.in && \
sed -e 's|$(basename $(2))|$(basename $(1))|' -e 's|\.hi|\.o|g' $(basename $(1)).d.in > $(basename $(1)).d && \
$(call silent-remove-file,$(basename $(1)).d.in)
# compile-hs(<output .o>,<input .hs>,<compile flags>)
compile-hs =$(call make-hs-obj,$(1),$(2),$(3)) && \
$(call silent-move-stubs,$(1),$(2)) && \
$(call make-hs-deps,$(1),$(2),$(3))
#--------------------------------------------------------------------------
# Linking
#--------------------------------------------------------------------------
# make single-object file
# combine-objs(<output .o>,<input .o files>)
ifeq ($(TOOLKIT),mac)
combine-objs =$(LD) -x -r -o $(1) $(2)
else
combine-objs =$(LD) -r -o $(1) $(2)
endif
# create an archive
# make-archive(<archive>,<input .o files>)
make-archive =$(AR) -sr $(1) $(2)
# update the archive symbol index
# make-archive-index(<archive>)
make-archive-index=$(AR) -s $(1)
#--------------------------------------------------------------------------
# Installation
#--------------------------------------------------------------------------
# install files, keeping directory structure intact (that is why we use 'foreach').
# we circumvent a 'ld' bug on the mac by also re-indexing archives on installation
# usage: $(call install-files,<local dir>,<install dir>,<files>)
# usage: $(call uninstall-files,<local dir>,<install dir>,<files>)
install-file =echo "install: $(2)" && $(INSTALL) $(1) $(dir $(2)) \
$(if $(filter %.a,$(2)),&& $(call make-archive-index,$(basename $(2)).a))
install-dir =echo "install directory: $(1)" && $(INSTALLDIR) $(1)
install-filesx =$(foreach dir,$(call dirs-of-files,$(call relative-fromto,$(1),$(2),$(3))),$(call install-dir,$(dir)) &&) \
$(foreach file,$(3),$(call install-file,$(file),$(call relative-fromto,$(1),$(2),$(file))) &&) \
:
install-files =$(call install-filesx,$(patsubst %/,%,$(1)),$(DESTDIR)$(2),$(3))
uninstall-file =if test -f "$(1)"; then echo "uninstall: $(1)"; $(RM) $(1); fi
uninstall-dir =if test -d "$(2)" -a "$(2)" != "./"; then echo "uninstall directory: $(1)/$(2)" && $(call run-silent,$(RMDIR) -p $(2)); fi
# extremely baroque way of reversing a list of (at most 10) items
reverse10 =$(patsubst 9%,%,$(patsubst 8%,%,$(patsubst 7%,%,\
$(patsubst 6%,%,$(patsubst 5%,%,$(patsubst 4%,%,\
$(patsubst 3%,%,$(patsubst 2%,%,$(patsubst 1%,%,\
$(patsubst 0%,%,\
$(sort $(join $(wordlist 1,$(words $(1)),9 8 7 6 5 4 3 2 1 0),$(1)))\
))))))))))
uninstall-filesx=$(foreach file,$(2),$(call uninstall-file,$(file)) &&) \
$(CD) $(1) && \
$(foreach dir,$(call reverse10,$(call dirs-of-files,$(call relative-to,$(1),$(2)))),$(call uninstall-dir,$(1),$(dir)) &&) \
:
uninstall-files =$(call uninstall-filesx,$(2),$(call relative-fromto,$(patsubst %/,%,$(1)),$(DESTDIR)$(2),$(3)))
# install packages
# usage: $(call install-pkg,<install dir>,<package file>)
# usage: $(call uninstall-pkg,<package name>)
install-pkg=env wxhlibdir=$(1) $(HCPKG) -u -i $(2)
uninstall-pkg=if $(call run-silent,$(HCPKG) -s $(1)); then echo "unregister package: $(1)" && $(HCPKG) -r $(1); fi
#--------------------------------------------------------------------------
# Packaging
#--------------------------------------------------------------------------
# copy files.
# usage: cp-bindist<dirprefix,target-dir,source files>
# use -R switch to copy symbolic links literally instead of following the links.
# use -p to preserve file dates to avoid linker bug on macosX with .a files.
cp-echox =echo "copy $(1) to $(2)" && $(CP) -p -R $(1) $(2) && :
cp-echo =$(foreach file,$(wildcard $(1)),$(call cp-echox,$(file),$(2)))
cp-fromto =$(call ensure-dirs-of-files,$(call relative-fromto,$(1),$(2),$(3))) && \
$(foreach file,$(3),$(call cp-echo,$(file),$(dir $(call relative-fromto,$(1),$(2),$(file)))) && ) :
cp-bindist =$(call cp-fromto,$(patsubst %/,%,$(1)),$(patsubst %/,%,$(2)),$(3))
# usage: $(call cp-relative,<out topdir>,<local files>)
cp-relative =$(call ensure-dirs-of-files,$(patsubst %,$(1)/%,$(2))) && \
$(foreach file,$(2),$(call cp-echox,$(file),$(1)/$(patsubst %/,%,$(dir $(file)))) && ):
cp-srcdist =$(call cp-relative,$(TOPDIR)/$(SRCDIST-SRCDIR),$(1))
cp-docdist =$(CD) $(1) && $(call cp-relative,$(TOPDIR)/$(DOCDIST-SRCDIR),$(patsubst $(1)/%,%,$(2)))
# zip commands
zip-add =echo zipping: $(1); $(ZIP) -y -9 $(TOPDIR)/$(1) $(2)
zip-add-rec =echo zipping: $(1); $(ZIP) -r -y -9 $(TOPDIR)/$(1) $(2)