Properly handle parallel make ("make -j"), and only rerun gyp if necessary.

This should completely resolve http://code.google.com/p/skia/issues/detail?id=330 ('building multiple targets in parallel fails on Linux')

This should resolve http://code.google.com/p/skia/issues/detail?id=313 ('toplevel makefile always reruns gyp_skia') for Linux, but not Mac.  (See details in comments within the file)
Review URL: http://codereview.appspot.com/4827043

git-svn-id: http://skia.googlecode.com/svn/trunk@1968 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/Makefile b/Makefile
index 6e4e538..aee6efd 100644
--- a/Makefile
+++ b/Makefile
@@ -29,30 +29,63 @@
 
 BUILDTYPE ?= Debug
 CWD := $(shell pwd)
+ALL_TARGETS := SampleApp bench gm tests tools
+
+# Default target.  This must be listed before all other targets.
+.PHONY: default
+default: all
+
+# As noted in http://code.google.com/p/skia/issues/detail?id=330 , building
+# multiple targets in parallel was failing.  The special .NOTPARALLEL target
+# tells gnu make not to run targets within _this_ Makefile in parallel, but the
+# recursively invoked Makefile within out/ _is_ allowed to run in parallel
+# (so you can still get some speedup that way).
+.NOTPARALLEL:
 
 uname := $(shell uname)
 ifneq (,$(findstring CYGWIN, $(uname)))
   $(error Cannot build using Make on Windows. See http://code.google.com/p/skia/wiki/GettingStartedOnWindows)
 endif
 
-# Default target.  This must be listed before all other targets.
-.PHONY: default
-default: all
-
 .PHONY: all
-all: SampleApp bench gm tests tools
+all: $(ALL_TARGETS)
 
 .PHONY: clean
 clean:
 	rm -rf out xcodebuild
 
-# Any targets not defined above...
-# Ask gyp to generate the buildfiles as appropriate for this platform,
-# and then pass control to those buildfiles.
+# Run gyp no matter what.
+.PHONY: gyp
+gyp:
+	$(CWD)/gyp_skia
+
+# Run gyp if necessary.
+#
+# On Linux, only run gyp if we haven't already generated the platform-specific
+# Makefiles.  If the underlying gyp configuration has changed since these
+# Makefiles were generated, they will rerun gyp on their own.
+#
+# This does not work for Mac, though... so for now, we ALWAYS rerun gyp on Mac.
+# TODO(epoger): Figure out a better solution for Mac... maybe compare the
+# gypfile timestamps to the xcodebuild project timestamps?
+.PHONY: gyp_if_needed
+gyp_if_needed:
+ifneq (,$(findstring Linux, $(uname)))
+	$(MAKE) out/Makefile
+endif
+ifneq (,$(findstring Darwin, $(uname)))
+	$(CWD)/gyp_skia
+endif
+
+out/Makefile:
+	$(CWD)/gyp_skia
+
+# For all specific targets: run gyp if necessary, and then pass control to
+# the gyp-generated buildfiles.
 #
 # For the Mac, we create a convenience symlink to the generated binary.
-%:
-	$(CWD)/gyp_skia
+.PHONY: $(ALL_TARGETS)
+$(ALL_TARGETS):: gyp_if_needed
 ifneq (,$(findstring Linux, $(uname)))
 	$(MAKE) -C out $@ BUILDTYPE=$(BUILDTYPE)
 endif
@@ -63,20 +96,3 @@
 	ln -s $(CWD)/xcodebuild/$(BUILDTYPE)/$@.app/Contents/MacOS/$@ out/$(BUILDTYPE)/$@
 endif
 
-# This repetition is ugly, but necessary.
-# If there are any files/directories within the same directory as this Makefile
-# which share the same name as a target ("tests", for example), then make
-# will refuse to rebuild those targets because the file already exists.
-local_filenames := $(shell ls)
-.PHONY: $(local_filenames)
-$(local_filenames)::
-	$(CWD)/gyp_skia
-ifneq (,$(findstring Linux, $(uname)))
-	$(MAKE) -C out $@ BUILDTYPE=$(BUILDTYPE)
-endif
-ifneq (,$(findstring Darwin, $(uname)))
-	xcodebuild -project out/gyp/$@.xcodeproj -configuration $(BUILDTYPE)
-	mkdir -p out/$(BUILDTYPE)
-	rm -f out/$(BUILDTYPE)/$@
-	ln -s $(CWD)/xcodebuild/$(BUILDTYPE)/$@.app/Contents/MacOS/$@ out/$(BUILDTYPE)/$@
-endif