1 #=========================================================================
2 # Toplevel Makefile for the Modular C++ Build System
3 #=========================================================================
4 # Please read the documenation in 'mcppbs-doc.txt' for more details on
5 # how the Modular C++ Build System works. For most projects, a developer
6 # will not need to make any changes to this makefile. The key targets
9 # - default : build all libraries and programs
10 # - check : build and run all unit tests
11 # - install : install headers, project library, and some programs
12 # - clean : remove all generated content (except autoconf files)
13 # - dist : make a source tarball
14 # - distcheck : make a source tarball, untar it, check it, clean it
15 # - distclean : remove everything
18 #-------------------------------------------------------------------------
20 #-------------------------------------------------------------------------
22 # Remove all default implicit rules since they can cause subtle bugs
23 # and they just make things run slower
31 # Default is to build the prereqs of the all target (defined at bottom)
35 project_name
:= @PACKAGE_TARNAME@
37 scripts_dir
:= $(src_dir
)/scripts
39 # If the version information is not in the configure script, then we
40 # assume that we are in a working directory. We use the vcs-version.sh
41 # script in the scripts directory to generate an appropriate version
42 # string. Currently the way things are setup we have to run this script
43 # everytime we run make so the script needs to be as fast as possible.
45 ifeq (@PACKAGE_VERSION@
,?
)
46 project_ver
:=$(shell $(scripts_dir
)/vcs-version.sh
$(src_dir
))
48 project_ver
:=@PACKAGE_VERSION@
51 # Installation directories
54 enable_stow
:= @enable_stow@
56 ifeq ($(enable_stow
),yes
)
57 stow_pkg_dir
:= $(prefix)/pkgs
58 DESTDIR ?
= $(stow_pkg_dir
)/$(project_name
)-$(project_ver
)
63 install_hdrs_dir
:= $(DESTDIR
)/include/$(project_name
)
64 install_libs_dir
:= $(DESTDIR
)/lib
/$(project_name
)
65 install_exes_dir
:= $(DESTDIR
)/bin
67 #-------------------------------------------------------------------------
69 #-------------------------------------------------------------------------
71 sprojs
:= @subprojects@
72 sprojs_enabled
:= @subprojects_enabled@
74 sprojs_include
:= -I.
$(addprefix -I
$(src_dir
)/, $(sprojs_enabled
))
75 VPATH
:= $(addprefix $(src_dir
)/, $(sprojs_enabled
))
77 #-------------------------------------------------------------------------
79 #-------------------------------------------------------------------------
82 # - CPPFLAGS : flags for the preprocessor (eg. -I,-D)
83 # - CXXFLAGS : flags for C++ compiler (eg. -Wall,-g,-O3)
86 CPPFLAGS
:= @CPPFLAGS@
87 CXXFLAGS
:= @CXXFLAGS@
88 COMPILE
:= $(CXX
) -MMD
-MP
$(CPPFLAGS
) $(CXXFLAGS
) \
91 # - LDFLAGS : Flags for the linker (eg. -L)
92 # - LIBS : Library flags (eg. -l)
97 LINK
:= $(LD
) $(LDFLAGS
)
107 RUNFLAGS
:= @RUNFLAGS@
111 MKINSTALLDIRS
:= $(scripts_dir
)/mk-install-dirs.sh
113 INSTALL_HDR
:= $(INSTALL
) -m
444
114 INSTALL_LIB
:= $(INSTALL
) -m
644
115 INSTALL_EXE
:= $(INSTALL
) -m
555
118 #-------------------------------------------------------------------------
119 # Include subproject makefile fragments
120 #-------------------------------------------------------------------------
122 sprojs_mk
= $(addsuffix .mk
, $(sprojs_enabled
))
124 -include $(sprojs_mk
)
126 dist_junk
+= $(sprojs_mk
)
128 #-------------------------------------------------------------------------
129 # Reverse list helper function
130 #-------------------------------------------------------------------------
131 # This function is used by the subproject template to reverse the list
132 # of dependencies. It uses recursion to perform the reversal.
135 # $(1) : space separated input list
136 # retval : input list in reverse order
139 reverse_list
= $(call reverse_list_h
,$(1),)
140 define reverse_list_h
141 $(if
$(strip $(1)), \
142 $(call reverse_list_h
, \
143 $(wordlist
2,$(words $(1)),$(1)), \
144 $(firstword $(1)) $(2)), \
148 #-------------------------------------------------------------------------
149 # Template for per subproject rules
150 #-------------------------------------------------------------------------
151 # The template is instantiated for each of the subprojects. It relies on
152 # subprojects defining a certain set of make variables which are all
153 # prefixed with the subproject name. Since subproject names can have
154 # dashes in them (and the make variables are assumed to only use
155 # underscores) the template takes two arguments - one with the regular
156 # subproject name and one with dashes replaced with underscores.
159 # $(1) : real subproject name (ie with dashes)
160 # $(2) : normalized subproject name (ie dashes replaced with underscores)
163 define subproject_template
165 # In some (rare) cases, a subproject might not have any actual object
166 # files. It might only include header files or program sources. To keep
167 # things consistent we still want a library for this subproject, so in
168 # this spectial case we create a dummy source file and thus the build
169 # system will create a library for this subproject with just the
170 # corresponding dummy object file.
172 ifeq ($$(strip $$($(2)_srcs
)),)
173 $(2)_srcs
+= _
$(1).
cc
174 $(2)_junk
+= _
$(1).
cc
178 echo
"int _$(2)( int arg ) { return arg; }" > $$@
180 # Build the object files for this subproject
182 $(2)_objs
:= $$(patsubst %.
cc, %.o
, $$($(2)_srcs
))
183 $(2)_deps
:= $$(patsubst %.o
, %.d
, $$($(2)_objs
))
184 $$($(2)_objs
) : %.o
: %.
cc
187 $(2)_junk
+= $$($(2)_objs
) $$($(2)_deps
)
189 # Build a library for this subproject
191 lib
$(1).a
: $$($(2)_objs
)
195 $(2)_junk
+= lib
$(1).a
197 # Reverse the dependency list so that a given subproject only depends on
198 # subprojects listed to its right. This is the correct order for linking
199 # the list of subproject libraries.
201 $(2)_reverse_deps
:= $$(call reverse_list
,$$($(2)_subproject_deps
))
205 $(2)_test_objs
:= $$(patsubst %.
cc, %.o
, $$($(2)_test_srcs
))
206 $(2)_test_deps
:= $$(patsubst %.o
, %.d
, $$($(2)_test_objs
))
207 $(2)_test_exes
:= $$(patsubst %.t.
cc, %-utst
, $$($(2)_test_srcs
))
208 $(2)_test_outs
:= $$(patsubst %, %.out
, $$($(2)_test_exes
))
209 $(2)_test_libs
:= $(1) $$($(2)_reverse_deps
) utst
210 $(2)_test_libnames
:= $$(patsubst %, lib
%.a
, $$($(2)_test_libs
))
211 $(2)_test_libarg
:= -L.
$$(patsubst %, -l
%, $$($(2)_test_libs
))
213 $$($(2)_test_objs
) : %.o
: %.
cc
216 $$($(2)_test_exes
) : %-utst
: %.t.o
$$($(2)_test_libnames
)
217 $(LINK
) -o
$$@
$$< $$($(2)_test_libarg
) $(LIBS
)
219 $(2)_deps
+= $$($(2)_test_deps
)
221 $$($(2)_test_objs
) $$($(2)_test_deps
) \
222 $$($(2)_test_exes
) *.junk-dat
226 $$($(2)_test_outs
) : %.out
: %
227 $(RUN
) $(RUNFLAGS
) .
/$$< default | tee
$$@
229 $(2)_junk
+= $$($(2)_test_outs
)
233 $(2)_prog_objs
:= $$(patsubst %.
cc, %.o
, $$($(2)_prog_srcs
))
234 $(2)_prog_deps
:= $$(patsubst %.o
, %.d
, $$($(2)_prog_objs
))
235 $(2)_prog_exes
:= $$(patsubst %.
cc, %, $$($(2)_prog_srcs
))
236 $(2)_prog_libs
:= $(1) $$($(2)_reverse_deps
)
237 $(2)_prog_libnames
:= $$(patsubst %, lib
%.a
, $$($(2)_prog_libs
))
238 $(2)_prog_libarg
:= -L.
$$(patsubst %, -l
%, $$($(2)_prog_libs
))
240 $$($(2)_prog_objs
) : %.o
: %.
cc
243 $$($(2)_prog_exes
) : % : %.o
$$($(2)_prog_libnames
)
244 $(LINK
) -o
$$@
$$< $$($(2)_prog_libarg
) $(LIBS
)
246 $(2)_deps
+= $$($(2)_prog_deps
)
247 $(2)_junk
+= $$($(2)_prog_objs
) $$($(2)_prog_deps
) $$($(2)_prog_exes
)
249 # Build programs which will be installed
251 $(2)_install_prog_objs
:= $$(patsubst %.
cc, %.o
, $$($(2)_install_prog_srcs
))
252 $(2)_install_prog_deps
:= $$(patsubst %.o
, %.d
, $$($(2)_install_prog_objs
))
253 $(2)_install_prog_exes
:= $$(patsubst %.
cc, %, $$($(2)_install_prog_srcs
))
255 $$($(2)_install_prog_objs
) : %.o
: %.
cc
258 $$($(2)_install_prog_exes
) : % : %.o
$$($(2)_prog_libnames
)
259 $(LINK
) -o
$$@
$$< $$($(2)_prog_libarg
) $(LIBS
)
261 $(2)_deps
+= $$($(2)_install_prog_deps
)
263 $$($(2)_install_prog_objs
) $$($(2)_install_prog_deps
) \
264 $$($(2)_install_prog_exes
)
266 # Subproject specific targets
268 all-
$(1) : lib
$(1).a
$$($(2)_install_prog_exes
)
270 check-
$(1) : $$($(2)_test_outs
)
271 echo
; grep
-h
-e
'Unit Tests' -e
'FAILED' -e
'Segementation' $$^
; echo
276 .PHONY
: all-
$(1) check-
$(1) clean-
$(1)
278 # Update running variables
281 objs
+= $$($(2)_objs
)
282 srcs
+= $$(addprefix $(src_dir
)/$(1)/, $$($(2)_srcs
))
283 hdrs
+= $$(addprefix $(src_dir
)/$(1)/, $$($(2)_hdrs
))
284 junk
+= $$($(2)_junk
)
285 deps
+= $$($(2)_deps
)
287 test_outs
+= $$($(2)_test_outs
)
289 install_hdrs
+= $$(addprefix $(src_dir
)/$(1)/, $$($(2)_hdrs
))
290 install_libs
+= lib
$(1).a
291 install_exes
+= $$($(2)_install_prog_exes
)
295 # Iterate over the subprojects and call the template for each one
297 $(foreach sproj
,$(sprojs_enabled
), \
298 $(eval
$(call subproject_template
,$(sproj
),$(subst -,_
,$(sproj
)))))
300 #-------------------------------------------------------------------------
301 # Autodependency files
302 #-------------------------------------------------------------------------
309 #-------------------------------------------------------------------------
311 #-------------------------------------------------------------------------
314 echo
; grep
-h
-e
'Unit Tests' -e
'FAILED' -e
'Segementation' $^
; echo
318 #-------------------------------------------------------------------------
320 #-------------------------------------------------------------------------
322 install-hdrs
: $(install_hdrs
)
323 $(MKINSTALLDIRS
) $(install_hdrs_dir
)
324 for file in
$(install_hdrs
); \
326 $(INSTALL_HDR
) $$file $(install_hdrs_dir
); \
329 install-libs
: $(install_libs
)
330 $(MKINSTALLDIRS
) $(install_libs_dir
)
331 for file in
$(install_libs
); \
333 $(INSTALL_LIB
) $$file $(install_libs_dir
); \
336 install-exes
: $(install_exes
)
337 $(MKINSTALLDIRS
) $(install_exes_dir
)
338 for file in
$(install_exes
); \
340 $(INSTALL_EXE
) $$file $(install_exes_dir
); \
343 install : install-hdrs install-libs install-exes
344 ifeq ($(enable_stow
),yes
)
345 $(MKINSTALLDIRS
) $(stow_pkg_dir
)
346 cd
$(stow_pkg_dir
) && \
347 $(STOW
) --delete
$(project_name
)-* && \
348 $(STOW
) $(project_name
)-$(project_ver
)
351 .PHONY
: install install-hdrs install-libs install-exes
353 #-------------------------------------------------------------------------
354 # Regenerate configure information
355 #-------------------------------------------------------------------------
358 $(src_dir
)/configure.ac \
359 $(src_dir
)/aclocal.m4 \
360 $(join $(addprefix $(src_dir
)/, $(sprojs_enabled
)), \
361 $(patsubst %, /%.ac
, $(sprojs_enabled
)))
363 $(src_dir
)/configure
: $(configure_prereq
)
364 cd
$(src_dir
) && autoconf
&& autoheader
366 config.status
: $(src_dir
)/configure
367 .
/config.status
--recheck
370 $(join $(addprefix $(src_dir
)/, $(sprojs_enabled
)), \
371 $(patsubst %, /%.mk.in
, $(sprojs_enabled
)))
373 Makefile
: $(src_dir
)/Makefile.in
$(sprojs_mk_in
) config.status
376 dist_junk
+= config.status config.h Makefile config.log
378 #-------------------------------------------------------------------------
380 #-------------------------------------------------------------------------
381 # The distribution tarball is named project-ver.tar.gz and it includes
382 # both enabled and disabled subprojects.
396 dist_dir
:= $(project_name
)-$(project_ver
)
397 dist_tgz
:= $(project_name
)-$(project_ver
).
tar.gz
399 # Notice that when we make the distribution we rewrite the configure.ac
400 # script with the current version and we rerun autoconf in the new
401 # source directory so that the distribution will have the proper version
402 # information. We also rewrite the "Version : " line in the README.
407 tar -C
$(src_dir
) -cf
- $(dist_files
) |
tar -C
$(dist_dir
) -xpf
-
408 sed
-i.bak
's/^\(# Version :\).*/\1 $(project_ver)/' $(dist_dir
)/README
409 sed
-i.bak
's/\( proj_version,\).*/\1 [$(project_ver)])/' $(dist_dir
)/configure.ac
411 autoconf
&& autoheader
&& \
412 rm -rf autom4te.cache configure.ac.bak README.bak
413 tar -czvf
$(dist_tgz
) $(dist_dir
)
416 # You can use the distcheck target to try untarring the distribution and
417 # then running configure, make, make check, and make distclean. A
418 # "directory is not empty" error means distclean is not removing
423 tar -xzvf
$(dist_tgz
)
424 mkdir
-p
$(dist_dir
)/build
425 cd
$(dist_dir
)/build
; ..
/configure
; make
; make
check; make
distclean
428 junk
+= $(project_name
)-*.
tar.gz
430 .PHONY
: dist distcheck
432 #-------------------------------------------------------------------------
434 #-------------------------------------------------------------------------
436 all : $(install_hdrs
) $(install_libs
) $(install_exes
)
439 #-------------------------------------------------------------------------
441 #-------------------------------------------------------------------------
442 # This handy rule will display the contents of any make variable by
443 # using the target debug-<varname>. So for example, make debug-junk will
444 # display the contents of the junk variable.
449 #-------------------------------------------------------------------------
451 #-------------------------------------------------------------------------
454 rm -rf
*~ \
#* $(junk)
457 rm -rf
*~ \
#* $(junk) $(dist_junk)
459 .PHONY
: clean distclean