1# Dali Clock for MacOS X, Copyright (c) 2005-2014 by Jamie Zawinski. 2 3XCODE_APP = /Applications/Xcode.app 4 5# To build savers that will run on MacOS 10.6 and 10.7, Xcode 5.0.2 must 6# be used (as that's the latest version of Xcode that ships with a version 7# of clang that implements "-fobjc-gc"). However, Xcode 5.0.2 will not 8# launch on MacOS 10.11 or later. 9# 10# XCODE_APP = /Applications/Xcode-5.0.2.app 11 12TARGETS = -target DaliClock \ 13 -target DaliClockStore \ 14 -target DaliClockSaver \ 15 -target DaliClockWidget 16#ARCH = -arch i386 -arch x86_64 ONLY_ACTIVE_ARCH=NO 17XCODEBUILD = $(XCODE_APP)/Contents/Developer/usr/bin/xcodebuild 18SETFILE = $(XCODE_APP)/Contents/Developer/Tools/SetFile 19SETICON = ./seticon.pl 20 21default: release 22all: debug release 23 24clean: 25 -rm -rf build 26# $(XCODEBUILD) $(TARGETS) clean 27 28distclean: 29 -rm -f config.status config.cache config.log \ 30 *.bak *.rej TAGS *~ "#"* 31 -rm -rf autom4te*.cache 32 -rm -rf build Sparkle.framework 33 34distdepend:: Sparkle.framework 35distdepend:: update_plist_version 36distdepend:: update_bindist_version 37 38debug: distdepend 39 $(XCODEBUILD) $(ARCH) $(TARGETS) -configuration Debug build 40 41release:: distdepend 42 $(XCODEBUILD) $(ARCH) $(TARGETS) -configuration Release build 43 spctl --assess --type execute build/Release/*.app 44 45release:: check_versions 46#release:: enable_gc 47 48Sparkle.framework: 49 rm -rf bin sparkle-bin 50 tar -vxjf ../archive/Sparkle-1.21.2.tar.bz2 \ 51 --exclude CHANGELOG \ 52 --exclude LICENSE \ 53 --exclude SampleAppcast.xml \ 54 --exclude Sparkle.framework.dSYM \ 55 --exclude Sparkle\ Test\ App\* 56 mv bin sparkle-bin 57 58 59# See comment at the top of xscreensaver/OSX/enable_gc.c 60enable_gc: 61 ../../xscreensaver/OSX/build/Debug/enable_gc \ 62 build/Release/DaliClock.saver/Contents/MacOS/DaliClock 63 64check_gc: 65 @\ 66 DIR="build/Release" ; \ 67 RESULT=0 ; \ 68 for S in "$$DIR/"*.saver ; do \ 69 SS=`echo "$$S" | sed -e 's@^.*/@@' -e 's/.saver$$//'` ; \ 70 D="$$S/Contents/MacOS/$$SS" ; \ 71 V=`otool -s __DATA __objc_imageinfo "$$D" \ 72 | grep ' 00 02 00 '` ; \ 73 if [ -z "$$V" ]; then \ 74 echo "$$S does not have GC enabled" ; \ 75 RESULT=1 ; \ 76 fi ; \ 77 done ; \ 78 if [ "$$RESULT" = 0 ]; then echo "GC enabled" ; fi ; \ 79 exit $$RESULT 80 81 82check_versions: 83 @\ 84 U=../version.h ; \ 85 V=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ;]*\).*/\1/p' < $$U` ; \ 86 DIR=build/Release ; \ 87 RESULT=0 ; \ 88 for P in `find $$DIR -name Info.plist | \ 89 grep -v Sparkle.framework` ; do \ 90 V2=`perl -0000 -n -e \ 91 'm@<key>CFBundleVersion</key>\s*<string>(.*?)</string>@si \ 92 && print $$1' < $$P` ; \ 93 if [ "$$V2" != "$$V" ] ; then \ 94 echo "Wrong version: $$P ($$V2)" ; \ 95 RESULT=1 ; \ 96 fi ; \ 97 done ; \ 98 if [ "$$RESULT" = 0 ]; then echo "Versions match ($$V2)" ; fi ; \ 99 exit $$RESULT 100 101 102echo_tarfiles: 103 @echo `find . \ 104 \( \( -name '.??*' -o -name build -o -name CVS -o -name '*~*' \ 105 -o -name 'jwz.*' -o -name '*.widgetplugin' \ 106 -o -name '*.psd' -o -name '*.ai' \) \ 107 -prune \) \ 108 -o \( -type f -o -type l \) -print \ 109 | sed 's@^\./@@' \ 110 | sort` 111 112update_plist_version: 113 @ \ 114 SS="AppInfo.plist SaverInfo.plist PluginInfo.plist iPhoneInfo.plist *.wdgt/Info.plist" ; \ 115 SRC=../version.h ; \ 116 V=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ]*\).*/\1/p' $$SRC` ; \ 117 Y=`date +%Y` ; \ 118 T=/tmp/xs.$$$$ ; \ 119 for S in $$SS ; do \ 120 /bin/echo -n "Updating version number in $$S to \"$$V\"... " ; \ 121 KEYS1="CFBundleVersion|CFBundleShortVersionString" ; \ 122 KEYS2="NSHumanReadableCopyright|CFBundleLongVersionString|CFBundleGetInfoString" ; \ 123 perl -0777 -pne \ 124 "s@(<key>($$KEYS1)</key>\s*<string>)[^<>]+(</string>)@\$${1}$$V\$${3}@g; \ 125 s@(<key>($$KEYS2)</key>\s*<string>[^\d]+)[\d.]+(.*?</string>)@\$${1}$$V\$${3}@gs; \ 126 s@(<key>($$KEYS2)</key>\s*<string>.*?1991-)\d\d\d\d(.*?</string>)@\$${1}$$Y\$${3}@gs" \ 127 < $$S > $$T ; \ 128 if cmp -s $$S $$T ; then \ 129 echo "unchanged." ; \ 130 else \ 131 cat $$T > $$S ; \ 132 echo "done." ; \ 133 fi ; \ 134 rm $$T ; \ 135 done 136 137 138update_bindist_version: 139 @ \ 140 SS="bindist.rtf Credits.html" ; \ 141 U=../version.h ; \ 142 V=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ;]*\).*/\1/p' < $$U` ; \ 143 D=`date '+%d-%b-%Y'` ; \ 144 Y=`date '+%Y'` ; \ 145 for S in $$SS ; do \ 146 T=/tmp/xs.$$$$ ; \ 147 sed -e "s/\(.*version \)[0-9][0-9]*\.[0-9]*[ab]*[0-9]*\(.*\)/\1$$V\2/" \ 148 -e "s/\(1991-\)[0-9][0-9][0-9][0-9]/\1$$Y/" \ 149 -e "s/\([0-9][0-9]-[A-Z][a-z][a-z]-[0-9][0-9][0-9]*\)/$$D/" \ 150 < $$S > $$T ; \ 151 if cmp -s $$S $$T ; then \ 152 true ; \ 153 else \ 154 cat $$T > $$S ; \ 155 echo "updated $$S to $$V $$D" ; \ 156 fi ; \ 157 done ; \ 158 rm $$T 159 160 161updates.xml:: 162 ./updates.pl DaliClock ../README ../archive ~/www/xdaliclock 163 @$(MAKE) test_sig 164 165test_sig:: 166 @ \ 167 U=../version.h ; \ 168 V=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ;]*\).*/\1/p' < $$U` ; \ 169 V2="$$V" ; \ 170 V=`echo $$V | sed 's/\.//g'` ; \ 171 ZIP="../archive/DaliClock-$$V.dmg" ; \ 172 OV=`sed -n 's/^.*<title>Version \([^<>]*\).*/\1/p' updates.xml | head -1`;\ 173 if [ "x$$V2" != "x$$OV" ] ; then \ 174 echo "updates.xml: file version is $$OV instead of $$V2" 2>&2 ; \ 175 exit 1 ; \ 176 fi ; \ 177 SIG=`sed -n 's/^.*dsaSignature="\(.*\)".*/\1/p' updates.xml` ; \ 178 PUB="sparkle_dsa_pub.pem" ; \ 179 NN="t.$$$$" ; \ 180 SIGB=/tmp/$$NN.sig ; \ 181 HASH=/tmp/$$NN.hash ; \ 182 rm -f "$$SIGB" "$$HASH" ; \ 183 echo "$$SIG " | base64 -D > "$$SIGB" ; \ 184 set -e ; \ 185 for OPENSSL in /usr/bin/openssl /opt/local/bin/openssl ; do \ 186 $$OPENSSL dgst -sha1 -binary < "$$ZIP" > "$$HASH" ; \ 187 /bin/echo -n "$$OPENSSL `$$OPENSSL version`: " ; \ 188 $$OPENSSL dgst -dss1 -verify "$$PUB" -signature "$$SIGB" "$$HASH" ; \ 189 done ; \ 190 rm -f "$$SIGB" "$$HASH" ; \ 191 192 193 194# Can no longer do: ${TARGET_BUILD_DIR}/DaliClock.wdgt 195# It causes code-signing to fail with "a sealed resource is missing or 196# invalid", and if we set the icon before signing (with a build phase on 197# DaliClockWidget) then signing fails with "resource fork, Finder 198# information, or similar detritus not allowed". 199 200 201# -format UDBZ saves 4% over UDZO, but that's only 8KB. 202# check_gc 203dmg:: distdepend check_versions _dmg notarize 204 205_dmg:: 206 @ \ 207 set -e ; \ 208 SRC=../version.h ; \ 209 V=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ;]*\).*/\1/p' $$SRC` ; \ 210 V2="$$V" ; \ 211 V=`echo $$V | sed 's/\.//g'` ; \ 212 TMPDIR="build" ; \ 213 SRC="build/Release" ; \ 214 BASE="DaliClock-$$V" ; \ 215 OUTDIR="../archive" ; \ 216 DMG="$$OUTDIR/$$BASE.dmg" ; \ 217 TMPDMG="$$TMPDIR/tmp.dmg" ; \ 218 VOLNAME="DaliClock $$V2" ; \ 219 STAGE="$$TMPDIR/dmg_stage" ; \ 220 rm -f "$$DMG" ; \ 221 rm -rf "$$STAGE" ; \ 222 echo + mkdir "$$STAGE" ; \ 223 mkdir "$$STAGE" ; \ 224 FILES="$$SRC/*.app $$SRC/*.saver $$SRC/*.wdgt" ; \ 225 echo + cp -pR $$FILES "$$STAGE" ; \ 226 cp -pR $$FILES "$$STAGE" ; \ 227 set -x ; \ 228 cp -p bindist.rtf "$$STAGE/ READ ME.rtf" ; \ 229 cp -p bindist-DS_Store "$$STAGE/.DS_Store" ; \ 230 cp -p bindist.webloc "$$STAGE/DaliClock for iOS.webloc" ; \ 231 cp -p bindist2.webloc "$$STAGE/DaliClock for Android.webloc" ; \ 232 ${SETFILE} -a E "$$STAGE/ READ ME.rtf" ; \ 233 ${SETFILE} -a e $$STAGE/*.saver ; \ 234 ${SETFILE} -a e $$STAGE/*.wdgt ; \ 235 ${SETFILE} -a E $$STAGE/*.webloc ; \ 236 $(SETICON) -d daliclockSaver.icns $$STAGE/*.saver ; \ 237 $(SETICON) -d weblociOS.icns $$STAGE/*iOS*.webloc ; \ 238 $(SETICON) -d weblocAndroid.icns $$STAGE/*Android*.webloc ; \ 239 \ 240 spctl --assess --type execute "$$STAGE/"*.app ; \ 241 spctl --assess --type install "$$STAGE/"*.{saver,wdgt} ; \ 242 \ 243 hdiutil makehybrid -quiet -ov -hfs -hfs-volume-name "$$VOLNAME" \ 244 -hfs-openfolder "$$STAGE" "$$STAGE" -o "$$TMPDMG" ; \ 245 rm -rf "$$STAGE" ; \ 246 \ 247 hdiutil convert -quiet -ov -format UDZO -imagekey zlib-level=9 \ 248 "$$TMPDMG" -o "$$DMG" ; \ 249 xattr -w com.apple.quarantine "0000;00000000;;" "$$DMG" ; \ 250 rm -f "$$TMPDMG" ; \ 251 ls -ldhgF "$$DMG" ; \ 252 253dmg2:: staple updates.xml 254 255 256# Adding this is cute: 257# hdiutil internet-enable -yes -quiet "$$DMG" 258# but means that nobody will ever see the display settings I used! 259# When finder copies the .dmg to a folder, it doesn't preserve them. 260 261 262# To set up notarization: 263# - Log in on https://appleid.apple.com/ 264# - Generate App-Specific Password, "altool-notarizer" 265# - Keychain Access / New 266# - Name: "altool-notarizer", Account: "jwz@jwz.org", 267# Pass: the one you just generated. 268# 269# "make notarize", which will upload the DMG (slow). 270# A response will be emailed back in about an hour. 271# When that arrives, "make staple". 272# 273# https://developer.apple.com/documentation/security/notarizing_your_app_before_distribution/customizing_the_notarization_workflow?language=objc 274# 275# Note that if Sparkle.framework/.../Autoupdate.app is not independently 276# signed, it won't pass. I had to add a build phase for that. 277# 278notarize:: 279 @ \ 280 set -e ; \ 281 SRC=../version.h ; \ 282 V=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ;]*\).*/\1/p' $$SRC` ; \ 283 V=`echo $$V | sed 's/\.//g'` ; \ 284 BASE="DaliClock-$$V" ; \ 285 OUTDIR="../archive" ; \ 286 DMG="$$OUTDIR/$$BASE.dmg" ; \ 287 set -x ; \ 288 xcrun altool --notarize-app --primary-bundle-id "org.jwz.xscreensaver" \ 289 --file "$$DMG" -u "jwz@jwz.org" -p "@keychain:altool-notarizer" ; \ 290 echo "" ; \ 291 echo "After notarization succeeds, make dmg2" 292 293 294staple:: 295 @ \ 296 set -e ; \ 297 SRC=../version.h ; \ 298 V=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ;]*\).*/\1/p' $$SRC` ; \ 299 V=`echo $$V | sed 's/\.//g'` ; \ 300 BASE="DaliClock-$$V" ; \ 301 OUTDIR="../archive" ; \ 302 DMG="$$OUTDIR/$$BASE.dmg" ; \ 303 set -x ; \ 304 xcrun stapler staple "$$DMG" 305 306notarization_history:: 307 xcrun altool --notarization-history 0 \ 308 -u "jwz@jwz.org" -p "@keychain:altool-notarizer" 309 @echo 'now do: xcrun altool --notarization-info <UUID> ...' ; \ 310 echo 'and wget the LogFileURL' 311