• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# -*- mode: makefile -*-
2#
3# Copyright (c) 2012, Joyent, Inc. All rights reserved.
4#
5# Makefile.targ: common targets.
6#
7# NOTE: This makefile comes from the "eng" repo. It's designed to be dropped
8# into other repos as-is without requiring any modifications. If you find
9# yourself changing this file, you should instead update the original copy in
10# eng.git and then update your repo to use the new version.
11#
12# This Makefile defines several useful targets and rules. You can use it by
13# including it from a Makefile that specifies some of the variables below.
14#
15# Targets defined in this Makefile:
16#
17#	check	Checks JavaScript files for lint and style
18#		Checks bash scripts for syntax
19#		Checks SMF manifests for validity against the SMF DTD
20#
21#	clean	Removes built files
22#
23#	docs	Builds restdown documentation in docs/
24#
25#	prepush	Depends on "check" and "test"
26#
27#	test	Does nothing (you should override this)
28#
29#	xref	Generates cscope (source cross-reference index)
30#
31# For details on what these targets are supposed to do, see the Joyent
32# Engineering Guide.
33#
34# To make use of these targets, you'll need to set some of these variables. Any
35# variables left unset will simply not be used.
36#
37#	BASH_FILES	Bash scripts to check for syntax
38#			(paths relative to top-level Makefile)
39#
40#	CLEAN_FILES	Files to remove as part of the "clean" target.  Note
41#			that files generated by targets in this Makefile are
42#			automatically included in CLEAN_FILES.  These include
43#			restdown-generated HTML and JSON files.
44#
45#	DOC_FILES	Restdown (documentation source) files. These are
46#			assumed to be contained in "docs/", and must NOT
47#			contain the "docs/" prefix.
48#
49#	JSL_CONF_NODE	Specify JavaScriptLint configuration files
50#	JSL_CONF_WEB	(paths relative to top-level Makefile)
51#
52#			Node.js and Web configuration files are separate
53#			because you'll usually want different global variable
54#			configurations.  If no file is specified, none is given
55#			to jsl, which causes it to use a default configuration,
56#			which probably isn't what you want.
57#
58#	JSL_FILES_NODE	JavaScript files to check with Node config file.
59#	JSL_FILES_WEB	JavaScript files to check with Web config file.
60#
61# You can also override these variables:
62#
63#	BASH		Path to bash (default: bash)
64#
65#	CSCOPE_DIRS	Directories to search for source files for the cscope
66#			index. (default: ".")
67#
68#	JSL		Path to JavaScriptLint (default: "jsl")
69#
70#	JSL_FLAGS_NODE	Additional flags to pass through to JSL
71#	JSL_FLAGS_WEB
72#	JSL_FLAGS
73#
74#	JSSTYLE		Path to jsstyle (default: jsstyle)
75#
76#	JSSTYLE_FLAGS	Additional flags to pass through to jsstyle
77#
78
79#
80# Defaults for the various tools we use.
81#
82BASH		?= bash
83BASHSTYLE	?= tools/bashstyle
84CP		?= cp
85CSCOPE		?= cscope
86CSCOPE_DIRS	?= .
87JSL		?= jsl
88JSSTYLE		?= jsstyle
89MKDIR		?= mkdir -p
90MV		?= mv
91RESTDOWN_FLAGS	?=
92RMTREE		?= rm -rf
93JSL_FLAGS  	?= --nologo --nosummary
94
95ifeq ($(shell uname -s),SunOS)
96	TAR	?= gtar
97else
98	TAR	?= tar
99endif
100
101
102#
103# Defaults for other fixed values.
104#
105BUILD		= build
106DISTCLEAN_FILES += $(BUILD)
107DOC_BUILD	= $(BUILD)/docs/public
108
109#
110# Configure JSL_FLAGS_{NODE,WEB} based on JSL_CONF_{NODE,WEB}.
111#
112ifneq ($(origin JSL_CONF_NODE), undefined)
113	JSL_FLAGS_NODE += --conf=$(JSL_CONF_NODE)
114endif
115
116ifneq ($(origin JSL_CONF_WEB), undefined)
117	JSL_FLAGS_WEB += --conf=$(JSL_CONF_WEB)
118endif
119
120#
121# Targets. For descriptions on what these are supposed to do, see the
122# Joyent Engineering Guide.
123#
124
125#
126# Instruct make to keep around temporary files. We have rules below that
127# automatically update git submodules as needed, but they employ a deps/*/.git
128# temporary file. Without this directive, make tries to remove these .git
129# directories after the build has completed.
130#
131.SECONDARY: $($(wildcard deps/*):%=%/.git)
132
133#
134# This rule enables other rules that use files from a git submodule to have
135# those files depend on deps/module/.git and have "make" automatically check
136# out the submodule as needed.
137#
138deps/%/.git:
139	git submodule update --init deps/$*
140
141#
142# These recipes make heavy use of dynamically-created phony targets. The parent
143# Makefile defines a list of input files like BASH_FILES. We then say that each
144# of these files depends on a fake target called filename.bashchk, and then we
145# define a pattern rule for those targets that runs bash in check-syntax-only
146# mode. This mechanism has the nice properties that if you specify zero files,
147# the rule becomes a noop (unlike a single rule to check all bash files, which
148# would invoke bash with zero files), and you can check individual files from
149# the command line with "make filename.bashchk".
150#
151.PHONY: check-bash
152check-bash: $(BASH_FILES:%=%.bashchk) $(BASH_FILES:%=%.bashstyle)
153
154%.bashchk: %
155	$(BASH) -n $^
156
157%.bashstyle: %
158	$(BASHSTYLE) $^
159
160.PHONY: check-jsl check-jsl-node check-jsl-web
161check-jsl: check-jsl-node check-jsl-web
162
163check-jsl-node: $(JSL_FILES_NODE:%=%.jslnodechk)
164
165check-jsl-web: $(JSL_FILES_WEB:%=%.jslwebchk)
166
167%.jslnodechk: % $(JSL_EXEC)
168	$(JSL) $(JSL_FLAGS) $(JSL_FLAGS_NODE) $<
169
170%.jslwebchk: % $(JSL_EXEC)
171	$(JSL) $(JSL_FLAGS) $(JSL_FLAGS_WEB) $<
172
173.PHONY: check-jsstyle
174check-jsstyle: $(JSSTYLE_FILES:%=%.jsstylechk)
175
176%.jsstylechk: % $(JSSTYLE_EXEC)
177	$(JSSTYLE) $(JSSTYLE_FLAGS) $<
178
179.PHONY: check
180check: check-jsl check-jsstyle check-bash
181	@echo check ok
182
183.PHONY: clean
184clean::
185	-$(RMTREE) $(CLEAN_FILES)
186
187.PHONY: distclean
188distclean:: clean
189	-$(RMTREE) $(DISTCLEAN_FILES)
190
191CSCOPE_FILES = cscope.in.out cscope.out cscope.po.out
192CLEAN_FILES += $(CSCOPE_FILES)
193
194.PHONY: xref
195xref: cscope.files
196	$(CSCOPE) -bqR
197
198.PHONY: cscope.files
199cscope.files:
200	find $(CSCOPE_DIRS) -name '*.c' -o -name '*.h' -o -name '*.cc' \
201	    -o -name '*.js' -o -name '*.s' -o -name '*.cpp' > $@
202
203#
204# The "docs" target is complicated because we do several things here:
205#
206#    (1) Use restdown to build HTML and JSON files from each of DOC_FILES.
207#
208#    (2) Copy these files into $(DOC_BUILD) (build/docs/public), which
209#        functions as a complete copy of the documentation that could be
210#        mirrored or served over HTTP.
211#
212#    (3) Then copy any directories and media from docs/media into
213#        $(DOC_BUILD)/media. This allows projects to include their own media,
214#        including files that will override same-named files provided by
215#        restdown.
216#
217# Step (3) is the surprisingly complex part: in order to do this, we need to
218# identify the subdirectories in docs/media, recreate them in
219# $(DOC_BUILD)/media, then do the same with the files.
220#
221DOC_MEDIA_DIRS := $(shell find docs/media -type d 2>/dev/null | grep -v "^docs/media$$")
222DOC_MEDIA_DIRS := $(DOC_MEDIA_DIRS:docs/media/%=%)
223DOC_MEDIA_DIRS_BUILD := $(DOC_MEDIA_DIRS:%=$(DOC_BUILD)/media/%)
224
225DOC_MEDIA_FILES := $(shell find docs/media -type f 2>/dev/null)
226DOC_MEDIA_FILES := $(DOC_MEDIA_FILES:docs/media/%=%)
227DOC_MEDIA_FILES_BUILD := $(DOC_MEDIA_FILES:%=$(DOC_BUILD)/media/%)
228
229#
230# Like the other targets, "docs" just depends on the final files we want to
231# create in $(DOC_BUILD), leveraging other targets and recipes to define how
232# to get there.
233#
234.PHONY: docs
235docs:							\
236    $(DOC_FILES:%.restdown=$(DOC_BUILD)/%.html)		\
237    $(DOC_FILES:%.restdown=$(DOC_BUILD)/%.json)		\
238    $(DOC_MEDIA_FILES_BUILD)
239
240#
241# We keep the intermediate files so that the next build can see whether the
242# files in DOC_BUILD are up to date.
243#
244.PRECIOUS:					\
245    $(DOC_FILES:%.restdown=docs/%.html)		\
246    $(DOC_FILES:%.restdown=docs/%json)
247
248#
249# We do clean those intermediate files, as well as all of DOC_BUILD.
250#
251CLEAN_FILES +=					\
252    $(DOC_BUILD)				\
253    $(DOC_FILES:%.restdown=docs/%.html)		\
254    $(DOC_FILES:%.restdown=docs/%.json)
255
256#
257# Before installing the files, we must make sure the directories exist. The |
258# syntax tells make that the dependency need only exist, not be up to date.
259# Otherwise, it might try to rebuild spuriously because the directory itself
260# appears out of date.
261#
262$(DOC_MEDIA_FILES_BUILD): | $(DOC_MEDIA_DIRS_BUILD)
263
264$(DOC_BUILD)/%: docs/% | $(DOC_BUILD)
265	$(CP) $< $@
266
267docs/%.json docs/%.html: docs/%.restdown | $(DOC_BUILD) $(RESTDOWN_EXEC)
268	$(RESTDOWN) $(RESTDOWN_FLAGS) -m $(DOC_BUILD) $<
269
270$(DOC_BUILD):
271	$(MKDIR) $@
272
273$(DOC_MEDIA_DIRS_BUILD):
274	$(MKDIR) $@
275
276#
277# The default "test" target does nothing. This should usually be overridden by
278# the parent Makefile. It's included here so we can define "prepush" without
279# requiring the repo to define "test".
280#
281.PHONY: test
282test:
283
284.PHONY: prepush
285prepush: check test
286