mirror of
https://github.com/google/pebble.git
synced 2025-03-15 00:31:21 +00:00
162 lines
5.5 KiB
Python
162 lines
5.5 KiB
Python
# Copyright 2024 Google LLC
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
from waflib import Task
|
|
|
|
import json
|
|
import string
|
|
import uuid
|
|
|
|
# This file parses appinfo.json and generates a C file that get's built into
|
|
# the pebble app binary.
|
|
# See http://wiki.hq.getpebble.com/wiki/index.php/Software/Formats/AppinfoJson
|
|
# for details on the format.
|
|
|
|
def generate_appinfo(input_filename, output_filename):
|
|
with open(input_filename, 'r') as json_file:
|
|
try:
|
|
app_info = json.load(json_file)
|
|
except ValueError as e:
|
|
raise Exception('Could not parse appinfo.json file: '+ str(e))
|
|
generate_appinfo_c(app_info, output_filename)
|
|
|
|
|
|
def generate_appinfo_c(app_info, output_filename, platform_name=None):
|
|
# Handle top level options
|
|
try:
|
|
app_uuid = uuid.UUID(app_info['uuid'])
|
|
except KeyError:
|
|
raise Exception('Could not find $.uuid in appinfo.json')
|
|
uuid_initializer_string = '{ %s }' % ", ".join(["0x%02X" % ord(b) for b in app_uuid.bytes])
|
|
|
|
try:
|
|
name = app_info['shortName']
|
|
except KeyError:
|
|
raise Exception('Could not find $.shortName in appinfo.json')
|
|
|
|
try:
|
|
company_name = app_info['companyName']
|
|
except KeyError:
|
|
raise Exception('Could not find $.companyName in appinfo.json')
|
|
|
|
|
|
try:
|
|
version_label = app_info['versionLabel']
|
|
version_label_major = 0
|
|
version_label_minor = 0
|
|
version_label_list = version_label.split('.')
|
|
if len(version_label_list) >= 1:
|
|
version_label_major = version_label_list[0]
|
|
if len(version_label_list) >= 2:
|
|
version_label_minor = version_label_list[1]
|
|
if len(version_label_list) > 2:
|
|
raise Exception('appinfo.json versionLabel format for app revision must be "Major" or "Major.Minor"')
|
|
|
|
# validate versionLabel range [0-255] and int-characters
|
|
try:
|
|
if int(version_label_major) < 0 or int(version_label_major) > 255:
|
|
raise ValueError
|
|
if int(version_label_minor) < 0 or int(version_label_minor) > 255:
|
|
raise ValueError
|
|
except ValueError:
|
|
raise Exception('appinfo.json versionLabel contains invalid or out of range values [0-255]')
|
|
|
|
|
|
except KeyError:
|
|
raise Exception('Could not find $.versionLabel in appinfo.json')
|
|
|
|
# Handle 'watchapp' options
|
|
try:
|
|
is_watchface = app_info['watchapp']['watchface']
|
|
except KeyError:
|
|
is_watchface = False
|
|
|
|
try:
|
|
only_shown_on_communication = app_info['watchapp']['onlyShownOnCommunication']
|
|
except KeyError:
|
|
only_shown_on_communication = False
|
|
|
|
try:
|
|
is_hidden = app_info['watchapp']['hiddenApp']
|
|
except KeyError:
|
|
is_hidden = False
|
|
|
|
# Handle 'resources' options
|
|
icon_resource_id = None
|
|
try:
|
|
for r in app_info['resources']['media']:
|
|
if 'menuIcon' in r and r['menuIcon']:
|
|
if icon_resource_id is not None:
|
|
raise Exception('More than one resource is set to be your menuIcon!')
|
|
icon_resource_id = 'RESOURCE_ID_' + r['name']
|
|
except KeyError:
|
|
pass
|
|
if icon_resource_id is None:
|
|
icon_resource_id = 'DEFAULT_MENU_ICON'
|
|
|
|
try:
|
|
is_rocky = app_info['projectType'] == 'rocky'
|
|
except KeyError:
|
|
is_rocky = False
|
|
|
|
flags = []
|
|
if is_watchface:
|
|
flags.append('PROCESS_INFO_WATCH_FACE')
|
|
if only_shown_on_communication:
|
|
flags.append('PROCESS_INFO_VISIBILITY_SHOWN_ON_COMMUNICATION')
|
|
if is_hidden:
|
|
flags.append('PROCESS_INFO_VISIBILITY_HIDDEN')
|
|
if is_rocky:
|
|
flags.append('PROCESS_INFO_ROCKY_APP')
|
|
if platform_name:
|
|
flags.append('PROCESS_INFO_PLATFORM_{}'.format(platform_name.upper()))
|
|
|
|
if len(flags):
|
|
flags_string = ' | '.join(flags)
|
|
else:
|
|
flags_string = '0'
|
|
|
|
|
|
with open(output_filename, 'w') as f:
|
|
f.write('#include "pebble_process_info.h"\n')
|
|
f.write('#include "src/resource_ids.auto.h"\n')
|
|
f.write(PEBBLE_APP_INFO_TEMPLATE.substitute(
|
|
version_major=version_label_major,
|
|
version_minor=version_label_minor,
|
|
name=name,
|
|
company=company_name,
|
|
icon_resource_id=icon_resource_id,
|
|
flags=flags_string,
|
|
uuid=uuid_initializer_string).encode('utf-8'))
|
|
|
|
PEBBLE_APP_INFO_TEMPLATE = string.Template("""
|
|
const PebbleProcessInfo __pbl_app_info __attribute__ ((section (".pbl_header"))) = {
|
|
.header = "PBLAPP",
|
|
.struct_version = { PROCESS_INFO_CURRENT_STRUCT_VERSION_MAJOR, PROCESS_INFO_CURRENT_STRUCT_VERSION_MINOR },
|
|
.sdk_version = { PROCESS_INFO_CURRENT_SDK_VERSION_MAJOR, PROCESS_INFO_CURRENT_SDK_VERSION_MINOR },
|
|
.process_version = { ${version_major}, ${version_minor} },
|
|
.load_size = 0xb6b6,
|
|
.offset = 0xb6b6b6b6,
|
|
.crc = 0xb6b6b6b6,
|
|
.name = "${name}",
|
|
.company = "${company}",
|
|
.icon_resource_id = ${icon_resource_id},
|
|
.sym_table_addr = 0xA7A7A7A7,
|
|
.flags = ${flags},
|
|
.num_reloc_entries = 0xdeadcafe,
|
|
.uuid = ${uuid},
|
|
.virtual_size = 0xb6b6
|
|
};
|
|
""")
|
|
|