Skip to content

Commit a44c215

Browse files
committed
test updating lvgl to master
1 parent 19a60b9 commit a44c215

File tree

3 files changed

+89
-54
lines changed

3 files changed

+89
-54
lines changed

ext_mod/lvgl/micropython.cmake

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ list(APPEND LV_CFLAGS
1313

1414
separate_arguments(SECOND_BUILD_ENV UNIX_COMMAND $ENV{SECOND_BUILD})
1515

16-
set(LVGL_HEADER "${BINDING_DIR}/build/lvgl_header.h")
16+
set(LVGL_DIR "${BINDING_DIR}/lib/lvgl")
17+
1718

1819
file(GLOB_RECURSE LVGL_HEADERS ${BINDING_DIR}/lib/lvgl/src/*.h ${BINDING_DIR}/lib/lv_conf.h)
1920

@@ -25,9 +26,10 @@ file(GLOB_RECURSE LVGL_HEADERS ${BINDING_DIR}/lib/lvgl/src/*.h ${BINDING_DIR}/li
2526
# found to go about doing it.
2627

2728
if(${SECOND_BUILD_ENV} EQUAL "0")
29+
2830
execute_process(
2931
COMMAND
30-
${Python3_EXECUTABLE} ${BINDING_DIR}/gen/$ENV{GEN_SCRIPT}_api_gen_mpy.py ${LV_CFLAGS} --output=${CMAKE_BINARY_DIR}/lv_mp.c --include=${BINDING_DIR}/lib --include=${BINDING_DIR}/lib/lvgl --board=$ENV{LV_PORT} --module_name=lvgl --module_prefix=lv --metadata=${CMAKE_BINARY_DIR}/lv_mp.c.json --header_file=${LVGL_HEADER}
32+
${Python3_EXECUTABLE} ${BINDING_DIR}/gen/$ENV{GEN_SCRIPT}_api_gen_mpy.py ${LV_CFLAGS} --output=${CMAKE_BINARY_DIR}/lv_mp.c --include=${BINDING_DIR}/lib --include=${BINDING_DIR}/lib/lvgl --board=$ENV{LV_PORT} --module_name=lvgl --module_prefix=lv --metadata=${CMAKE_BINARY_DIR}/lv_mp.c.json --header_file=${LVGL_DIR}/lvgl.h
3133
WORKING_DIRECTORY
3234
${CMAKE_CURRENT_LIST_DIR}
3335

ext_mod/lvgl/micropython.mk

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ LVGL_BINDING_DIR = $(subst /ext_mod/lvgl,,$(MOD_DIR))
88

99
LIB_DIR = $(LVGL_BINDING_DIR)/lib
1010
LVGL_DIR = $(LVGL_BINDING_DIR)/lib/lvgl
11-
LVGL_HEADER = $(LVGL_BINDING_DIR)/build/lvgl_header.h
1211

1312
CURRENT_DIR = $(LVGL_BINDING_DIR)/ext_mod/lvgl
1413
CFLAGS_USERMOD += -I$(LVGL_DIR)
@@ -37,7 +36,8 @@ SRC_USERMOD_C += $(LVGL_MPY)
3736
$(LVGL_MPY): $(ALL_LVGL_SRC) $(LVGL_BINDING_DIR)/gen/$(GEN_SCRIPT)_api_gen_mpy.py
3837
$(ECHO) "LVGL-GEN $@"
3938
$(Q)mkdir -p $(dir $@)
40-
$(Q)$(PYTHON) $(LVGL_BINDING_DIR)/gen/$(GEN_SCRIPT)_api_gen_mpy.py $(LV_CFLAGS) --board=$(LV_PORT) --output=$(LVGL_MPY) --include=$(LIB_DIR) --include=$(LVGL_DIR) --module_name=lvgl --module_prefix=lv --metadata=$(LVGL_MPY_METADATA) --header_file=$(LVGL_HEADER)
39+
40+
$(Q)$(PYTHON) $(LVGL_BINDING_DIR)/gen/$(GEN_SCRIPT)_api_gen_mpy.py $(LV_CFLAGS) --board=$(LV_PORT) --output=$(LVGL_MPY) --include=$(LIB_DIR) --include=$(LVGL_DIR) --module_name=lvgl --module_prefix=lv --metadata=$(LVGL_MPY_METADATA) --header_file=$(LVGL_DIR)/lvgl.h
4141

4242
.PHONY: LVGL_MPY
4343
LVGL_MPY: $(LVGL_MPY)

gen/python_api_gen_mpy.py

Lines changed: 83 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ def eprint(*args, **kwargs):
2525
# from pudb.remote import set_trace
2626
# set_trace(term_size=(180, 50))
2727

28-
from sys import argv
2928
import sys
3029
import os
3130

@@ -35,7 +34,8 @@ def eprint(*args, **kwargs):
3534
from os.path import commonprefix
3635

3736
script_path = dirname(abspath(__file__))
38-
pycparser_path = os.path.join(script_path, '..', 'lib', 'pycparser')
37+
project_path = os.path.abspath(os.path.join(script_path, '..'))
38+
pycparser_path = os.path.join(project_path, 'lib', 'pycparser')
3939

4040

4141
sys.path.insert(0, os.path.abspath(pycparser_path))
@@ -93,8 +93,7 @@ def Node__repr__(self):
9393
return result
9494

9595

96-
c_ast._repr = _repr
97-
setattr(c_ast.Node, '__repr__', Node__repr__)
96+
9897

9998

10099
#
@@ -110,15 +109,47 @@ def Node__repr__(self):
110109
argParser.add_argument('--board', dest='board', help='Board or OS', metavar='<Board or OS>', action='store', default='')
111110
argParser.add_argument('--output', dest='output', help='Output file path', metavar='<Output path>', action='store')
112111
argParser.add_argument('--debug', dest='debug', help='enable debugging output', action='store_true')
113-
argParser.add_argument('--header_file', dest='input', action='append', default=[])
112+
argParser.add_argument('--header_file', dest='header', action='store', default=None)
114113

115114
args, unknownargs = argParser.parse_known_args()
116115

117116
module_name = args.module_name
118117
module_prefix = args.module_prefix if args.module_prefix else args.module_name
119-
input_headers = args.input[:]
118+
input_header = args.header
120119
DEBUG = args.debug
121120

121+
lvgl_path = os.path.dirname(input_header)
122+
private_header = os.path.join(lvgl_path, 'lv_private.h')
123+
124+
lv_config_path = os.path.abspath(os.path.join(lvgl_path, '..', 'lv_conf.h'))
125+
gen_json_path = os.path.join(lvgl_path, 'scripts/gen_json')
126+
127+
sys.path.insert(0, gen_json_path)
128+
129+
original_nodes = {}
130+
131+
import inspect
132+
133+
for key, value in c_ast.__dict__.items():
134+
if inspect.isclass(value):
135+
original_nodes[key] = value
136+
137+
138+
import gen_json
139+
140+
141+
json_ast = gen_json.run(None, lv_config_path, False, os.path.join(project_path, 'build', 'lvgl_header.h'), False)
142+
lvgl_json = json_ast.to_dict()
143+
144+
145+
for key, value in original_nodes.items():
146+
setattr(c_ast, key, value)
147+
148+
149+
c_ast._repr = _repr
150+
setattr(c_ast.Node, '__repr__', Node__repr__)
151+
152+
122153
pp_file = args.output.rsplit('.', 1)[0] + '.pp'
123154

124155
if DEBUG:
@@ -269,7 +300,7 @@ def get_path(name: str, p: str) -> str:
269300
cpp_cmd.extend([f'-D{define}' for define in args.define])
270301
cpp_cmd.extend(['-DPYCPARSER', '-E', f'-I{fake_libc_path}'])
271302
cpp_cmd.extend([f'-I{include}' for include in args.include])
272-
cpp_cmd.append(f'"{input_headers[0]}"')
303+
cpp_cmd.append(f'"{input_header}"')
273304

274305

275306
if sys.platform.startswith('win'):
@@ -439,7 +470,7 @@ def function_prototype(func):
439470
create_obj_pattern = re.compile('^{prefix}_(.+)_create$'.format(prefix=module_prefix))
440471
lv_method_pattern = re.compile('^{prefix}_[^_]+_(.+)'.format(prefix=module_prefix), re.IGNORECASE)
441472
lv_base_obj_pattern = re.compile('^(struct _){{0,1}}{prefix}_{base_name}_t( [*]){{0,1}}'.format(prefix=module_prefix, base_name = base_obj_name))
442-
lv_str_enum_pattern = re.compile('^_{prefix}_STR_(.+)'.format(prefix=module_prefix.upper()))
473+
lv_str_enum_pattern = re.compile('^_?{prefix}_STR_(.+)'.format(prefix=module_prefix.upper()))
443474
lv_callback_type_pattern = re.compile('({prefix}_){{0,1}}(.+)_cb(_t){{0,1}}'.format(prefix=module_prefix))
444475
lv_global_callback_pattern = re.compile('.*g_cb_t')
445476
lv_func_returns_array = re.compile('.*_array$')
@@ -620,7 +651,7 @@ def is_struct(type):
620651
pp_data = f.read()
621652

622653
cparser = pycparser.CParser()
623-
ast = cparser.parse(pp_data, input_headers[0])
654+
ast = cparser.parse(pp_data, input_header)
624655

625656
forward_struct_decls = {}
626657

@@ -733,18 +764,17 @@ def my_excepthook(exc_type, exc_value, tb):
733764
synonym[t.declname] = t.type.name
734765
# eprint('%s === struct %s' % (t.declname, t.type.name))
735766
struct_typedefs = [typedef for typedef in typedefs if is_struct(typedef.type)]
736-
structs = collections.OrderedDict((typedef.declname, typedef.type) for typedef in struct_typedefs if typedef.declname and typedef.type.decls) # and not lv_base_obj_pattern.match(typedef.declname))
737767
structs_without_typedef = collections.OrderedDict((decl.type.name, decl.type) for decl in ast.ext if hasattr(decl, 'type') and is_struct(decl.type))
738-
#
739-
# # for typedefs that referenced to a forward declaration struct, replace it with the real definition.
740-
# for typedef in struct_typedefs:
741-
# if typedef.type.decls is None: # None means it's a forward declaration
742-
# struct_name = typedef.type.name
743-
# # check if it's found in `structs_without_typedef`. It actually has the typedef. Replace type with it.
744-
# if typedef.type.name in structs_without_typedef:
745-
# typedef.type = structs_without_typedef[struct_name]
746-
#
747-
# structs = collections.OrderedDict((typedef.declname, typedef.type) for typedef in struct_typedefs if typedef.declname and typedef.type.decls) # and not lv_base_obj_pattern.match(typedef.declname))
768+
769+
# for typedefs that referenced to a forward declaration struct, replace it with the real definition.
770+
for typedef in struct_typedefs:
771+
if typedef.type.decls is None: # None means it's a forward declaration
772+
struct_name = typedef.type.name
773+
# check if it's found in `structs_without_typedef`. It actually has the typedef. Replace type with it.
774+
if typedef.type.name in structs_without_typedef:
775+
typedef.type = structs_without_typedef[struct_name]
776+
777+
structs = collections.OrderedDict((typedef.declname, typedef.type) for typedef in struct_typedefs if typedef.declname and typedef.type.decls) # and not lv_base_obj_pattern.match(typedef.declname))
748778
structs.update(structs_without_typedef) # This is for struct without typedef
749779
explicit_structs = collections.OrderedDict((typedef.type.name, typedef.declname) for typedef in struct_typedefs if typedef.type.name) # and not lv_base_obj_pattern.match(typedef.type.name))
750780
opaque_structs = collections.OrderedDict((typedef.declname, c_ast.Struct(name=typedef.declname, decls=[])) for typedef in typedefs if isinstance(typedef.type, c_ast.Struct) and typedef.type.decls == None)
@@ -1202,6 +1232,8 @@ def register_int_ptr_type(convertor, *types):
12021232
# Emit Header
12031233
#
12041234

1235+
input_headers = [input_header, private_header]
1236+
12051237
print ("""
12061238
/*
12071239
* Auto-Generated file, DO NOT EDIT!
@@ -1237,7 +1269,7 @@ def register_int_ptr_type(convertor, *types):
12371269
{lv_headers}
12381270
""".format(
12391271
module_name = module_name,
1240-
cmd_line=' '.join(argv),
1272+
cmd_line=' '.join(sys.argv),
12411273
pp_cmd=pp_cmd,
12421274
objs=", ".join(['%s(%s)' % (objname, parent_obj_names[objname]) for objname in obj_names]),
12431275
lv_headers='\n'.join('#include "%s"' % header for header in input_headers)))
@@ -2218,7 +2250,7 @@ def register_int_ptr_type(convertor, *types):
22182250
enums[enum_name] = enum
22192251

22202252
for enum in [enum for enum in enums if len(enums[enum]) == 1 and enum.startswith('ENUM')]:
2221-
int_constants.append('%s_%s' % (enum, list(enums[enum].keys())[0]))
2253+
int_constants.append('%s_%s' % (enum, next(iter(enums[enum]))))
22222254
enum_name = '%s_%s' % (enum, list(enums[enum].keys())[0])
22232255
constant_metadata[enum_name.replace('ENUM_', '').replace('LV_', '')] = {'py_type': 'int', 'c_type': enum_name.replace('ENUM_', '')}
22242256
del enums[enum]
@@ -2327,14 +2359,17 @@ def get_user_data(func, func_name = None, containing_struct = None, containing_s
23272359
user_data = 'user_data'
23282360
user_data_found = user_data in [decl.name for decl in flatten_struct_decls]
23292361
# print('/* --> callback: user_data=%s user_data_found=%s containing_struct=%s */' % (user_data, user_data_found, containing_struct))
2330-
2331-
ud_accessors = get_user_data_accessors(containing_struct, containing_struct_name)
2332-
if user_data_found:
2333-
res = (user_data, )
2334-
else:
2335-
res = (None, )
2336-
2337-
return res + ud_accessors
2362+
if not user_data_found and lvgl_json is not None:
2363+
containing_struct_j = next((struct for struct in lvgl_json["structures"] if struct["name"] == struct_arg_type_name), None)
2364+
if (containing_struct_j is None
2365+
and struct_arg_type_name.startswith("lv_")
2366+
and None is not next((fwd_decl for fwd_decl in lvgl_json["forward_decls"] if fwd_decl["name"] == struct_arg_type_name), None)
2367+
):
2368+
struct_arg_type_name_with_underscore = "_" + struct_arg_type_name
2369+
containing_struct_j = next((struct for struct in lvgl_json["structures"] if struct["name"] == struct_arg_type_name_with_underscore), None)
2370+
if containing_struct_j is not None:
2371+
user_data_found = any(user_data == field["name"] for field in containing_struct_j["fields"])
2372+
return (user_data if user_data_found else None), *get_user_data_accessors(containing_struct, containing_struct_name)
23382373

23392374
#
23402375
# Generate structs when needed
@@ -2438,12 +2473,10 @@ def try_generate_struct(struct_name, struct):
24382473
gen_func_error(decl, "Missing 'user_data' as a field of the first parameter of the callback function '%s_%s_callback'" % (struct_name, func_name))
24392474
else:
24402475
gen_func_error(decl, "Missing 'user_data' member in struct '%s'" % struct_name)
2441-
2442-
write_cases.append('case MP_QSTR_{field}: data->{field} = {cast}mp_lv_callback(dest[1], {lv_callback} ,MP_QSTR_{struct_name}_{field}, {user_data}, NULL, NULL, NULL); break; // converting to callback {type_name}'.
2443-
format(struct_name = struct_name, field = sanitize(decl.name), lv_callback = lv_callback, user_data = full_user_data_ptr, type_name = type_name, cast = cast))
2444-
read_cases.append('case MP_QSTR_{field}: dest[0] = mp_lv_funcptr(&mp_{funcptr}_mpobj, {cast}data->{field}, {lv_callback} ,MP_QSTR_{struct_name}_{field}, {user_data}); break; // converting from callback {type_name}'.
2445-
format(struct_name = struct_name, field = sanitize(decl.name), lv_callback = lv_callback, funcptr = lv_to_mp_funcptr[type_name], user_data = full_user_data, type_name = type_name, cast = cast))
2446-
attribute_meta[sanitize(decl.name)] = {'py_type': 'Callable', 'c_type': type_name, 'is_writeable': True, 'is_readable': True}
2476+
write_cases.append('case MP_QSTR_{field}: data->{decl_name} = {cast}mp_lv_callback(dest[1], {lv_callback} ,MP_QSTR_{struct_name}_{field}, {user_data}, NULL, NULL, NULL); break; // converting to callback {type_name}'.
2477+
format(struct_name = struct_name, field = sanitize(decl.name), decl_name = decl.name, lv_callback = lv_callback, user_data = full_user_data_ptr, type_name = type_name, cast = cast))
2478+
read_cases.append('case MP_QSTR_{field}: dest[0] = mp_lv_funcptr(&mp_{funcptr}_mpobj, {cast}data->{decl_name}, {lv_callback} ,MP_QSTR_{struct_name}_{field}, {user_data}); break; // converting from callback {type_name}'.
2479+
format(struct_name = struct_name, field = sanitize(decl.name), decl_name = decl.name, lv_callback = lv_callback, funcptr = lv_to_mp_funcptr[type_name], user_data = full_user_data, type_name = type_name, cast = cast))
24472480
else:
24482481
user_data = None
24492482
# Only allow write to non-const members
@@ -2455,20 +2488,16 @@ def try_generate_struct(struct_name, struct):
24552488
if isinstance(decl.type, c_ast.ArrayDecl):
24562489
memcpy_size = 'sizeof(%s)*%s' % (gen.visit(decl.type.type), gen.visit(decl.type.dim))
24572490
if is_writeable:
2458-
write_cases.append('case MP_QSTR_{field}: memcpy((void*)&data->{field}, {cast}{convertor}(dest[1]), {size}); break; // converting to {type_name}'.
2459-
format(field = sanitize(decl.name), convertor = mp_to_lv_convertor, type_name = type_name, cast = cast, size = memcpy_size))
2460-
2461-
2462-
read_cases.append('case MP_QSTR_{field}: dest[0] = {convertor}({cast}data->{field}); break; // converting from {type_name}'.
2463-
format(field = sanitize(decl.name), convertor = lv_to_mp_convertor, type_name = type_name, cast = cast))
2491+
write_cases.append('case MP_QSTR_{field}: memcpy((void*)&data->{decl_name}, {cast}{convertor}(dest[1]), {size}); break; // converting to {type_name}'.
2492+
format(field = sanitize(decl.name), decl_name = decl.name, convertor = mp_to_lv_convertor, type_name = type_name, cast = cast, size = memcpy_size))
2493+
read_cases.append('case MP_QSTR_{field}: dest[0] = {convertor}({cast}data->{decl_name}); break; // converting from {type_name}'.
2494+
format(field = sanitize(decl.name), decl_name = decl.name, convertor = lv_to_mp_convertor, type_name = type_name, cast = cast))
24642495
else:
24652496
if is_writeable:
2466-
write_cases.append('case MP_QSTR_{field}: data->{field} = {cast}{convertor}(dest[1]); break; // converting to {type_name}'.
2467-
format(field = sanitize(decl.name), convertor = mp_to_lv_convertor, type_name = type_name, cast = cast))
2468-
2469-
read_cases.append(
2470-
'case MP_QSTR_{field}: dest[0] = {convertor}({cast}data->{field}); break; // converting from {type_name}'.
2471-
format(field=sanitize(decl.name), convertor=lv_to_mp_convertor, type_name=type_name, cast=cast))
2497+
write_cases.append('case MP_QSTR_{field}: data->{decl_name} = {cast}{convertor}(dest[1]); break; // converting to {type_name}'.
2498+
format(field = sanitize(decl.name), decl_name = decl.name, convertor = mp_to_lv_convertor, type_name = type_name, cast = cast))
2499+
read_cases.append('case MP_QSTR_{field}: dest[0] = {convertor}({cast}data->{decl_name}); break; // converting from {type_name}'.
2500+
format(field = sanitize(decl.name), decl_name = decl.name, convertor = lv_to_mp_convertor, type_name = type_name, cast = cast))
24722501
print('''
24732502
/*
24742503
* Struct {struct_name}
@@ -3082,7 +3111,7 @@ def gen_mp_func(func, obj_name):
30823111
prototype_str = gen.visit(function_prototype(func))
30833112
if prototype_str in func_prototypes:
30843113
original_func = func_prototypes[prototype_str]
3085-
if not original_func.name.endswith('cb_t') and generated_funcs[original_func.name] == True:
3114+
if generated_funcs[original_func.name] == True:
30863115
print("/* Reusing %s for %s */" % (original_func.name, func.name))
30873116
emit_func_obj(func.name, original_func.name, param_count, func.name, is_static_member(func, base_obj_type))
30883117

@@ -3158,7 +3187,11 @@ def gen_mp_func(func, obj_name):
31583187
func=func.name,
31593188
func_ptr=prototype_str,
31603189
print_func=gen.visit(func),
3161-
build_args="\n ".join(build_args),
3190+
build_args="\n ".join([build_mp_func_arg(arg, i, func, obj_name) for i,arg in enumerated_args
3191+
if isinstance(arg, c_ast.EllipsisParam) or
3192+
(not isinstance(arg.type, c_ast.TypeDecl)) or
3193+
(not isinstance(arg.type.type, c_ast.IdentifierType)) or
3194+
'void' not in arg.type.type.names]), # Handle the case of 'void' param which should be ignored
31623195
send_args=", ".join([(arg.name if (hasattr(arg, 'name') and arg.name) else ("arg%d" % i)) for i,arg in enumerate(args)]),
31633196
build_result=build_result,
31643197
build_return_value=build_return_value))

0 commit comments

Comments
 (0)