app.mk (23832B)
1 ######################################################################### 2 # common include file for application Makefiles 3 # 4 # Makefile common usage: 5 # > make 6 # > make run 7 # > make install 8 # > make remove 9 # 10 # Makefile less common usage: 11 # > make art-opt 12 # > make pkg 13 # > make install_native 14 # > make remove_native 15 # > make tr 16 # 17 # By default, ZIP_EXCLUDE will exclude -x \*.pkg -x storeassets\* -x keys\* -x .\* 18 # If you define ZIP_EXCLUDE in your Makefile, it will override the default setting. 19 # 20 # To exclude different files from being added to the zipfile during packaging 21 # include a line like this:ZIP_EXCLUDE= -x keys\* 22 # that will exclude any file who's name begins with 'keys' 23 # to exclude using more than one pattern use additional '-x <pattern>' arguments 24 # ZIP_EXCLUDE= -x \*.pkg -x storeassets\* 25 # 26 # If you want to add additional files to the default ZIP_EXCLUDE use 27 # ZIP_EXCLUDE_LOCAL 28 # 29 # Important Notes: 30 # To use the "run", "install" and "remove" targets to install your 31 # application directly from the shell, you must do the following: 32 # 33 # 1) Make sure that you have the curl command line executable in your path 34 # 2) Set the variable ROKU_DEV_TARGET in your environment to the IP 35 # address of your Roku box. (e.g. export ROKU_DEV_TARGET=192.168.1.1. 36 ########################################################################## 37 38 # improve performance and simplify Makefile debugging by omitting 39 # default language rules that don't apply to this environment. 40 MAKEFLAGS += --no-builtin-rules 41 .SUFFIXES: 42 43 HOST_OS := unknown 44 UNAME_S := $(shell uname -s) 45 ifeq ($(UNAME_S),Darwin) 46 HOST_OS := macos 47 else ifeq ($(UNAME_S),Linux) 48 HOST_OS := linux 49 else ifneq (,$(findstring CYGWIN,$(UNAME_S))) 50 HOST_OS := cygwin 51 else ifeq ($(UNAME_S),FreeBSD) 52 HOST_OS := freebsd 53 endif 54 55 IS_TEAMCITY_BUILD ?= 56 ifneq ($(TEAMCITY_BUILDCONF_NAME),) 57 IS_TEAMCITY_BUILD := true 58 endif 59 60 # get the root directory in absolute form, so that current directory 61 # can be changed during the make if needed. 62 APPS_ROOT_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) 63 64 # the current directory is the app root directory 65 SOURCEDIR := . 66 67 DISTREL := $(APPS_ROOT_DIR)/dist 68 COMMONREL := $(APPS_ROOT_DIR)/common 69 70 ZIPREL := $(DISTREL)/apps 71 PKGREL := $(DISTREL)/packages 72 CHECK_TMP_DIR := $(DISTREL)/tmp-check 73 74 DATE_TIME := $(shell date +%F-%T) 75 76 APP_ZIP_FILE := $(ZIPREL)/$(APPNAME).zip 77 APP_PKG_FILE := $(PKGREL)/$(APPNAME)_$(DATE_TIME).pkg 78 79 # these variables are only used for the .pkg file version tagging. 80 APP_NAME := $(APPNAME) 81 APP_VERSION := $(VERSION) 82 ifeq ($(IS_TEAMCITY_BUILD),true) 83 APP_NAME := $(subst /,-,$(TEAMCITY_BUILDCONF_NAME)) 84 APP_VERSION := $(BUILD_NUMBER) 85 endif 86 87 APPSOURCEDIR := $(SOURCEDIR)/source 88 IMPORTFILES := $(foreach f,$(IMPORTS),$(COMMONREL)/$f.brs) 89 IMPORTCLEANUP := $(foreach f,$(IMPORTS),$(APPSOURCEDIR)/$f.brs) 90 91 # ROKU_NATIVE_DEV must be set in the calling environment to 92 # the firmware native-build src directory 93 NATIVE_DIST_DIR := $(ROKU_NATIVE_DEV)/dist 94 # 95 NATIVE_DEV_REL := $(NATIVE_DIST_DIR)/rootfs/Linux86_dev.OBJ/root/nvram/incoming 96 NATIVE_DEV_PKG := $(NATIVE_DEV_REL)/dev.zip 97 NATIVE_PLETHORA := $(NATIVE_DIST_DIR)/application/Linux86_dev.OBJ/root/bin/plethora 98 NATIVE_TICKLER := $(NATIVE_PLETHORA) tickle-plugin-installer 99 100 # only Linux host is supported for these tools currently 101 APPS_TOOLS_DIR := $(APPS_ROOT_DIR)/tools/$(HOST_OS)/bin 102 103 APP_PACKAGE_TOOL := $(APPS_TOOLS_DIR)/app-package 104 MAKE_TR_TOOL := $(APPS_TOOLS_DIR)/maketr 105 BRIGHTSCRIPT_TOOL := $(APPS_TOOLS_DIR)/brightscript 106 107 # if building from a firmware tree, use the BrightScript libraries from there 108 ifneq (,$(wildcard $(APPS_ROOT_DIR)/../3rdParty/brightscript/Scripts/LibCore/.)) 109 BRIGHTSCRIPT_LIBS_DIR ?= $(APPS_ROOT_DIR)/../3rdParty/brightscript/Scripts/LibCore 110 endif 111 # else use the reference libraries from the tools directory. 112 BRIGHTSCRIPT_LIBS_DIR ?= $(APPS_ROOT_DIR)/tools/brightscript/Scripts/LibCore 113 114 APP_KEY_PASS_TMP := /tmp/app_key_pass 115 DEV_SERVER_TMP_FILE := /tmp/dev_server_out 116 117 # The developer password that was set on the player is required for 118 # plugin_install operations on modern versions of firmware. 119 # It may be pre-specified in the DEVPASSWORD environment variable on entry, 120 # otherwise the make will stop and prompt the user to enter it when needed. 121 ifdef DEVPASSWORD 122 USERPASS := rokudev:$(DEVPASSWORD) 123 else 124 USERPASS := rokudev 125 endif 126 127 ifeq ($(HOST_OS),macos) 128 # Mac doesn't support these args 129 CP_ARGS = 130 else 131 CP_ARGS = --preserve=ownership,timestamps --no-preserve=mode 132 endif 133 134 # For a quick ping, we want the command to return success as soon as possible, 135 # and a timeout failure in no more than a second or two. 136 ifeq ($(HOST_OS),cygwin) 137 # This assumes that the Windows ping command is used, not cygwin's. 138 QUICK_PING_ARGS = -n 1 -w 1000 139 else ifeq ($(HOST_OS),freebsd) 140 QUICK_PING_ARGS = -c 1 -t 1 141 else # Linux 142 QUICK_PING_ARGS = -c 1 -w 1 143 endif 144 145 ifndef ZIP_EXCLUDE 146 ZIP_EXCLUDE= -x \*.pkg -x storeassets\* -x keys\* -x \*/.\* $(ZIP_EXCLUDE_LOCAL) 147 endif 148 149 # ------------------------------------------------------------------------- 150 # $(APPNAME): the default target is to create the zip file for the app. 151 # This contains the set of files that are to be deployed on a Roku. 152 # ------------------------------------------------------------------------- 153 .PHONY: $(APPNAME) 154 $(APPNAME): manifest 155 @echo "*** Creating $(APPNAME).zip ***" 156 157 @echo " >> removing old application zip $(APP_ZIP_FILE)" 158 @if [ -e "$(APP_ZIP_FILE)" ]; then \ 159 rm -f $(APP_ZIP_FILE); \ 160 fi 161 162 @echo " >> creating destination directory $(ZIPREL)" 163 @if [ ! -d $(ZIPREL) ]; then \ 164 mkdir -p $(ZIPREL); \ 165 fi 166 167 @echo " >> setting directory permissions for $(ZIPREL)" 168 @if [ ! -w $(ZIPREL) ]; then \ 169 chmod 755 $(ZIPREL); \ 170 fi 171 172 @echo " >> copying imports" 173 @if [ "$(IMPORTFILES)" ]; then \ 174 mkdir $(APPSOURCEDIR)/common; \ 175 cp -f $(CP_ARGS) -v $(IMPORTFILES) $(APPSOURCEDIR)/common/; \ 176 fi \ 177 178 # zip .png files without compression 179 # do not zip up Makefiles, or any files ending with '~' 180 @echo " >> creating application zip $(APP_ZIP_FILE)" 181 @if [ -d $(SOURCEDIR) ]; then \ 182 (zip -0 -r "$(APP_ZIP_FILE)" . -i \*.png $(ZIP_EXCLUDE)); \ 183 (zip -9 -r "$(APP_ZIP_FILE)" . -x \*~ -x \*.png -x Makefile $(ZIP_EXCLUDE)); \ 184 else \ 185 echo "Source for $(APPNAME) not found at $(SOURCEDIR)"; \ 186 fi 187 188 @if [ "$(IMPORTCLEANUP)" ]; then \ 189 echo " >> deleting imports";\ 190 rm -r -f $(APPSOURCEDIR)/common; \ 191 fi \ 192 193 @echo "*** packaging $(APPNAME) complete ***" 194 195 # If DISTDIR is not empty then copy the zip package to the DISTDIR. 196 # Note that this is used by the firmware build, to build applications that are 197 # embedded in the firmware software image, such as the built-in screensaver. 198 # For those cases, the Netflix/Makefile calls this makefile for each app 199 # with DISTDIR and DISTZIP set to the target directory and base filename 200 # respectively. 201 @if [ $(DISTDIR) ]; then \ 202 rm -f $(DISTDIR)/$(DISTZIP).zip; \ 203 mkdir -p $(DISTDIR); \ 204 cp -f --preserve=ownership,timestamps --no-preserve=mode \ 205 $(APP_ZIP_FILE) $(DISTDIR)/$(DISTZIP).zip; \ 206 fi 207 208 # ------------------------------------------------------------------------- 209 # clean: remove any build output for the app. 210 # ------------------------------------------------------------------------- 211 .PHONY: clean 212 clean: 213 rm -f $(APP_ZIP_FILE) 214 # FIXME: we should use a canonical output file name, rather than having 215 # the date-time stamp in the output file name. 216 # rm -f $(APP_PKG_FILE) 217 rm -f $(PKGREL)/$(APPNAME)_*.pkg 218 219 # ------------------------------------------------------------------------- 220 # clobber: remove any build output for the app. 221 # ------------------------------------------------------------------------- 222 .PHONY: clobber 223 clobber: clean 224 225 # ------------------------------------------------------------------------- 226 # dist-clean: remove the dist directory for the sandbox. 227 # ------------------------------------------------------------------------- 228 .PHONY: dist-clean 229 dist-clean: 230 rm -rf $(DISTREL)/* 231 232 # ------------------------------------------------------------------------- 233 # CHECK_OPTIONS: this is used to specify configurable options, such 234 # as which version of the BrightScript library sources should be used 235 # to compile the app. 236 # ------------------------------------------------------------------------- 237 CHECK_OPTIONS = 238 ifneq (,$(wildcard $(BRIGHTSCRIPT_LIBS_DIR)/.)) 239 CHECK_OPTIONS += -lib $(BRIGHTSCRIPT_LIBS_DIR) 240 endif 241 242 # ------------------------------------------------------------------------- 243 # check: run the desktop BrightScript compiler/check tool on the 244 # application. 245 # You can bypass checking on the application by setting 246 # APP_CHECK_DISABLED=true in the app's Makefile or in the environment. 247 # ------------------------------------------------------------------------- 248 .PHONY: check 249 check: $(APPNAME) 250 ifeq ($(APP_CHECK_DISABLED),true) 251 ifeq ($(IS_TEAMCITY_BUILD),true) 252 @echo "*** Warning: application check skipped ***" 253 endif 254 else 255 ifeq ($(wildcard $(BRIGHTSCRIPT_TOOL)),) 256 @echo "*** Note: application check not available ***" 257 else 258 @echo "*** Checking application ***" 259 rm -rf $(CHECK_TMP_DIR) 260 mkdir -p $(CHECK_TMP_DIR) 261 unzip -q $(APP_ZIP_FILE) -d $(CHECK_TMP_DIR) 262 $(BRIGHTSCRIPT_TOOL) check \ 263 $(CHECK_OPTIONS) \ 264 $(CHECK_TMP_DIR) 265 rm -rf $(CHECK_TMP_DIR) 266 endif 267 endif 268 269 # ------------------------------------------------------------------------- 270 # check-strict: run the desktop BrightScript compiler/check tool on the 271 # application using strict mode. 272 # ------------------------------------------------------------------------- 273 .PHONY: check-strict 274 check-strict: $(APPNAME) 275 @echo "*** Checking application (strict) ***" 276 rm -rf $(CHECK_TMP_DIR) 277 mkdir -p $(CHECK_TMP_DIR) 278 unzip -q $(APP_ZIP_FILE) -d $(CHECK_TMP_DIR) 279 $(BRIGHTSCRIPT_TOOL) check -strict \ 280 $(CHECK_OPTIONS) \ 281 $(CHECK_TMP_DIR) 282 rm -rf $(CHECK_TMP_DIR) 283 284 # ------------------------------------------------------------------------- 285 # GET_FRIENDLY_NAME_FROM_DD is used to extract the Roku device ID 286 # from the ECP device description XML response. 287 # ------------------------------------------------------------------------- 288 define GET_FRIENDLY_NAME_FROM_DD 289 cat $(DEV_SERVER_TMP_FILE) | \ 290 grep -o "<friendlyName>.*</friendlyName>" | \ 291 sed "s|<friendlyName>||" | \ 292 sed "s|</friendlyName>||" 293 endef 294 295 # ------------------------------------------------------------------------- 296 # CHECK_ROKU_DEV_TARGET is used to check if ROKU_DEV_TARGET refers a 297 # Roku device on the network that has an enabled developer web server. 298 # If the target doesn't exist or doesn't have an enabled web server 299 # the connection should fail. 300 # ------------------------------------------------------------------------- 301 define CHECK_ROKU_DEV_TARGET 302 if [ -z "$(ROKU_DEV_TARGET)" ]; then \ 303 echo "ERROR: ROKU_DEV_TARGET is not set."; \ 304 exit 1; \ 305 fi 306 echo "Checking dev server at $(ROKU_DEV_TARGET)..." 307 308 # first check if the device is on the network via a quick ping 309 ping $(QUICK_PING_ARGS) $(ROKU_DEV_TARGET) &> $(DEV_SERVER_TMP_FILE) || \ 310 ( \ 311 echo "ERROR: Device is not responding to ping."; \ 312 exit 1 \ 313 ) 314 315 # second check ECP, to verify we are talking to a Roku 316 rm -f $(DEV_SERVER_TMP_FILE) 317 curl --connect-timeout 2 --silent --output $(DEV_SERVER_TMP_FILE) \ 318 http://$(ROKU_DEV_TARGET):8060 || \ 319 ( \ 320 echo "ERROR: Device is not responding to ECP...is it a Roku?"; \ 321 exit 1 \ 322 ) 323 324 # echo the device friendly name to let us know what we are talking to 325 ROKU_DEV_NAME=`$(GET_FRIENDLY_NAME_FROM_DD)`; \ 326 echo "Device reports as \"$$ROKU_DEV_NAME\"." 327 328 # third check dev web server. 329 # Note, it should return 401 Unauthorized since we aren't passing the password. 330 rm -f $(DEV_SERVER_TMP_FILE) 331 HTTP_STATUS=`curl --connect-timeout 2 --silent --output $(DEV_SERVER_TMP_FILE) \ 332 http://$(ROKU_DEV_TARGET)` || \ 333 ( \ 334 echo "ERROR: Device server is not responding...is the developer installer enabled?"; \ 335 exit 1 \ 336 ) 337 338 echo "Dev server is ready." 339 endef 340 341 # ------------------------------------------------------------------------- 342 # CHECK_DEVICE_HTTP_STATUS is used to that the last curl command 343 # to the dev web server returned HTTP 200 OK. 344 # ------------------------------------------------------------------------- 345 define CHECK_DEVICE_HTTP_STATUS 346 if [ "$$HTTP_STATUS" != "200" ]; then \ 347 echo "ERROR: Device returned HTTP $$HTTP_STATUS"; \ 348 exit 1; \ 349 fi 350 endef 351 352 # ------------------------------------------------------------------------- 353 # GET_PLUGIN_PAGE_RESULT_STATUS is used to extract the status message 354 # (e.g. Success/Failed) from the dev server plugin_* web page response. 355 # (Note that the plugin_install web page has two fields, whereas the 356 # plugin_package web page just has one). 357 # ------------------------------------------------------------------------- 358 define GET_PLUGIN_PAGE_RESULT_STATUS 359 cat $(DEV_SERVER_TMP_FILE) | \ 360 grep -o "<font color=\"red\">.*" | \ 361 sed "s|<font color=\"red\">||" | \ 362 sed "s|</font>||" 363 endef 364 365 # ------------------------------------------------------------------------- 366 # GET_PLUGIN_PAGE_PACKAGE_LINK is used to extract the installed package 367 # URL from the dev server plugin_package web page response. 368 # ------------------------------------------------------------------------- 369 define GET_PLUGIN_PAGE_PACKAGE_LINK = 370 cat $(DEV_SERVER_TMP_FILE) | \ 371 grep -o "<a href=\"pkgs//[^\"]*\"" | \ 372 sed "s|<a href=\"pkgs//||" | \ 373 sed "s|\"||" 374 endef 375 376 # ------------------------------------------------------------------------- 377 # install: install the app as the dev channel on the Roku target device. 378 # ------------------------------------------------------------------------- 379 .PHONY: install 380 install: $(APPNAME) check 381 @$(CHECK_ROKU_DEV_TARGET) 382 383 @echo "Installing $(APPNAME)..." 384 @rm -f $(DEV_SERVER_TMP_FILE) 385 @HTTP_STATUS=`curl --user $(USERPASS) --digest --silent --show-error \ 386 -F "mysubmit=Install" -F "archive=@$(APP_ZIP_FILE)" \ 387 --output $(DEV_SERVER_TMP_FILE) \ 388 --write-out "%{http_code}" \ 389 http://$(ROKU_DEV_TARGET)/plugin_install`; \ 390 $(CHECK_DEVICE_HTTP_STATUS) 391 392 @MSG=`$(GET_PLUGIN_PAGE_RESULT_STATUS)`; \ 393 echo "Result: $$MSG" 394 395 # ------------------------------------------------------------------------- 396 # remove: uninstall the dev channel from the Roku target device. 397 # ------------------------------------------------------------------------- 398 .PHONY: remove 399 remove: 400 @$(CHECK_ROKU_DEV_TARGET) 401 402 @echo "Removing dev app..." 403 @rm -f $(DEV_SERVER_TMP_FILE) 404 @HTTP_STATUS=`curl --user $(USERPASS) --digest --silent --show-error \ 405 -F "mysubmit=Delete" -F "archive=" \ 406 --output $(DEV_SERVER_TMP_FILE) \ 407 --write-out "%{http_code}" \ 408 http://$(ROKU_DEV_TARGET)/plugin_install`; \ 409 $(CHECK_DEVICE_HTTP_STATUS) 410 411 @MSG=`$(GET_PLUGIN_PAGE_RESULT_STATUS)`; \ 412 echo "Result: $$MSG" 413 414 # ------------------------------------------------------------------------- 415 # check-roku-dev-target: check the status of the Roku target device. 416 # ------------------------------------------------------------------------- 417 .PHONY: check-roku-dev-target 418 check-roku-dev-target: 419 @$(CHECK_ROKU_DEV_TARGET) 420 421 # ------------------------------------------------------------------------- 422 # run: the install target is 'smart' and doesn't do anything if the package 423 # didn't change. 424 # But usually I want to run it even if it didn't change, so force a fresh 425 # install by doing a remove first. 426 # Some day we should look at doing the force run via a plugin_install flag, 427 # but for now just brute force it. 428 # ------------------------------------------------------------------------- 429 .PHONY: run 430 run: remove install 431 432 # ------------------------------------------------------------------------- 433 # pkg: use to create a pkg file from the application sources. 434 # 435 # Usage: 436 # The application name should be specified via $APPNAME. 437 # The application version should be specified via $VERSION. 438 # The developer's signing password (from genkey) should be passed via 439 # $APP_KEY_PASS, or via stdin, otherwise the script will prompt for it. 440 # ------------------------------------------------------------------------- 441 .PHONY: pkg 442 pkg: install 443 @echo "*** Creating Package ***" 444 445 @echo " >> creating destination directory $(PKGREL)" 446 @if [ ! -d $(PKGREL) ]; then \ 447 mkdir -p $(PKGREL); \ 448 fi 449 450 @echo " >> setting directory permissions for $(PKGREL)" 451 @if [ ! -w $(PKGREL) ]; then \ 452 chmod 755 $(PKGREL); \ 453 fi 454 455 @$(CHECK_ROKU_DEV_TARGET) 456 457 @echo "Packaging $(APP_NAME)/$(APP_VERSION) to $(APP_PKG_FILE)" 458 459 @if [ -z "$(APP_KEY_PASS)" ]; then \ 460 read -r -p "Password: " REPLY; \ 461 echo "$$REPLY" > $(APP_KEY_PASS_TMP); \ 462 else \ 463 echo "$(APP_KEY_PASS)" > $(APP_KEY_PASS_TMP); \ 464 fi 465 466 @rm -f $(DEV_SERVER_TMP_FILE) 467 @PASSWD=`cat $(APP_KEY_PASS_TMP)`; \ 468 PKG_TIME=`expr \`date +%s\` \* 1000`; \ 469 HTTP_STATUS=`curl --user $(USERPASS) --digest --silent --show-error \ 470 -F "mysubmit=Package" -F "app_name=$(APP_NAME)/$(APP_VERSION)" \ 471 -F "passwd=$$PASSWD" -F "pkg_time=$$PKG_TIME" \ 472 --output $(DEV_SERVER_TMP_FILE) \ 473 --write-out "%{http_code}" \ 474 http://$(ROKU_DEV_TARGET)/plugin_package`; \ 475 $(CHECK_DEVICE_HTTP_STATUS) 476 477 @MSG=`$(GET_PLUGIN_PAGE_RESULT_STATUS)`; \ 478 case "$$MSG" in \ 479 *Success*) \ 480 ;; \ 481 *) echo "Result: $$MSG"; \ 482 exit 1 \ 483 ;; \ 484 esac 485 486 @PKG_LINK=`$(GET_PLUGIN_PAGE_PACKAGE_LINK)`; \ 487 HTTP_STATUS=`curl --user $(USERPASS) --digest --silent --show-error \ 488 --output $(APP_PKG_FILE) \ 489 --write-out "%{http_code}" \ 490 http://$(ROKU_DEV_TARGET)/pkgs/$$PKG_LINK`; \ 491 $(CHECK_DEVICE_HTTP_STATUS) 492 493 @echo "*** Package $(APPNAME) complete ***" 494 495 # ------------------------------------------------------------------------- 496 # app-pkg: use to create a pkg file from the application sources. 497 # Similar to the pkg target, but does not require a player to do the signing. 498 # Instead it requires the developer key file and signing password to be 499 # specified, which are then passed to the app-package desktop tool to create 500 # the package file. 501 # 502 # Usage: 503 # The application name should be specified via $APPNAME. 504 # The application version should be specified via $VERSION. 505 # The developer's key file (.pkg file) should be specified via $APP_KEY_FILE. 506 # The developer's signing password (from genkey) should be passed via 507 # $APP_KEY_PASS, or via stdin, otherwise the script will prompt for it. 508 # ------------------------------------------------------------------------- 509 .PHONY: app-pkg 510 app-pkg: $(APPNAME) check 511 @echo "*** Creating package ***" 512 513 @echo " >> creating destination directory $(PKGREL)" 514 @mkdir -p $(PKGREL) && chmod 755 $(PKGREL) 515 516 @if [ -z "$(APP_KEY_FILE)" ]; then \ 517 echo "ERROR: APP_KEY_FILE not defined"; \ 518 exit 1; \ 519 fi 520 @if [ ! -f "$(APP_KEY_FILE)" ]; then \ 521 echo "ERROR: key file not found: $(APP_KEY_FILE)"; \ 522 exit 1; \ 523 fi 524 525 @if [ -z "$(APP_KEY_PASS)" ]; then \ 526 read -r -p "Password: " REPLY; \ 527 echo "$$REPLY" > $(APP_KEY_PASS_TMP); \ 528 else \ 529 echo "$(APP_KEY_PASS)" > $(APP_KEY_PASS_TMP); \ 530 fi 531 532 @echo "Packaging $(APP_NAME)/$(APP_VERSION) to $(APP_PKG_FILE)" 533 534 @if [ -z "$(APP_VERSION)" ]; then \ 535 echo "WARNING: VERSION is not set."; \ 536 fi 537 538 @PASSWD=`cat $(APP_KEY_PASS_TMP)`; \ 539 $(APP_PACKAGE_TOOL) package $(APP_ZIP_FILE) \ 540 -n $(APP_NAME)/$(APP_VERSION) \ 541 -k $(APP_KEY_FILE) \ 542 -p "$$PASSWD" \ 543 -o $(APP_PKG_FILE) 544 545 @rm $(APP_KEY_PASS_TMP) 546 547 @echo "*** Package $(APPNAME) complete ***" 548 549 # ------------------------------------------------------------------------- 550 # teamcity: used to build .zip and .pkg file on TeamCity. 551 # See app-pkg target for info on options for specifying the signing password. 552 # ------------------------------------------------------------------------- 553 .PHONY: teamcity 554 teamcity: app-pkg 555 ifeq ($(IS_TEAMCITY_BUILD),true) 556 @echo "Adding TeamCity artifacts..." 557 558 sudo rm -f /tmp/artifacts 559 sudo mkdir -p /tmp/artifacts 560 561 cp $(APP_ZIP_FILE) /tmp/artifacts/$(APP_NAME)-$(APP_VERSION).zip 562 @echo "##teamcity[publishArtifacts '/tmp/artifacts/$(APP_NAME)-$(APP_VERSION).zip']" 563 564 cp $(APP_PKG_FILE) /tmp/artifacts/$(APP_NAME)-$(APP_VERSION).pkg 565 @echo "##teamcity[publishArtifacts '/tmp/artifacts/$(APP_NAME)-$(APP_VERSION).pkg']" 566 567 @echo "TeamCity artifacts complete." 568 else 569 @echo "Not running on TeamCity, skipping artifacts." 570 endif 571 572 ########################################################################## 573 574 # ------------------------------------------------------------------------- 575 # CHECK_NATIVE_TARGET is used to check if the Roku simulator is 576 # configured. 577 # ------------------------------------------------------------------------- 578 define CHECK_NATIVE_TARGET 579 if [ -z "$(ROKU_NATIVE_DEV)" ]; then \ 580 echo "ERROR: ROKU_NATIVE_DEV not defined"; \ 581 exit 1; \ 582 i 583 if [ ! -d "$(ROKU_NATIVE_DEV)" ]; then \ 584 echo "ERROR: native dev dir not found: $(ROKU_NATIVE_DEV)"; \ 585 exit 1; \ 586 fi 587 if [ ! -d "$(NATIVE_DIST_DIR)" ]; then \ 588 echo "ERROR: native build dir not found: $(NATIVE_DIST_DIR)"; \ 589 exit 1; \ 590 fi 591 endef 592 593 # ------------------------------------------------------------------------- 594 # install-native: install the app as the dev channel on the Roku simulator. 595 # ------------------------------------------------------------------------- 596 .PHONY: install-native 597 install-native: $(APPNAME) check 598 @$(CHECK_NATIVE_TARGET) 599 @echo "Installing $(APPNAME) to native." 600 @if [ ! -d "$(NATIVE_DEV_REL)" ]; then \ 601 mkdir "$(NATIVE_DEV_REL)"; \ 602 fi 603 @echo "Source is $(APP_ZIP_FILE)" 604 @echo "Target is $(NATIVE_DEV_PKG)" 605 @cp $(APP_ZIP_FILE) $(NATIVE_DEV_PKG) 606 @$(NATIVE_TICKLER) 607 608 # ------------------------------------------------------------------------- 609 # remove-native: uninstall the dev channel from the Roku simulator. 610 # ------------------------------------------------------------------------- 611 .PHONY: remove-native 612 remove-native: 613 @$(CHECK_NATIVE_TARGET) 614 @echo "Removing $(APPNAME) from native." 615 @rm $(NATIVE_DEV_PKG) 616 @$(NATIVE_TICKLER) 617 618 ########################################################################## 619 620 # ------------------------------------------------------------------------- 621 # art-jpg-opt: compress any jpg files in the source tree. 622 # Used by the art-opt target. 623 # ------------------------------------------------------------------------- 624 APPS_JPG_ART=`\find . -name "*.jpg"` 625 626 .PHONY: art-jpg-opt 627 art-jpg-opt: 628 p4 edit $(APPS_JPG_ART) 629 for i in $(APPS_JPG_ART); \ 630 do \ 631 TMPJ=`mktemp` || return 1; \ 632 echo "optimizing $$i"; \ 633 (jpegtran -copy none -optimize -outfile $$TMPJ $$i && mv -f $$TMPJ $$i &); \ 634 done 635 wait 636 p4 revert -a $(APPS_JPG_ART) 637 638 # ------------------------------------------------------------------------- 639 # art-png-opt: compress any png files in the source tree. 640 # Used by the art-opt target. 641 # ------------------------------------------------------------------------- 642 APPS_PNG_ART=`\find . -name "*.png"` 643 644 .PHONY: art-png-opt 645 art-png-opt: 646 p4 edit $(APPS_PNG_ART) 647 for i in $(APPS_PNG_ART); \ 648 do \ 649 (optipng -o7 $$i &); \ 650 done 651 wait 652 p4 revert -a $(APPS_PNG_ART) 653 654 # ------------------------------------------------------------------------- 655 # art-opt: compress any png and jpg files in the source tree using 656 # lossless compression options. 657 # This assumes a Perforce client/workspace is configured. 658 # Modified files are opened for edit in the default changelist. 659 # ------------------------------------------------------------------------- 660 .PHONY: art-opt 661 art-opt: art-png-opt art-jpg-opt 662 663 ########################################################################## 664 665 # ------------------------------------------------------------------------- 666 # tr: this target is used to update translation files for an application 667 # MAKE_TR_OPTIONS may be set to [-t] [-d] etc. in the external environment, 668 # if needed. 669 # ------------------------------------------------------------------------- 670 .PHONY: tr 671 tr: 672 p4 opened -c default 673 p4 edit locale/.../translations.xml 674 $(MAKE_TR_TOOL) $(MAKE_TR_OPTIONS) 675 rm locale/en_US/translations.xml 676 p4 revert -a locale/.../translations.xml 677 p4 opened -c default 678 679 ##########################################################################