# Dali Clock for MacOS X, Copyright (c) 2005-2014 by Jamie Zawinski.

XCODE_APP = /Applications/Xcode.app

# To build savers that will run on MacOS 10.6 and 10.7, Xcode 5.0.2 must
# be used (as that's the latest version of Xcode that ships with a version
# of clang that implements "-fobjc-gc").  However, Xcode 5.0.2 will not
# launch on MacOS 10.11 or later.
#
# XCODE_APP = /Applications/Xcode-5.0.2.app

TARGETS    = -target DaliClock \
	     -target DaliClockStore \
	     -target DaliClockSaver \
	     -target DaliClockWidget
#ARCH      = -arch i386 -arch x86_64 ONLY_ACTIVE_ARCH=NO
XCODEBUILD = $(XCODE_APP)/Contents/Developer/usr/bin/xcodebuild
SETFILE    = $(XCODE_APP)/Contents/Developer/Tools/SetFile
SETICON    = ./seticon.pl

default: release
all: debug release

clean:
	-rm -rf build
#	$(XCODEBUILD) $(TARGETS) clean

distclean:
	-rm -f config.status config.cache config.log \
	  *.bak *.rej TAGS *~ "#"*
	-rm -rf autom4te*.cache
	-rm -rf build Sparkle.framework

distdepend:: Sparkle.framework
distdepend:: update_plist_version
distdepend:: update_bindist_version

debug: distdepend
	$(XCODEBUILD) $(ARCH) $(TARGETS) -configuration Debug   build

release:: distdepend
	$(XCODEBUILD) $(ARCH) $(TARGETS) -configuration Release build
	spctl --assess --type execute build/Release/*.app

release:: check_versions
#release:: enable_gc

Sparkle.framework:
	rm -rf bin sparkle-bin
	tar -vxjf ../archive/Sparkle-1.21.2.tar.bz2 \
	  --exclude CHANGELOG \
	  --exclude LICENSE \
	  --exclude SampleAppcast.xml \
	  --exclude Sparkle.framework.dSYM \
	  --exclude Sparkle\ Test\ App\*
	mv bin sparkle-bin


# See comment at the top of xscreensaver/OSX/enable_gc.c
enable_gc:
	../../xscreensaver/OSX/build/Debug/enable_gc \
	build/Release/DaliClock.saver/Contents/MacOS/DaliClock

check_gc:
	@\
  DIR="build/Release" ;							\
  RESULT=0 ;								\
  for S in "$$DIR/"*.saver ; do						\
   SS=`echo "$$S" | sed -e 's@^.*/@@' -e 's/.saver$$//'` ;		\
   D="$$S/Contents/MacOS/$$SS" ;					\
   V=`otool -s __DATA __objc_imageinfo "$$D"				\
      | grep ' 00 02 00 '` ;						\
   if [ -z "$$V" ]; then						\
     echo "$$S does not have GC enabled" ;				\
     RESULT=1 ;								\
   fi ;									\
  done ;								\
  if [ "$$RESULT" = 0 ]; then echo "GC enabled" ; fi ;			\
  exit $$RESULT


check_versions:
	@\
  U=../version.h ;							\
  V=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ;]*\).*/\1/p' < $$U` ;		\
  DIR=build/Release ;							\
  RESULT=0 ;								\
  for P in `find $$DIR -name Info.plist |				\
	    grep -v Sparkle.framework` ; do				\
     V2=`perl -0000 -n -e						\
	'm@<key>CFBundleVersion</key>\s*<string>(.*?)</string>@si 	\
	 && print $$1' < $$P` ;						\
     if [ "$$V2" != "$$V" ] ; then					\
       echo "Wrong version: $$P ($$V2)" ;				\
       RESULT=1 ;							\
     fi ;								\
  done ;								\
  if [ "$$RESULT" = 0 ]; then echo "Versions match ($$V2)" ; fi ;	\
  exit $$RESULT


echo_tarfiles:
	@echo `find . \
	  \( \( -name '.??*' -o -name build -o -name CVS -o -name '*~*' \
	     -o -name 'jwz.*' -o -name '*.widgetplugin' \
	     -o -name '*.psd' -o -name '*.ai' \) \
	     -prune \) \
	  -o \( -type f -o -type l \) -print \
	| sed 's@^\./@@' \
	| sort`

update_plist_version:
	@								      \
  SS="AppInfo.plist SaverInfo.plist PluginInfo.plist iPhoneInfo.plist *.wdgt/Info.plist" ;   \
  SRC=../version.h ;							      \
  V=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ]*\).*/\1/p' $$SRC` ;		      \
  Y=`date +%Y` ;							      \
  T=/tmp/xs.$$$$ ;							      \
  for S in $$SS ; do							      \
    /bin/echo -n "Updating version number in $$S to \"$$V\"... " ;	      \
    KEYS1="CFBundleVersion|CFBundleShortVersionString" ;		      \
    KEYS2="NSHumanReadableCopyright|CFBundleLongVersionString|CFBundleGetInfoString" ; \
    perl -0777 -pne							      \
      "s@(<key>($$KEYS1)</key>\s*<string>)[^<>]+(</string>)@\$${1}$$V\$${3}@g; \
       s@(<key>($$KEYS2)</key>\s*<string>[^\d]+)[\d.]+(.*?</string>)@\$${1}$$V\$${3}@gs; \
       s@(<key>($$KEYS2)</key>\s*<string>.*?1991-)\d\d\d\d(.*?</string>)@\$${1}$$Y\$${3}@gs" \
    < $$S > $$T ;							    \
   if cmp -s $$S $$T ; then						    \
     echo "unchanged." ;						    \
   else									    \
    cat $$T > $$S ;							    \
    echo "done." ;							    \
   fi ;									    \
   rm $$T ;								    \
  done


update_bindist_version:
	@								    \
  SS="bindist.rtf Credits.html" ;					    \
  U=../version.h ;							    \
  V=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ;]*\).*/\1/p' < $$U` ;		    \
  D=`date '+%d-%b-%Y'` ;						    \
  Y=`date '+%Y'` ;							    \
  for S in $$SS ; do							    \
   T=/tmp/xs.$$$$ ;							    \
   sed -e "s/\(.*version \)[0-9][0-9]*\.[0-9]*[ab]*[0-9]*\(.*\)/\1$$V\2/"   \
       -e "s/\(1991-\)[0-9][0-9][0-9][0-9]/\1$$Y/"			    \
       -e "s/\([0-9][0-9]-[A-Z][a-z][a-z]-[0-9][0-9][0-9]*\)/$$D/"	    \
      < $$S > $$T ;							    \
   if cmp -s $$S $$T ; then						    \
    true ;								    \
   else									    \
    cat $$T > $$S ;							    \
    echo "updated $$S to $$V $$D" ;					    \
   fi ;									    \
  done ;								    \
  rm $$T


updates.xml::
	./updates.pl DaliClock ../README ../archive ~/www/xdaliclock
	@$(MAKE) test_sig

test_sig::
	@								    \
  U=../version.h ;							    \
  V=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ;]*\).*/\1/p' < $$U` ;		    \
  V2="$$V" ;								      \
  V=`echo $$V | sed 's/\.//g'` ;					    \
  ZIP="../archive/DaliClock-$$V.dmg" ;					    \
  OV=`sed -n 's/^.*<title>Version \([^<>]*\).*/\1/p' updates.xml | head -1`;\
  if [ "x$$V2" != "x$$OV" ] ; then					    \
    echo "updates.xml: file version is $$OV instead of $$V2" 2>&2 ;	    \
    exit 1 ; 								    \
  fi ;									    \
  SIG=`sed -n 's/^.*dsaSignature="\(.*\)".*/\1/p' updates.xml` ;	    \
  PUB="sparkle_dsa_pub.pem" ;						    \
  NN="t.$$$$" ;								    \
  SIGB=/tmp/$$NN.sig ;							    \
  HASH=/tmp/$$NN.hash ;							    \
  rm -f "$$SIGB" "$$HASH" ;						    \
  echo "$$SIG " | base64 -D  > "$$SIGB" ;				    \
  set -e ;								    \
  for OPENSSL in /usr/bin/openssl /opt/local/bin/openssl ; do		    \
    $$OPENSSL dgst -sha1 -binary  < "$$ZIP"  > "$$HASH" ;		    \
    /bin/echo -n "$$OPENSSL	`$$OPENSSL version`:	" ;		    \
    $$OPENSSL dgst -dss1 -verify "$$PUB" -signature "$$SIGB" "$$HASH" ;	    \
  done ;								    \
  rm -f "$$SIGB" "$$HASH" ;						    \



# Can no longer do: ${TARGET_BUILD_DIR}/DaliClock.wdgt
# It causes code-signing to fail with "a sealed resource is missing or
# invalid", and if we set the icon before signing (with a build phase on
# DaliClockWidget) then signing fails with "resource fork, Finder
# information, or similar detritus not allowed".


# -format UDBZ saves 4% over UDZO, but that's only 8KB.
# check_gc
dmg:: distdepend check_versions _dmg notarize

_dmg::
	@								      \
  set -e ;								      \
  SRC=../version.h ;							      \
  V=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ;]*\).*/\1/p' $$SRC` ;		      \
  V2="$$V" ;								      \
  V=`echo $$V | sed 's/\.//g'` ;					      \
  TMPDIR="build" ;							      \
  SRC="build/Release" ;							      \
  BASE="DaliClock-$$V" ;						      \
  OUTDIR="../archive" ;							      \
  DMG="$$OUTDIR/$$BASE.dmg" ;						      \
  TMPDMG="$$TMPDIR/tmp.dmg" ;						      \
  VOLNAME="DaliClock $$V2" ;						      \
  STAGE="$$TMPDIR/dmg_stage" ;						      \
  rm -f "$$DMG" ;							      \
  rm -rf "$$STAGE" ;							      \
  echo + mkdir "$$STAGE" ;						      \
         mkdir "$$STAGE" ;						      \
  FILES="$$SRC/*.app $$SRC/*.saver $$SRC/*.wdgt" ;			      \
  echo + cp -pR $$FILES "$$STAGE" ;					      \
         cp -pR $$FILES "$$STAGE" ;					      \
  set -x ;								      \
  cp -p bindist.rtf "$$STAGE/ READ ME.rtf" ;				      \
  cp -p bindist-DS_Store "$$STAGE/.DS_Store" ;				      \
  cp -p bindist.webloc "$$STAGE/DaliClock for iOS.webloc" ;		      \
  cp -p bindist2.webloc "$$STAGE/DaliClock for Android.webloc" ;	      \
  ${SETFILE} -a E "$$STAGE/ READ ME.rtf" ;				      \
  ${SETFILE} -a e $$STAGE/*.saver ;					      \
  ${SETFILE} -a e $$STAGE/*.wdgt ;					      \
  ${SETFILE} -a E $$STAGE/*.webloc ;					      \
  $(SETICON) -d daliclockSaver.icns $$STAGE/*.saver ;			      \
  $(SETICON) -d weblociOS.icns $$STAGE/*iOS*.webloc ;			      \
  $(SETICON) -d weblocAndroid.icns $$STAGE/*Android*.webloc ;		      \
									      \
  spctl --assess --type execute "$$STAGE/"*.app ;			      \
  spctl --assess --type install "$$STAGE/"*.{saver,wdgt} ;		      \
									      \
  hdiutil makehybrid -quiet -ov -hfs -hfs-volume-name "$$VOLNAME"	      \
    -hfs-openfolder "$$STAGE" "$$STAGE" -o "$$TMPDMG" ;			      \
  rm -rf "$$STAGE" ;							      \
									      \
  hdiutil convert -quiet -ov -format UDZO -imagekey zlib-level=9	      \
    "$$TMPDMG" -o "$$DMG" ;						      \
  xattr -w com.apple.quarantine "0000;00000000;;" "$$DMG" ;		      \
  rm -f "$$TMPDMG" ;							      \
  ls -ldhgF "$$DMG" ;							      \

dmg2:: staple updates.xml


# Adding this is cute:
#    hdiutil internet-enable -yes -quiet "$$DMG"
# but means that nobody will ever see the display settings I used!
# When finder copies the .dmg to a folder, it doesn't preserve them.


# To set up notarization:
#  - Log in on https://appleid.apple.com/
#  - Generate App-Specific Password, "altool-notarizer"
#  - Keychain Access / New
#  - Name: "altool-notarizer", Account: "jwz@jwz.org",
#    Pass: the one you just generated.
#
# "make notarize", which will upload the DMG (slow).
# A response will be emailed back in about an hour.
# When that arrives, "make staple".
#
# https://developer.apple.com/documentation/security/notarizing_your_app_before_distribution/customizing_the_notarization_workflow?language=objc
#
# Note that if Sparkle.framework/.../Autoupdate.app is not independently
# signed, it won't pass. I had to add a build phase for that.
#
notarize::
	@								      \
  set -e ;								      \
  SRC=../version.h ;							      \
  V=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ;]*\).*/\1/p' $$SRC` ;		      \
  V=`echo $$V | sed 's/\.//g'` ;					      \
  BASE="DaliClock-$$V" ;						      \
  OUTDIR="../archive" ;							      \
  DMG="$$OUTDIR/$$BASE.dmg" ;						      \
  set -x ;								      \
  xcrun altool --notarize-app --primary-bundle-id "org.jwz.xscreensaver"      \
    --file "$$DMG" -u "jwz@jwz.org" -p "@keychain:altool-notarizer" ;	      \
  echo "" ;								      \
  echo "After notarization succeeds, make dmg2"


staple::
	@								      \
  set -e ;								      \
  SRC=../version.h ;							      \
  V=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ;]*\).*/\1/p' $$SRC` ;		      \
  V=`echo $$V | sed 's/\.//g'` ;					      \
  BASE="DaliClock-$$V" ;						      \
  OUTDIR="../archive" ;							      \
  DMG="$$OUTDIR/$$BASE.dmg" ;						      \
  set -x ;								      \
  xcrun stapler staple "$$DMG"

notarization_history::
	xcrun altool --notarization-history 0 \
	-u "jwz@jwz.org" -p "@keychain:altool-notarizer"
	@echo 'now do: xcrun altool --notarization-info <UUID> ...' ; \
	echo 'and wget the LogFileURL'
