Makefile.targ 8.19 KB
Newer Older
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 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
# -*- mode: makefile -*-
#
# Copyright (c) 2012, Joyent, Inc. All rights reserved.
#
# Makefile.targ: common targets.
#
# NOTE: This makefile comes from the "eng" repo. It's designed to be dropped
# into other repos as-is without requiring any modifications. If you find
# yourself changing this file, you should instead update the original copy in
# eng.git and then update your repo to use the new version.
#
# This Makefile defines several useful targets and rules. You can use it by
# including it from a Makefile that specifies some of the variables below.
#
# Targets defined in this Makefile:
#
#	check	Checks JavaScript files for lint and style
#		Checks bash scripts for syntax
#		Checks SMF manifests for validity against the SMF DTD
#
#	clean	Removes built files
#
#	docs	Builds restdown documentation in docs/
#
#	prepush	Depends on "check" and "test"
#
#	test	Does nothing (you should override this)
#
#	xref	Generates cscope (source cross-reference index)
#
# For details on what these targets are supposed to do, see the Joyent
# Engineering Guide.
#
# To make use of these targets, you'll need to set some of these variables. Any
# variables left unset will simply not be used.
#
#	BASH_FILES	Bash scripts to check for syntax
#			(paths relative to top-level Makefile)
#
#	CLEAN_FILES	Files to remove as part of the "clean" target.  Note
#			that files generated by targets in this Makefile are
#			automatically included in CLEAN_FILES.  These include
#			restdown-generated HTML and JSON files.
#
#	DOC_FILES	Restdown (documentation source) files. These are
#			assumed to be contained in "docs/", and must NOT
#			contain the "docs/" prefix.
#
#	JSL_CONF_NODE	Specify JavaScriptLint configuration files
#	JSL_CONF_WEB	(paths relative to top-level Makefile)
#
#			Node.js and Web configuration files are separate
#			because you'll usually want different global variable
#			configurations.  If no file is specified, none is given
#			to jsl, which causes it to use a default configuration,
#			which probably isn't what you want.
#
#	JSL_FILES_NODE	JavaScript files to check with Node config file.
#	JSL_FILES_WEB	JavaScript files to check with Web config file.
#
# You can also override these variables:
#
#	BASH		Path to bash (default: bash)
#
#	CSCOPE_DIRS	Directories to search for source files for the cscope
#			index. (default: ".")
#
#	JSL		Path to JavaScriptLint (default: "jsl")
#
#	JSL_FLAGS_NODE	Additional flags to pass through to JSL
#	JSL_FLAGS_WEB
#	JSL_FLAGS
#
#	JSSTYLE		Path to jsstyle (default: jsstyle)
#
#	JSSTYLE_FLAGS	Additional flags to pass through to jsstyle
#

#
# Defaults for the various tools we use.
#
BASH		?= bash
BASHSTYLE	?= tools/bashstyle
CP		?= cp
CSCOPE		?= cscope
CSCOPE_DIRS	?= .
JSL		?= jsl
JSSTYLE		?= jsstyle
MKDIR		?= mkdir -p
MV		?= mv
RESTDOWN_FLAGS	?=
RMTREE		?= rm -rf
JSL_FLAGS  	?= --nologo --nosummary

ifeq ($(shell uname -s),SunOS)
	TAR	?= gtar
else
	TAR	?= tar
endif


#
# Defaults for other fixed values.
#
BUILD		= build
DISTCLEAN_FILES += $(BUILD)
DOC_BUILD	= $(BUILD)/docs/public

#
# Configure JSL_FLAGS_{NODE,WEB} based on JSL_CONF_{NODE,WEB}.
#
ifneq ($(origin JSL_CONF_NODE), undefined)
	JSL_FLAGS_NODE += --conf=$(JSL_CONF_NODE)
endif

ifneq ($(origin JSL_CONF_WEB), undefined)
	JSL_FLAGS_WEB += --conf=$(JSL_CONF_WEB)
endif

#
# Targets. For descriptions on what these are supposed to do, see the
# Joyent Engineering Guide.
#

#
# Instruct make to keep around temporary files. We have rules below that
# automatically update git submodules as needed, but they employ a deps/*/.git
# temporary file. Without this directive, make tries to remove these .git
# directories after the build has completed.
#
.SECONDARY: $($(wildcard deps/*):%=%/.git)

#
# This rule enables other rules that use files from a git submodule to have
# those files depend on deps/module/.git and have "make" automatically check
# out the submodule as needed.
#
deps/%/.git:
	git submodule update --init deps/$*

#
# These recipes make heavy use of dynamically-created phony targets. The parent
# Makefile defines a list of input files like BASH_FILES. We then say that each
# of these files depends on a fake target called filename.bashchk, and then we
# define a pattern rule for those targets that runs bash in check-syntax-only
# mode. This mechanism has the nice properties that if you specify zero files,
# the rule becomes a noop (unlike a single rule to check all bash files, which
# would invoke bash with zero files), and you can check individual files from
# the command line with "make filename.bashchk".
#
.PHONY: check-bash
check-bash: $(BASH_FILES:%=%.bashchk) $(BASH_FILES:%=%.bashstyle)

%.bashchk: %
	$(BASH) -n $^

%.bashstyle: %
	$(BASHSTYLE) $^

.PHONY: check-jsl check-jsl-node check-jsl-web
check-jsl: check-jsl-node check-jsl-web

check-jsl-node: $(JSL_FILES_NODE:%=%.jslnodechk)

check-jsl-web: $(JSL_FILES_WEB:%=%.jslwebchk)

%.jslnodechk: % $(JSL_EXEC)
	$(JSL) $(JSL_FLAGS) $(JSL_FLAGS_NODE) $<

%.jslwebchk: % $(JSL_EXEC)
	$(JSL) $(JSL_FLAGS) $(JSL_FLAGS_WEB) $<

.PHONY: check-jsstyle
check-jsstyle: $(JSSTYLE_FILES:%=%.jsstylechk)

%.jsstylechk: % $(JSSTYLE_EXEC)
	$(JSSTYLE) $(JSSTYLE_FLAGS) $<

.PHONY: check
check: check-jsl check-jsstyle check-bash
	@echo check ok

.PHONY: clean
clean::
	-$(RMTREE) $(CLEAN_FILES)

.PHONY: distclean
distclean:: clean
	-$(RMTREE) $(DISTCLEAN_FILES)

CSCOPE_FILES = cscope.in.out cscope.out cscope.po.out
CLEAN_FILES += $(CSCOPE_FILES)

.PHONY: xref
xref: cscope.files
	$(CSCOPE) -bqR

.PHONY: cscope.files
cscope.files:
	find $(CSCOPE_DIRS) -name '*.c' -o -name '*.h' -o -name '*.cc' \
	    -o -name '*.js' -o -name '*.s' -o -name '*.cpp' > $@

#
# The "docs" target is complicated because we do several things here:
#
#    (1) Use restdown to build HTML and JSON files from each of DOC_FILES.
#
#    (2) Copy these files into $(DOC_BUILD) (build/docs/public), which
#        functions as a complete copy of the documentation that could be
#        mirrored or served over HTTP.
#
#    (3) Then copy any directories and media from docs/media into
#        $(DOC_BUILD)/media. This allows projects to include their own media,
#        including files that will override same-named files provided by
#        restdown.
#
# Step (3) is the surprisingly complex part: in order to do this, we need to
# identify the subdirectories in docs/media, recreate them in
# $(DOC_BUILD)/media, then do the same with the files.
#
DOC_MEDIA_DIRS := $(shell find docs/media -type d 2>/dev/null | grep -v "^docs/media$$")
DOC_MEDIA_DIRS := $(DOC_MEDIA_DIRS:docs/media/%=%)
DOC_MEDIA_DIRS_BUILD := $(DOC_MEDIA_DIRS:%=$(DOC_BUILD)/media/%)

DOC_MEDIA_FILES := $(shell find docs/media -type f 2>/dev/null)
DOC_MEDIA_FILES := $(DOC_MEDIA_FILES:docs/media/%=%)
DOC_MEDIA_FILES_BUILD := $(DOC_MEDIA_FILES:%=$(DOC_BUILD)/media/%)

#
# Like the other targets, "docs" just depends on the final files we want to
# create in $(DOC_BUILD), leveraging other targets and recipes to define how
# to get there.
#
.PHONY: docs
docs:							\
    $(DOC_FILES:%.restdown=$(DOC_BUILD)/%.html)		\
    $(DOC_FILES:%.restdown=$(DOC_BUILD)/%.json)		\
    $(DOC_MEDIA_FILES_BUILD)

#
# We keep the intermediate files so that the next build can see whether the
# files in DOC_BUILD are up to date.
#
.PRECIOUS:					\
    $(DOC_FILES:%.restdown=docs/%.html)		\
    $(DOC_FILES:%.restdown=docs/%json)

#
# We do clean those intermediate files, as well as all of DOC_BUILD.
#
CLEAN_FILES +=					\
    $(DOC_BUILD)				\
    $(DOC_FILES:%.restdown=docs/%.html)		\
    $(DOC_FILES:%.restdown=docs/%.json)

#
# Before installing the files, we must make sure the directories exist. The |
# syntax tells make that the dependency need only exist, not be up to date.
# Otherwise, it might try to rebuild spuriously because the directory itself
# appears out of date.
#
$(DOC_MEDIA_FILES_BUILD): | $(DOC_MEDIA_DIRS_BUILD)

$(DOC_BUILD)/%: docs/% | $(DOC_BUILD)
	$(CP) $< $@

docs/%.json docs/%.html: docs/%.restdown | $(DOC_BUILD) $(RESTDOWN_EXEC)
	$(RESTDOWN) $(RESTDOWN_FLAGS) -m $(DOC_BUILD) $<

$(DOC_BUILD):
	$(MKDIR) $@

$(DOC_MEDIA_DIRS_BUILD):
	$(MKDIR) $@

#
# The default "test" target does nothing. This should usually be overridden by
# the parent Makefile. It's included here so we can define "prepush" without
# requiring the repo to define "test".
#
.PHONY: test
test:

.PHONY: prepush
prepush: check test