From 0e977c00c4d0ad4a2b8b34491eb1c63f37187a25 Mon Sep 17 00:00:00 2001 From: armink Date: Sat, 19 Jan 2019 18:09:18 +0800 Subject: Sync from master (0889bafda8e03c6809d43ec87ee28b940efb28aa). --- tools/building.py | 11 ++- tools/mkdist.py | 2 +- tools/mkromfs.py | 264 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tools/vsc.py | 4 +- 4 files changed, 276 insertions(+), 5 deletions(-) create mode 100644 tools/mkromfs.py (limited to 'tools') diff --git a/tools/building.py b/tools/building.py index 57e58b9ab0..978c0f7237 100644 --- a/tools/building.py +++ b/tools/building.py @@ -273,6 +273,13 @@ def PrepareBuilding(env, root_directory, has_libcpu=False, remove_components = [ env['LIBLINKSUFFIX'] = '.lib' env['LIBDIRPREFIX'] = '--userlibpath ' + elif rtconfig.PLATFORM == 'iar': + env['LIBPREFIX'] = '' + env['LIBSUFFIX'] = '.a' + env['LIBLINKPREFIX'] = '' + env['LIBLINKSUFFIX'] = '.a' + env['LIBDIRPREFIX'] = '--search ' + # patch for win32 spawn if env['PLATFORM'] == 'win32': win32_spawn = Win32Spawn() @@ -286,8 +293,8 @@ def PrepareBuilding(env, root_directory, has_libcpu=False, remove_components = [ # add program path env.PrependENVPath('PATH', rtconfig.EXEC_PATH) - # add rtconfig.h path - env.Append(CPPPATH = [str(Dir('#').abspath)]) + # add rtconfig.h/BSP path into Kernel group + DefineGroup("Kernel", [], [], CPPPATH=[str(Dir('#').abspath)]) # add library build action act = SCons.Action.Action(BuildLibInstallAction, 'Install compiled library... $TARGET') diff --git a/tools/mkdist.py b/tools/mkdist.py index cf30e95284..9d90e95e55 100644 --- a/tools/mkdist.py +++ b/tools/mkdist.py @@ -119,7 +119,7 @@ def bsp_update_kconfig(dist_dir): found = 1 if line.find('default') != -1 and found: position = line.find('default') - line = line[0:position] + 'default: "rt-thread"\n' + line = line[0:position] + 'default "rt-thread"\n' found = 0 f.write(line) diff --git a/tools/mkromfs.py b/tools/mkromfs.py new file mode 100644 index 0000000000..5371106987 --- /dev/null +++ b/tools/mkromfs.py @@ -0,0 +1,264 @@ +#!/usr/bin/env python + +import sys +import os + +import struct +from collections import namedtuple +import StringIO + +import argparse +parser = argparse.ArgumentParser() +parser.add_argument('rootdir', type=str, help='the path to rootfs') +parser.add_argument('output', type=argparse.FileType('wb'), nargs='?', help='output file name') +parser.add_argument('--dump', action='store_true', help='dump the fs hierarchy') +parser.add_argument('--binary', action='store_true', help='output binary file') +parser.add_argument('--addr', default='0', help='set the base address of the binary file, default to 0.') + +class File(object): + def __init__(self, name): + self._name = name + self._data = open(name, 'rb').read() + + @property + def name(self): + return self._name + + @property + def c_name(self): + return '_' + self._name.replace('.', '_') + + @property + def bin_name(self): + # Pad to 4 bytes boundary with \0 + pad_len = 4 + bn = self._name + '\0' * (pad_len - len(self._name) % pad_len) + return bn + + def c_data(self, prefix=''): + '''Get the C code represent of the file content.''' + head = 'static const rt_uint8_t %s[] = {\n' % \ + (prefix + self.c_name) + tail = '\n};' + + if self.entry_size == 0: + return '' + + return head + ','.join(('0x%02x' % ord(i) for i in self._data)) + tail + + @property + def entry_size(self): + return len(self._data) + + def bin_data(self, base_addr=0x0): + return bytes(self._data) + + def dump(self, indent=0): + print('%s%s' % (' ' * indent, self._name)) + +class Folder(object): + bin_fmt = struct.Struct('IIII') + bin_item = namedtuple('dirent', 'type, name, data, size') + + def __init__(self, name): + self._name = name + self._children = [] + + @property + def name(self): + return self._name + + @property + def c_name(self): + # add _ to avoid conflict with C key words. + return '_' + self._name + + @property + def bin_name(self): + # Pad to 4 bytes boundary with \0 + pad_len = 4 + bn = self._name + '\0' * (pad_len - len(self._name) % pad_len) + return bn + + def walk(self): + # os.listdir will return unicode list if the argument is unicode. + # TODO: take care of the unicode names + for ent in os.listdir(u'.'): + if os.path.isdir(ent): + cwd = os.getcwdu() + d = Folder(ent) + # depth-first + os.chdir(os.path.join(cwd, ent)) + d.walk() + # restore the cwd + os.chdir(cwd) + self._children.append(d) + else: + self._children.append(File(ent)) + + def sort(self): + def _sort(x, y): + if x.name == y.name: + return 0 + elif x.name > y.name: + return 1 + else: + return -1 + self._children.sort(cmp=_sort) + + # sort recursively + for c in self._children: + if isinstance(c, Folder): + c.sort() + + def dump(self, indent=0): + print('%s%s' % (' ' * indent, self._name)) + for c in self._children: + c.dump(indent + 1) + + def c_data(self, prefix=''): + '''get the C code represent of the folder. + + It is recursive.''' + # make the current dirent + # static is good. Only root dirent is global visible. + if self.entry_size == 0: + return '' + + dhead = 'static const struct romfs_dirent %s[] = {\n' % (prefix + self.c_name) + dtail = '\n};' + body_fmt = ' {{{type}, "{name}", (rt_uint8_t *){data}, sizeof({data})/sizeof({data}[0])}}' + body_fmt0= ' {{{type}, "{name}", RT_NULL, 0}}' + # prefix of children + cpf = prefix+self.c_name + body_li = [] + payload_li = [] + for c in self._children: + entry_size = c.entry_size + if isinstance(c, File): + tp = 'ROMFS_DIRENT_FILE' + elif isinstance(c, Folder): + tp = 'ROMFS_DIRENT_DIR' + else: + assert False, 'Unkown instance:%s' % str(c) + if entry_size == 0: + body_li.append(body_fmt0.format(type=tp, name = c.name)) + else: + body_li.append(body_fmt.format(type=tp, + name=c.name, + data=cpf+c.c_name)) + payload_li.append(c.c_data(prefix=cpf)) + + # All the data we need is defined in payload so we should append the + # dirent to it. It also meet the depth-first policy in this code. + payload_li.append(dhead + ',\n'.join(body_li) + dtail) + + return '\n\n'.join(payload_li) + + @property + def entry_size(self): + return len(self._children) + + def bin_data(self, base_addr=0x0): + '''Return StringIO object''' + # The binary layout is different from the C code layout. We put the + # dirent before the payload in this mode. But the idea is still simple: + # Depth-First. + + #{ + # rt_uint32_t type; + # const char *name; + # const rt_uint8_t *data; + # rt_size_t size; + #} + d_li = [] + # payload base + p_base = base_addr + self.bin_fmt.size * self.entry_size + # the length to record how many data is in + v_len = p_base + # payload + p_li = [] + for c in self._children: + if isinstance(c, File): + # ROMFS_DIRENT_FILE + tp = 0 + elif isinstance(c, Folder): + # ROMFS_DIRENT_DIR + tp = 1 + else: + assert False, 'Unkown instance:%s' % str(c) + + name = bytes(c.bin_name) + name_addr = v_len + v_len += len(name) + + data = c.bin_data(base_addr=v_len) + data_addr = v_len + # pad the data to 4 bytes boundary + pad_len = 4 + if len(data) % pad_len != 0: + data += '\0' * (pad_len - len(data) % pad_len) + v_len += len(data) + + d_li.append(self.bin_fmt.pack(*self.bin_item( + type=tp, + name=name_addr, + data=data_addr, + size=c.entry_size))) + + p_li.extend((name, data)) + + return bytes().join(d_li) + bytes().join(p_li) + +def get_c_data(tree): + # Handle the root dirent specially. + root_dirent_fmt = '''/* Generated by mkromfs. Edit with caution. */ +#include +#include + +{data} + +const struct romfs_dirent {name} = {{ + ROMFS_DIRENT_DIR, "/", (rt_uint8_t *){rootdirent}, sizeof({rootdirent})/sizeof({rootdirent}[0]) +}}; +''' + + return root_dirent_fmt.format(name='romfs_root', + rootdirent=tree.c_name, + data=tree.c_data()) + +def get_bin_data(tree, base_addr): + v_len = base_addr + Folder.bin_fmt.size + name = bytes('/\0\0\0') + name_addr = v_len + v_len += len(name) + data_addr = v_len + # root entry + data = Folder.bin_fmt.pack(*Folder.bin_item(type=1, + name=name_addr, + data=data_addr, + size=tree.entry_size)) + return data + name + tree.bin_data(v_len) + +if __name__ == '__main__': + args = parser.parse_args() + + os.chdir(args.rootdir) + + tree = Folder('romfs_root') + tree.walk() + tree.sort() + + if args.dump: + tree.dump() + + if args.binary: + data = get_bin_data(tree, int(args.addr, 16)) + else: + data = get_c_data(tree) + + output = args.output + if not output: + output = sys.stdout + + output.write(data) diff --git a/tools/vsc.py b/tools/vsc.py index 6a978c1e39..99a49789b7 100644 --- a/tools/vsc.py +++ b/tools/vsc.py @@ -64,13 +64,13 @@ def GenerateCFiles(env): json_obj = {} json_obj['configurations'] = [config_obj] - vsc_file.write(json.dumps(json_obj, indent=4)) + vsc_file.write(json.dumps(json_obj, ensure_ascii=False, indent=4)) vsc_file.close() return def GenerateVSCode(env): - print('Update setting files for VSCode...'), + print('Update setting files for VSCode...') GenerateCFiles(env) print('Done!') -- cgit v1.3.1