py: Implement very simple frozen modules support.
Only modules (not packages) supported now. Source modules can be converted to frozen module structures using tools/make-frozen.py script.
This commit is contained in:
parent
438b3d26b5
commit
640e0b221e
@ -32,6 +32,7 @@
|
|||||||
#define MICROPY_PY_IO (0)
|
#define MICROPY_PY_IO (0)
|
||||||
#define MICROPY_PY_STRUCT (0)
|
#define MICROPY_PY_STRUCT (0)
|
||||||
#define MICROPY_PY_SYS (0)
|
#define MICROPY_PY_SYS (0)
|
||||||
|
#define MICROPY_MODULE_FROZEN (0)
|
||||||
#define MICROPY_CPYTHON_COMPAT (0)
|
#define MICROPY_CPYTHON_COMPAT (0)
|
||||||
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE)
|
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE)
|
||||||
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE)
|
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE)
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "py/objmodule.h"
|
#include "py/objmodule.h"
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
#include "py/builtin.h"
|
#include "py/builtin.h"
|
||||||
|
#include "py/frozenmod.h"
|
||||||
|
|
||||||
#if 0 // print debugging info
|
#if 0 // print debugging info
|
||||||
#define DEBUG_PRINT (1)
|
#define DEBUG_PRINT (1)
|
||||||
@ -109,9 +110,7 @@ STATIC mp_import_stat_t find_file(const char *file_str, uint file_len, vstr_t *d
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void do_load(mp_obj_t module_obj, vstr_t *file) {
|
STATIC void do_load_from_lexer(mp_obj_t module_obj, mp_lexer_t *lex, const char *fname) {
|
||||||
// create the lexer
|
|
||||||
mp_lexer_t *lex = mp_lexer_new_from_file(vstr_str(file));
|
|
||||||
|
|
||||||
if (lex == NULL) {
|
if (lex == NULL) {
|
||||||
// we verified the file exists using stat, but lexer could still fail
|
// we verified the file exists using stat, but lexer could still fail
|
||||||
@ -119,7 +118,7 @@ STATIC void do_load(mp_obj_t module_obj, vstr_t *file) {
|
|||||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ImportError, "module not found"));
|
nlr_raise(mp_obj_new_exception_msg(&mp_type_ImportError, "module not found"));
|
||||||
} else {
|
} else {
|
||||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError,
|
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError,
|
||||||
"no module named '%s'", vstr_str(file)));
|
"no module named '%s'", fname));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,6 +132,12 @@ STATIC void do_load(mp_obj_t module_obj, vstr_t *file) {
|
|||||||
mp_parse_compile_execute(lex, MP_PARSE_FILE_INPUT, mod_globals, mod_globals);
|
mp_parse_compile_execute(lex, MP_PARSE_FILE_INPUT, mod_globals, mod_globals);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STATIC void do_load(mp_obj_t module_obj, vstr_t *file) {
|
||||||
|
// create the lexer
|
||||||
|
mp_lexer_t *lex = mp_lexer_new_from_file(vstr_str(file));
|
||||||
|
do_load_from_lexer(module_obj, lex, vstr_str(file));
|
||||||
|
}
|
||||||
|
|
||||||
mp_obj_t mp_builtin___import__(mp_uint_t n_args, const mp_obj_t *args) {
|
mp_obj_t mp_builtin___import__(mp_uint_t n_args, const mp_obj_t *args) {
|
||||||
#if DEBUG_PRINT
|
#if DEBUG_PRINT
|
||||||
DEBUG_printf("__import__:\n");
|
DEBUG_printf("__import__:\n");
|
||||||
@ -237,6 +242,15 @@ mp_obj_t mp_builtin___import__(mp_uint_t n_args, const mp_obj_t *args) {
|
|||||||
}
|
}
|
||||||
DEBUG_printf("Module not yet loaded\n");
|
DEBUG_printf("Module not yet loaded\n");
|
||||||
|
|
||||||
|
#if MICROPY_MODULE_FROZEN
|
||||||
|
mp_lexer_t *lex = mp_find_frozen_module(mod_str, mod_len);
|
||||||
|
if (lex != NULL) {
|
||||||
|
module_obj = mp_obj_new_module(MP_OBJ_QSTR_VALUE(module_name));
|
||||||
|
do_load_from_lexer(module_obj, lex, mod_str);
|
||||||
|
return module_obj;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
uint last = 0;
|
uint last = 0;
|
||||||
VSTR_FIXED(path, MICROPY_ALLOC_PATH_MAX)
|
VSTR_FIXED(path, MICROPY_ALLOC_PATH_MAX)
|
||||||
module_obj = MP_OBJ_NULL;
|
module_obj = MP_OBJ_NULL;
|
||||||
|
53
py/frozenmod.c
Normal file
53
py/frozenmod.c
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Micro Python project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 Paul Sokolovsky
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "py/lexer.h"
|
||||||
|
|
||||||
|
#if MICROPY_MODULE_FROZEN
|
||||||
|
|
||||||
|
extern const uint16_t mp_frozen_sizes[];
|
||||||
|
extern const char mp_frozen_content[];
|
||||||
|
|
||||||
|
mp_lexer_t *mp_find_frozen_module(const char *str, int len) {
|
||||||
|
const uint16_t *sz_ptr = mp_frozen_sizes;
|
||||||
|
const char *s = mp_frozen_content;
|
||||||
|
|
||||||
|
while (*sz_ptr) {
|
||||||
|
int l = strlen(s);
|
||||||
|
if (l == len && !memcmp(str, s, l)) {
|
||||||
|
s += l + 1;
|
||||||
|
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR_, s, *sz_ptr, 0);
|
||||||
|
return lex;
|
||||||
|
}
|
||||||
|
s += l + 1 + *sz_ptr++;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MICROPY_MODULE_FROZEN
|
27
py/frozenmod.h
Normal file
27
py/frozenmod.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Micro Python project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Damien P. George
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
mp_lexer_t *mp_find_frozen_module(const char *str, int len);
|
@ -328,6 +328,11 @@ typedef double mp_float_t;
|
|||||||
#define MICROPY_MODULE_WEAK_LINKS (0)
|
#define MICROPY_MODULE_WEAK_LINKS (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Whether frozen modules are supported
|
||||||
|
#ifndef MICROPY_MODULE_FROZEN
|
||||||
|
#define MICROPY_MODULE_FROZEN (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
// Whether you can override builtins in the builtins module
|
// Whether you can override builtins in the builtins module
|
||||||
#ifndef MICROPY_CAN_OVERRIDE_BUILTINS
|
#ifndef MICROPY_CAN_OVERRIDE_BUILTINS
|
||||||
#define MICROPY_CAN_OVERRIDE_BUILTINS (0)
|
#define MICROPY_CAN_OVERRIDE_BUILTINS (0)
|
||||||
|
1
py/py.mk
1
py/py.mk
@ -112,6 +112,7 @@ PY_O_BASENAME = \
|
|||||||
smallint.o \
|
smallint.o \
|
||||||
pfenv.o \
|
pfenv.o \
|
||||||
pfenv_printf.o \
|
pfenv_printf.o \
|
||||||
|
frozenmod.o \
|
||||||
../extmod/moductypes.o \
|
../extmod/moductypes.o \
|
||||||
../extmod/modujson.o \
|
../extmod/modujson.o \
|
||||||
../extmod/modure.o \
|
../extmod/modure.o \
|
||||||
|
50
tools/make-frozen.py
Executable file
50
tools/make-frozen.py
Executable file
@ -0,0 +1,50 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
#
|
||||||
|
# Create frozen modules structure for MicroPython.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
#
|
||||||
|
# Have a directory with modules to be frozen (only modules, not packages
|
||||||
|
# supported so far):
|
||||||
|
#
|
||||||
|
# frozen/foo.py
|
||||||
|
# frozen/bar.py
|
||||||
|
#
|
||||||
|
# Run script, passing path to the directory above:
|
||||||
|
#
|
||||||
|
# ./make-frozen.py frozen > frozen.c
|
||||||
|
#
|
||||||
|
# Include frozen.c in your build, having defined MICROPY_MODULE_FROZEN in
|
||||||
|
# config.
|
||||||
|
#
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
def module_name(f):
|
||||||
|
return f[:-len(".py")]
|
||||||
|
|
||||||
|
modules = []
|
||||||
|
|
||||||
|
for dirpath, dirnames, filenames in os.walk(sys.argv[1]):
|
||||||
|
for f in filenames:
|
||||||
|
st = os.stat(dirpath + "/" + f)
|
||||||
|
modules.append((f, st))
|
||||||
|
|
||||||
|
print("#include <stdint.h>")
|
||||||
|
print("const uint16_t mp_frozen_sizes[] = {")
|
||||||
|
|
||||||
|
for f, st in modules:
|
||||||
|
print("%d," % st.st_size)
|
||||||
|
|
||||||
|
print("0};")
|
||||||
|
|
||||||
|
print("const char mp_frozen_content[] = {")
|
||||||
|
for f, st in modules:
|
||||||
|
m = module_name(f)
|
||||||
|
print('"%s\\0"' % m)
|
||||||
|
data = open(sys.argv[1] + "/" + f).read()
|
||||||
|
data = repr(data)[1:-1]
|
||||||
|
data = data.replace('"', '\\"')
|
||||||
|
print('"%s"' % data)
|
||||||
|
print("};")
|
Loading…
x
Reference in New Issue
Block a user