123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- #
- # This waf script is responsible for building the SDK which can be shipped off to users into
- # tintin/build/sdk/src_wscript is the file which app developers actually run to build their apps
- #
- import json
- import os
- import waflib
- from string import Template
- from tools.fw_elf_obfuscate import obfuscate
- COPY = "cp ${SRC} ${TGT}"
- def _generate_sdk_waf(ctx):
- """
- Build a custom version of waf that includes the waf plugins we need
- :param bld:
- :return:
- """
- sdk_waftools = [tool.path_from(ctx.path.parent) for tool in ctx.path.ant_glob('waftools/*.py')]
- shared_waftools = [
- "tools/resources/waftools/generate_resource_ball.py",
- "tools/resources/waftools/generate_pbpack.py",
- "tools/resources/waftools/generate_resource_id_header.py",
- "waftools/file_name_c_define.py",
- "waftools/ldscript.py",
- "waftools/objcopy.py",
- "waftools/pebble_sdk_gcc.py",
- "waftools/pebble_sdk_version.py",
- "waftools/xcode_pebble.py"
- ]
- pebble_waf_tools = []
- for tool in sdk_waftools + shared_waftools:
- path = ctx.path.parent.find_node(tool)
- if path is None:
- ctx.fatal("Trying to bundle non existent resource in pb-waf ({})".format(tool))
- pebble_waf_tools.append(path)
- # We cannot run this as a sub-wscript because we use a specific vendor-provided
- # wscript that provides the --make-waf option and needs to be run in its own clean
- # environment
- def _build_waf(task):
- bld = task.generator.bld
- cmd_str = ('cd "{}" && python "{}" distclean configure build --make-waf --tools="{}" &&'
- 'cp waf "{}"'.format(waf_folder.abspath(),
- task.inputs[0].abspath(),
- ','.join(x.abspath() for x in task.inputs[1:]),
- task.outputs[0].abspath()))
- try:
- bld.cmd_and_log(cmd_str, quiet=waflib.Context.BOTH)
- except waflib.Errors.WafError as e:
- bld.to_log("out: %s" % e.stdout)
- bld.to_log("err: %s" % e.stderr)
- raise e
- waf_folder = ctx.path.find_node('waf')
- waf_light = waf_folder.find_node('waf-light')
- ctx(rule=_build_waf,
- source=[waf_light, ] + pebble_waf_tools,
- target=waf_folder.get_bld())
- def _copy_common_tools(bld, common_folder_node):
- """
- Copy SDK tools into common/waftools and common/tools
- :param bld:
- :param common_folder_node:
- :return:
- """
- for tool in bld.path.ant_glob(['tools/**/*']):
- bld(rule=COPY,
- source=tool,
- target=common_folder_node.make_node(tool.path_from(bld.path)))
- shared_tools = [
- "tools/binutils.py",
- "tools/bitmapgen.py",
- "tools/font/__init__.py",
- "tools/font/fontgen.py",
- "tools/generate_appinfo.py",
- "tools/generate_c_byte_array.py",
- "tools/mkbundle.py",
- "tools/pbpack.py",
- "tools/pbpack_meta_data.py",
- "tools/pebble_image_routines.py",
- "tools/pebble_sdk_platform.py",
- "tools/png2pblpng.py",
- "tools/stm32_crc.py"
- ]
- if bld.env.INTERNAL_SDK_BUILD:
- shared_tools.append("tools/pebble_sdk_platform_internal.py")
- for tool in shared_tools:
- bld(rule=COPY,
- source=bld.path.parent.find_node(tool),
- target=common_folder_node.make_node(tool))
- resource_waftools = [
- "tools/resources/__init__.py",
- "tools/resources/find_resource_filename.py",
- "tools/resources/resource_map/__init__.py",
- "tools/resources/resource_map/resource_generator.py",
- "tools/resources/resource_map/resource_generator_bitmap.py",
- "tools/resources/resource_map/resource_generator_font.py",
- "tools/resources/resource_map/resource_generator_js.py",
- "tools/resources/resource_map/resource_generator_pbi.py",
- "tools/resources/resource_map/resource_generator_png.py",
- "tools/resources/resource_map/resource_generator_raw.py",
- "tools/resources/types/__init__.py",
- "tools/resources/types/resource_ball.py",
- "tools/resources/types/resource_declaration.py",
- "tools/resources/types/resource_definition.py",
- "tools/resources/types/resource_object.py"
- ]
- for tool in resource_waftools:
- tool_node = bld.path.parent.find_node(tool)
- bld(rule=COPY,
- source=tool_node,
- target=(common_folder_node.make_node('waftools')
- .make_node(tool_node.path_from(bld.path.parent.find_node('tools')))))
- def options(opt):
- opt.add_option('--sdk_debug_elf', action='store_true',
- help='Enable building obfuscated ELF files for SDK debugging.')
- def configure(conf):
- if conf.options.sdk_debug_elf:
- conf.env.INCLUDE_SDK_DEBUG_ELF = True
- def build(bld):
- bld(rule=COPY,
- source=bld.path.find_node('sdk_requirements.txt'),
- target=bld.path.get_bld().make_node('requirements.txt'))
- bld(rule=COPY,
- source=bld.path.find_node('sdk_package.json'),
- target=bld.path.get_bld().make_node('package.json'))
- bld(rule=COPY,
- source=bld.path.find_node('use_requirements.json'),
- target=bld.path.get_bld().make_node('use_requirements.json'))
- tintin_home = bld.path.parent
- platform_folder_node = bld.path.get_bld().make_node(bld.env.PLATFORM_NAME)
- platform_folder_node.parent.mkdir()
- bld(features='subst',
- source=bld.path.find_node('Doxyfile-SDK.template'),
- target=platform_folder_node.make_node('Doxyfile-SDK.auto'),
- TINTIN_ROOT=tintin_home.abspath(),
- PLATFORM_PATH=platform_folder_node.path_from(bld.path.parent))
- common_folder_node = bld.path.get_bld().make_node('common')
- common_folder_node.parent.mkdir()
- for sdk_file in bld.path.ant_glob(['include/*', 'pebble_app.ld.template']):
- bld(rule=COPY,
- source=sdk_file,
- target=common_folder_node.make_node(sdk_file.path_from(bld.path)))
- if not bld.env.NOJS:
- js_tooling_path = os.path.dirname(bld.env.JS_TOOLING_SCRIPT.relpath())
- for js_tool in ('js_tooling.js', 'generate_snapshot.js'):
- bld(rule=COPY,
- source=bld.path.parent.get_bld().make_node(js_tooling_path).make_node(js_tool),
- target=common_folder_node.make_node('tools').make_node(js_tool),
- name='copy_rocky_tooling')
- template_folder_node = common_folder_node.make_node('templates')
- template_folder_node.parent.mkdir()
- defaults_node = bld.path.find_node('defaults')
- # Check whether the default project files are valid templates:
- with open(defaults_node.find_node('templates.json').abspath()) as f:
- templates = json.load(f)
- def _collect_check_templates_tasks(dct):
- for key in dct:
- val = dct[key]
- if isinstance(val, str):
- # avoid unicode, it will trip up waf's Node3 and make it 💩 all over the place
- val = str(val)
- template_node = defaults_node.find_node(val.split(os.path.sep))
- if not template_node:
- waflib.Logs.warn(
- "Could not find {}, but it's defined in "
- "templates.json".format(val))
- continue
- with open(template_node.abspath()) as tf:
- try:
- Template(tf.read()).substitute()
- except KeyError:
- pass # This is expected, no args to substitute()
- except ValueError as e:
- bld.fatal(
- "Template error in {}:\n{}\n"
- "Hint: make sure to escape dollar signs! ($ => $$)".format(
- template_node.abspath(), e.message))
- elif isinstance(val, dict):
- _collect_check_templates_tasks(val)
- _collect_check_templates_tasks(templates)
- # Copy default SDK project files
- for default_file in bld.path.ant_glob('defaults/**/*'):
- bld(rule=COPY,
- source=default_file,
- target=template_folder_node.make_node(default_file.path_from(defaults_node)))
- # Generate shims
- # We shell out to this script because it imports the clang module, which does not run correctly
- # under pypy. By running python explicitly when calling this script, we avoid the
- # incompatibility with pypy and clang.
- native_generator_script = (
- bld.path.parent.find_node('tools/generate_native_sdk/generate_pebble_native_sdk_files.py'))
- export_symbols = bld.path.parent.find_node('tools/generate_native_sdk/exported_symbols.json')
- source_dir = bld.path.parent.find_node('src')
- output_source_dir = source_dir.get_bld()
- with open(export_symbols.abspath()) as f:
- native_generator_sources = (
- [source_dir.find_node(str(header)) for header in json.load(f)['files']])
- native_generator_sources.append(export_symbols)
- native_generator_targets = [bld.path.parent.make_node('src/fw/pebble.auto.c').get_bld(),
- platform_folder_node.make_node('include/pebble.h'),
- platform_folder_node.make_node('include/pebble_sdk_version.h'),
- platform_folder_node.make_node('include/pebble_process_info.h'),
- platform_folder_node.make_node('include/pebble_worker.h'),
- platform_folder_node.make_node('include/pebble_worker_sdk_version.h')]
- bld(rule="cd '{}' ; python '{}' --sdk-dir='{}' '{}' '{}' '{}' '{}' {}".
- format(tintin_home.abspath(),
- native_generator_script.abspath(),
- platform_folder_node.abspath(),
- export_symbols.abspath(),
- source_dir.abspath(),
- output_source_dir.abspath(),
- bld.env.PLATFORM_NAME,
- '--internal-sdk-build' if bld.env.INTERNAL_SDK_BUILD else ''),
- name="generate_native_sdk",
- source=native_generator_sources,
- target=native_generator_targets)
- _generate_sdk_waf(bld)
- _copy_common_tools(bld, common_folder_node)
- # Generate our exported font header based on the whitelist in exported_symbols.json.
- # This is different than our internal header (font_resource_keys.auto.h) as it excludes
- # some fonts that we don't want to export
- def _generate_pebble_fonts_h(task):
- with open(task.outputs[0].abspath(), 'w') as f_out:
- f_out.write('#pragma once\n')
- f_out.write('\n')
- with open(task.inputs[0].abspath(), 'r') as f_in:
- font_list = json.load(f_in)["fonts"]
- for font in font_list:
- f_out.write('#define FONT_KEY_{0} "RESOURCE_ID_{0}"\n'.format(font))
- # Copy any font keys over to the SDK
- bld(rule=_generate_pebble_fonts_h,
- source=export_symbols,
- target=platform_folder_node.make_node('include/pebble_fonts.h'))
- # Generate obfuscated elf file for GDB debugging
- if bld.env.INCLUDE_SDK_DEBUG_ELF:
- def _obfuscate_elf(task):
- input_elf = task.inputs[0].abspath()
- output_elf = task.outputs[0].abspath()
- obfuscate(input_elf, output_elf, no_text=False)
- firmware_build_node = bld.path.parent.get_bld().find_or_declare('src').find_or_declare('fw')
- bld(rule=_obfuscate_elf,
- source=firmware_build_node.make_node('tintin_fw.elf'),
- target=bld.path.get_bld().make_node('{}_sdk_debug.elf'.format(bld.env.PLATFORM_NAME)))
|