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