import os import time import waflib import waflib.Tools import waftools.objcopy as objcopy import waftools.pebble_sdk_gcc as pebble_sdk_gcc from resources.types.resource_definition import ResourceDefinition from resources.types.resource_object import ResourceObject from pebble_sdk_platform import pebble_platforms, maybe_import_internal from pebble_sdk_version import set_env_sdk_version import generate_appinfo # # Make each of the apps within the stored_apps directory # # ----------------------------------------------------------------------------------- def configure(conf): process_info = conf.path.parent.find_node('src/fw/process_management/pebble_process_info.h') set_env_sdk_version(conf, process_info) pebble_sdk_gcc.configure(conf) conf.env.append_value('DEFINES', 'RELEASE') # ----------------------------------------------------------------------------------- def build_app(bld, app_name): sdk_folder = bld.path.parent.get_bld().make_node('sdk').make_node(bld.env.PLATFORM_NAME) # ----------------------------------------------------------------------------------- # Generate the appinfo.auto.c file appinfo_json_node = bld.path.get_src().find_node('%s/appinfo.json' % (app_name)) if appinfo_json_node is None: bld.fatal('Could not find appinfo.json') appinfo_c_node = bld.path.get_bld().make_node('%s/appinfo.auto.c' % (app_name)) resource_ids_auto_node = bld.path.get_bld().make_node( '%s/src/resource_ids.auto.h' % (app_name)) bld(rule='echo "#define DEFAULT_MENU_ICON 0" >> ${TGT}', target=resource_ids_auto_node) message_keys_auto_node = bld.path.get_bld().make_node(app_name).make_node("message_keys.auto.h") bld(rule='touch ${TGT}', target=message_keys_auto_node) def _generate_appinfo_c_file_rule(task): generate_appinfo.generate_appinfo(task.inputs[0].abspath(), task.outputs[0].abspath()) bld(rule=_generate_appinfo_c_file_rule, source=appinfo_json_node, target=appinfo_c_node) # ----------------------------------------------------------------------------------- # Generate the rule to compile and link the sources into an ELF includes = [sdk_folder.make_node('include'), app_name, '%s/src' % (app_name)] link_flags = ['-mcpu=cortex-m3','-mthumb','-fPIE', '-Wl,--emit-relocs'] source = bld.path.ant_glob('%s/src/**/*.c' % (app_name)) + [appinfo_c_node] ld_script = bld.path.make_node('pebble_app.ld').path_from(bld.path) app_elf_file = bld.path.get_bld().make_node('%s/pebble-app.elf' % (app_name)) stored_apps_env = bld.all_envs['stored_apps'] maybe_import_internal(bld.env) # Fetch platform-specific defines and add them to CFLAGS platform_name = stored_apps_env['PLATFORM_NAME'] platform_info = pebble_platforms.get(platform_name, None) if platform_info is None: bld.fatal("Unsupported platform: %s" % platform_name) platform_defines = platform_info['DEFINES'] c_flags = ['-fPIE'] + ['-D%s' % define for define in platform_defines] gen = bld.program(env=stored_apps_env, source=source, target=app_elf_file, includes=includes, cflags=c_flags, ldscript=ld_script, linkflags=link_flags, stlibpath=[sdk_folder.make_node('lib').abspath()], stlib=['pebble']) # ----------------------------------------------------------------------------------- # Create the bin file and inject the metadata app_raw_bin_file = bld.path.get_bld().make_node('%s/pebble-app.raw.bin' % (app_name)) bld(rule=objcopy.objcopy_bin, source=app_elf_file, target=app_raw_bin_file) app_bin_file = bld.path.get_bld().make_node('%s/pebble-app.bin' % (app_name)) # Use a dummy timestamp for the metadata in stored_apps. This timestamp is only used # to describe the resource version, and stored_apps have no resources. If we use the # real timestamp that will cause the CRC of the app to change from build to build, # which causes the pbpack's CRC to change from build to build, which means we have to # keep using image_resources in development every time we rebuild, even though the # content didn't change. pebble_sdk_gcc.gen_inject_metadata_rule(bld, src_bin_file=app_raw_bin_file, dst_bin_file=app_bin_file, elf_file=app_elf_file, resource_file=None, timestamp=0, has_pkjs=False, has_worker=False) # ----------------------------------------------------------------------------------- # Copy into the resources directory as a .reso file def _make_reso(task): app_bin_data = task.inputs[0].read(flags='rb') reso = ResourceObject( ResourceDefinition('raw', 'STORED_APP_{}'.format(app_name.upper()), None), app_bin_data) reso.dump(task.outputs[0]) resources_bld_node = bld.bldnode.make_node('resources/') app_resource_node = resources_bld_node.make_node('normal/base/raw/app_%s.bin.reso' % (app_name)) bld(rule=_make_reso, source=app_bin_file, target=app_resource_node, name='stored_app_reso') bld.DYNAMIC_RESOURCES.append(app_resource_node) # ----------------------------------------------------------------------------------- def build(bld): # When you add a new stored app, you must also do the following to include it into the # system resources and register it with the launcher: # 1.) Add a raw resource entry with a name of "STORED_APP_" to # resources/normal/resource_map.json. # The "file" field should be set to normal/raw/app_.bin # 2.) Add a new entry to the INIT_STORED_APPS array in system_app_registry.h apps = bld.path.ant_glob('*', dir=True, src=False) for app in apps: build_app(bld, app.name) # vim:filetype=python