pebble/tools/generate_native_sdk/generate_pebble_native_sdk_files.py
2025-01-27 11:38:16 -08:00

188 lines
7.7 KiB
Python
Executable file

#!/usr/bin/env 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 __future__ import with_statement
from __future__ import print_function
import os
import os.path as path
import shutil
import argparse
from generate_app_header import make_app_header
from generate_app_shim import make_app_shim_lib
from generate_fw_shim import make_fw_shims
from generate_json_api_description import make_json_api_description
from generate_app_sdk_version_header import generate_app_sdk_version_header
from extract_symbol_info import extract_symbol_info
from extract_comments import extract_comments
import exports
# When this file is called by waf using `python generate_pebble_native_sdk_files.py ...`, we
# need to append the parent directory to the system PATH because relative imports won't work
try:
from ..pebble_sdk_platform import pebble_platforms, maybe_import_internal
except ValueError:
os.sys.path.append(path.dirname(path.dirname(__file__)))
from pebble_sdk_platform import pebble_platforms, maybe_import_internal
SRC_DIR = 'src'
INCLUDE_DIR = 'include'
LIB_DIR = 'lib'
PEBBLE_APP_H_TEXT = """\
#include "pebble_fonts.h"
#include "message_keys.auto.h"
#include "src/resource_ids.auto.h"
#define PBL_APP_INFO(...) _Pragma("message \\"\\n\\n \\
*** PBL_APP_INFO has been replaced with appinfo.json\\n \\
Try updating your project with `pebble convert-project`\\n \\
Visit our developer guides to learn more about appinfo.json:\\n \\
http://developer.getpebble.com/guides/pebble-apps/\\n \\""); \\
_Pragma("GCC error \\"PBL_APP_INFO has been replaced with appinfo.json\\"");
#define PBL_APP_INFO_SIMPLE PBL_APP_INFO
"""
def generate_shim_files(shim_def_path, pbl_src_dir, pbl_output_src_dir, sdk_include_dir,
sdk_lib_dir, platform_name, internal_sdk_build=False):
if internal_sdk_build:
try:
from .. import pebble_sdk_platform_internal
except ValueError:
os.sys.path.append(path.dirname(path.dirname(__file__)))
import pebble_sdk_platform_internal
try:
platform_info = pebble_platforms.get(platform_name)
except KeyError:
raise Exception("Unsupported platform: %s" % platform_name)
files, exports_tree = exports.parse_export_file(shim_def_path, internal_sdk_build)
files = [ os.path.join(pbl_src_dir, f) for f in files ]
functions = []
exports.walk_tree(exports_tree, lambda e: functions.append(e) if e.type == 'function' else None)
types = []
exports.walk_tree(exports_tree, lambda e: types.append(e) if e.type == 'type' else None)
defines = []
exports.walk_tree(exports_tree, lambda e: defines.append(e) if e.type == 'define' else None)
groups = []
exports.walk_tree(exports_tree, lambda e: groups.append(e) if isinstance(e, exports.Group) else None, include_groups=True)
compiler_flags = ["-D{}".format(d) for d in platform_info["DEFINES"]]
freertos_port_name = "ARM_CM3_PEBBLE" if platform_name == "aplite" else "ARM_CM4_PEBBLE"
compiler_flags.extend(["-I{}/fw/vendor/FreeRTOS/Source/{}".format(pbl_src_dir, p) for p in
["include",
"portable/GCC/{}".format(freertos_port_name)]])
extract_symbol_info(files, functions, types, defines, pbl_output_src_dir,
internal_sdk_build=internal_sdk_build,
compiler_flags=compiler_flags)
extract_comments(files, groups, defines)
# Make sure we found all the exported items
def check_complete(e):
if not e.complete():
raise Exception("""Missing export: %s %s.
Hint: Add appropriate headers to the \"files\" array in exported_symbols.json""" % (e, str(e.__dict__)))
exports.walk_tree(exports_tree, check_complete)
pebble_app_h_text_to_inject = PEBBLE_APP_H_TEXT + \
'\n'.join(platform_info['ADDITIONAL_TEXT_LINES_FOR_PEBBLE_H'])
# Build pebble.h and pebble_worker.h for our apps to include
for type_name_prefix in [('app', 'pebble.h', pebble_app_h_text_to_inject),
('worker', 'pebble_worker.h', None),
('worker_only', 'doxygen/pebble_worker.h', None)]:
sdk_header_filename = path.join(sdk_include_dir, type_name_prefix[1])
make_app_header(exports_tree, sdk_header_filename, type_name_prefix[0], type_name_prefix[2])
def function_export_compare_func(x, y):
if (x.added_revision != y.added_revision):
return cmp(x.added_revision, y.added_revision)
return cmp(x.sort_name, y.sort_name)
sorted_functions = sorted(functions, cmp=function_export_compare_func)
# Build libpebble.a for our apps to compile against
make_app_shim_lib(sorted_functions, sdk_lib_dir)
# Build pebble.auto.c to build into our firmware
make_fw_shims(sorted_functions, pbl_output_src_dir)
# Build .json API description, used as input for static analysis tools:
make_json_api_description(sorted_functions, pbl_output_src_dir)
for filename, functions in (('pebble_sdk_version.h',
(f for f in functions if not f.worker_only)),
('pebble_worker_sdk_version.h',
(f for f in functions if not f.app_only))):
generate_app_sdk_version_header(path.join(sdk_include_dir, filename), functions)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Auto-generate the Pebble native SDK files')
parser.add_argument("--sdk-dir", dest="sdk_dir",
help="root of the SDK dir",
metavar="SDKDIR",
required=True)
parser.add_argument("config")
parser.add_argument("src_dir")
parser.add_argument("output_dir")
parser.add_argument("platform_name")
parser.add_argument("--internal-sdk-build", action="store_true", help="build internal SDK")
options = parser.parse_args()
shim_config = path.normpath(path.abspath(options.config))
pbl_src_dir = path.normpath(path.abspath(options.src_dir))
pbl_output_src_dir = path.normpath(path.abspath(options.output_dir))
sdk_include_dir = path.join(path.abspath(options.sdk_dir), INCLUDE_DIR)
sdk_lib_dir = path.join(path.abspath(options.sdk_dir), LIB_DIR)
if not path.isdir(pbl_src_dir):
raise RuntimeError("'%s' does not exist" % pbl_src_dir)
for d in (sdk_include_dir, sdk_lib_dir):
if not path.isdir(d):
os.makedirs(d)
shutil.copy(path.join(pbl_src_dir, 'fw', 'process_management', 'pebble_process_info.h'),
path.join(sdk_include_dir, 'pebble_process_info.h'))
shutil.copy(path.join(pbl_src_dir, 'fw/applib/graphics', 'gcolor_definitions.h'),
path.join(sdk_include_dir, 'gcolor_definitions.h'))
# Copy unsupported function warnings header to SDK
shutil.copy(path.join(pbl_src_dir, 'fw', 'applib', 'pebble_warn_unsupported_functions.h'),
path.join(sdk_include_dir, 'pebble_warn_unsupported_functions.h'))
generate_shim_files(
shim_config,
pbl_src_dir,
pbl_output_src_dir,
sdk_include_dir,
sdk_lib_dir,
options.platform_name,
internal_sdk_build=options.internal_sdk_build)