Last active
September 23, 2020 19:19
-
-
Save gvanem/dc378254510f41c6760b176e18532422 to your computer and use it in GitHub Desktop.
MicroPython. GNU-makefile and a 'lib_main.c' for MSVC or clang-cl.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * This file is part of the MicroPython project, http://micropython.org/ | |
| * | |
| * The MIT License (MIT) | |
| * | |
| * Copyright (c) 2013, 2014 Damien P. George | |
| * Copyright (c) 2014-2017 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. | |
| */ | |
| /* | |
| * Cooked from 'ports/unix/main.c' and created as the entry-point, | |
| * I.e. the 'mp_main()' for both the dynamic version of MicroPython (uPython.dll) | |
| * and the static version (uPython.lib). Ref. 'Py_Init()' in CPython. | |
| * | |
| * And there is no need for a 'DllMain()'. | |
| * | |
| * Caveats: | |
| * MICROPY_USE_READLINE == 1 is required | |
| * Removed all code for: | |
| * MICROPY_UNIX_COVERAGE | |
| * MICROPY_PY_BLUETOOTH | |
| */ | |
| #include <windows.h> | |
| #include <stdint.h> | |
| #include <stdbool.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <stdarg.h> | |
| #include <time.h> | |
| #include <unistd.h> | |
| #include <ctype.h> | |
| #include <sys/stat.h> | |
| #include <sys/types.h> | |
| #include <errno.h> | |
| #include <signal.h> | |
| #if MICROPY_PY_LWIP | |
| #include <lwip/init.h> | |
| #include <lwip/sys.h> | |
| #include <lwip/tcpip.h> | |
| #include <lwip/dhcp.h> | |
| #include <lwip/netif.h> | |
| #include <lwip/apps/mdns.h> | |
| #include <ports/win32/cfg_file.h> | |
| #include <ports/win32/pcapif.h> | |
| static struct netif netif; | |
| static void mp_init_lwip (void); | |
| #endif | |
| #include "py/compile.h" | |
| #include "py/runtime.h" | |
| #include "py/builtin.h" | |
| #include "py/repl.h" | |
| #include "py/gc.h" | |
| #include "py/stackctrl.h" | |
| #include "py/mphal.h" | |
| #include "py/mpthread.h" | |
| #include "extmod/misc.h" | |
| #include "extmod/vfs.h" | |
| #include "extmod/vfs_posix.h" | |
| #include "genhdr/mpversion.h" | |
| #include "ports/unix/input.h" | |
| #include "lib/mp-readline/readline.h" | |
| #define PATHLIST_SEP_CHAR ';' | |
| // Command line options, with their defaults | |
| STATIC bool compile_only = false; | |
| STATIC uint emit_opt = MP_EMIT_OPT_NONE; | |
| #if MICROPY_ENABLE_GC | |
| // Heap size of GC heap (if enabled) | |
| // Make it larger on a 64 bit machine, because pointers are larger. | |
| long heap_size = 1024 * 1024 * (sizeof(mp_uint_t) / 4); | |
| #endif | |
| STATIC void stderr_print_strn(void *env, const char *str, size_t len) { | |
| (void)env; | |
| ssize_t ret; | |
| MP_HAL_RETRY_SYSCALL(ret, write(STDERR_FILENO, str, len), {}); | |
| mp_uos_dupterm_tx_strn(str, len); | |
| } | |
| const mp_print_t mp_stderr_print = {NULL, stderr_print_strn}; | |
| #define FORCED_EXIT (0x100) | |
| // If exc is SystemExit, return value where FORCED_EXIT bit set, | |
| // and lower 8 bits are SystemExit value. For all other exceptions, | |
| // return 1. | |
| STATIC int handle_uncaught_exception(mp_obj_base_t *exc) { | |
| // check for SystemExit | |
| if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(exc->type), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) { | |
| // None is an exit value of 0; an int is its value; anything else is 1 | |
| mp_obj_t exit_val = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(exc)); | |
| mp_int_t val = 0; | |
| if (exit_val != mp_const_none && !mp_obj_get_int_maybe(exit_val, &val)) { | |
| val = 1; | |
| } | |
| return FORCED_EXIT | (val & 255); | |
| } | |
| // Report all other exceptions | |
| mp_obj_print_exception(&mp_stderr_print, MP_OBJ_FROM_PTR(exc)); | |
| return 1; | |
| } | |
| #define LEX_SRC_STR (1) | |
| #define LEX_SRC_VSTR (2) | |
| #define LEX_SRC_FILENAME (3) | |
| #define LEX_SRC_STDIN (4) | |
| // Returns standard error codes: 0 for success, 1 for all other errors, | |
| // except if FORCED_EXIT bit is set then script raised SystemExit and the | |
| // value of the exit is in the lower 8 bits of the return value | |
| STATIC int execute_from_lexer(int source_kind, const void *source, mp_parse_input_kind_t input_kind, bool is_repl) { | |
| mp_hal_set_interrupt_char(CHAR_CTRL_C); | |
| nlr_buf_t nlr; | |
| if (nlr_push(&nlr) == 0) { | |
| // create lexer based on source kind | |
| mp_lexer_t *lex; | |
| if (source_kind == LEX_SRC_STR) { | |
| const char *line = source; | |
| lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, line, strlen(line), false); | |
| } else if (source_kind == LEX_SRC_VSTR) { | |
| const vstr_t *vstr = source; | |
| lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr->buf, vstr->len, false); | |
| } else if (source_kind == LEX_SRC_FILENAME) { | |
| lex = mp_lexer_new_from_file((const char *)source); | |
| } else { // LEX_SRC_STDIN | |
| lex = mp_lexer_new_from_fd(MP_QSTR__lt_stdin_gt_, 0, false); | |
| } | |
| qstr source_name = lex->source_name; | |
| #if MICROPY_PY___FILE__ | |
| if (input_kind == MP_PARSE_FILE_INPUT) { | |
| mp_store_global(MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name)); | |
| } | |
| #endif | |
| mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); | |
| mp_obj_t module_fun = mp_compile(&parse_tree, source_name, is_repl); | |
| if (!compile_only) { | |
| // execute it | |
| mp_call_function_0(module_fun); | |
| } | |
| mp_hal_set_interrupt_char(-1); | |
| mp_handle_pending(true); | |
| nlr_pop(); | |
| return 0; | |
| } else { | |
| // uncaught exception | |
| mp_hal_set_interrupt_char(-1); | |
| mp_handle_pending(false); | |
| return handle_uncaught_exception(nlr.ret_val); | |
| } | |
| } | |
| STATIC int do_repl(void) { | |
| mp_hal_stdout_tx_str("MicroPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " | |
| MICROPY_PY_SYS_PLATFORM " version\nUse Ctrl-D to exit, Ctrl-E for paste mode\n"); | |
| // use MicroPython supplied readline | |
| vstr_t line; | |
| vstr_init(&line, 16); | |
| for (;;) { | |
| mp_hal_stdio_mode_raw(); | |
| input_restart: | |
| vstr_reset(&line); | |
| int ret = readline(&line, ">>> "); | |
| mp_parse_input_kind_t parse_input_kind = MP_PARSE_SINGLE_INPUT; | |
| if (ret == CHAR_CTRL_C) { | |
| // cancel input | |
| mp_hal_stdout_tx_str("\r\n"); | |
| goto input_restart; | |
| } else if (ret == CHAR_CTRL_D) { | |
| // EOF | |
| printf("\n"); | |
| mp_hal_stdio_mode_orig(); | |
| vstr_clear(&line); | |
| return 0; | |
| } else if (ret == CHAR_CTRL_E) { | |
| // paste mode | |
| mp_hal_stdout_tx_str("\npaste mode; Ctrl-C to cancel, Ctrl-D to finish\n=== "); | |
| vstr_reset(&line); | |
| for (;;) { | |
| char c = mp_hal_stdin_rx_chr(); | |
| if (c == CHAR_CTRL_C) { | |
| // cancel everything | |
| mp_hal_stdout_tx_str("\n"); | |
| goto input_restart; | |
| } else if (c == CHAR_CTRL_D) { | |
| // end of input | |
| mp_hal_stdout_tx_str("\n"); | |
| break; | |
| } else { | |
| // add char to buffer and echo | |
| vstr_add_byte(&line, c); | |
| if (c == '\r') { | |
| mp_hal_stdout_tx_str("\n=== "); | |
| } else { | |
| mp_hal_stdout_tx_strn(&c, 1); | |
| } | |
| } | |
| } | |
| parse_input_kind = MP_PARSE_FILE_INPUT; | |
| } else if (line.len == 0) { | |
| if (ret != 0) { | |
| printf("\n"); | |
| } | |
| goto input_restart; | |
| } else { | |
| // got a line with non-zero length, see if it needs continuing | |
| while (mp_repl_continue_with_input(vstr_null_terminated_str(&line))) { | |
| vstr_add_byte(&line, '\n'); | |
| ret = readline(&line, "... "); | |
| if (ret == CHAR_CTRL_C) { | |
| // cancel everything | |
| printf("\n"); | |
| goto input_restart; | |
| } else if (ret == CHAR_CTRL_D) { | |
| // stop entering compound statement | |
| break; | |
| } | |
| } | |
| } | |
| mp_hal_stdio_mode_orig(); | |
| ret = execute_from_lexer(LEX_SRC_VSTR, &line, parse_input_kind, true); | |
| if (ret & FORCED_EXIT) { | |
| return ret; | |
| } | |
| } | |
| } | |
| STATIC int do_file(const char *file) { | |
| return execute_from_lexer(LEX_SRC_FILENAME, file, MP_PARSE_FILE_INPUT, false); | |
| } | |
| STATIC int do_str(const char *str) { | |
| return execute_from_lexer(LEX_SRC_STR, str, MP_PARSE_FILE_INPUT, false); | |
| } | |
| STATIC void print_help(char **argv) { | |
| printf( | |
| "usage: %s [<opts>] [-X <implopt>] [-c <command> | -m <module> | <filename>]\n" | |
| "Options:\n" | |
| "-h : print this help message\n" | |
| "-i : enable inspection via REPL after running command/module/file\n" | |
| #if MICROPY_DEBUG_PRINTERS | |
| "-v : verbose (trace various operations); can be multiple\n" | |
| #endif | |
| "-O[N] : apply bytecode optimizations of level N\n" | |
| "\n" | |
| "Implementation specific options (-X):\n", argv[0] | |
| ); | |
| int impl_opts_cnt = 0; | |
| printf( | |
| " compile-only -- parse and compile only\n" | |
| #if MICROPY_EMIT_NATIVE | |
| " emit={bytecode,native,viper} -- set the default code emitter\n" | |
| #else | |
| " emit=bytecode -- set the default code emitter\n" | |
| #endif | |
| ); | |
| impl_opts_cnt++; | |
| #if MICROPY_ENABLE_GC | |
| printf( | |
| " heapsize=<n>[w][K|M] -- set the heap size for the GC (default %ld)\n" | |
| , heap_size); | |
| impl_opts_cnt++; | |
| #endif | |
| if (impl_opts_cnt == 0) { | |
| printf(" (none)\n"); | |
| } | |
| } | |
| STATIC int invalid_args(void) { | |
| fprintf(stderr, "Invalid command line arguments. Use -h option for help.\n"); | |
| return 1; | |
| } | |
| // Process options which set interpreter init options | |
| STATIC void pre_process_options(int argc, char **argv) { | |
| for (int a = 1; a < argc; a++) { | |
| if (argv[a][0] == '-') { | |
| if (strcmp(argv[a], "-h") == 0) { | |
| print_help(argv); | |
| exit(0); | |
| } | |
| if (strcmp(argv[a], "-X") == 0) { | |
| if (a + 1 >= argc) { | |
| exit(invalid_args()); | |
| } | |
| if (0) { | |
| } else if (strcmp(argv[a + 1], "compile-only") == 0) { | |
| compile_only = true; | |
| } else if (strcmp(argv[a + 1], "emit=bytecode") == 0) { | |
| emit_opt = MP_EMIT_OPT_BYTECODE; | |
| #if MICROPY_EMIT_NATIVE | |
| } else if (strcmp(argv[a + 1], "emit=native") == 0) { | |
| emit_opt = MP_EMIT_OPT_NATIVE_PYTHON; | |
| } else if (strcmp(argv[a + 1], "emit=viper") == 0) { | |
| emit_opt = MP_EMIT_OPT_VIPER; | |
| #endif | |
| #if MICROPY_ENABLE_GC | |
| } else if (strncmp(argv[a + 1], "heapsize=", sizeof("heapsize=") - 1) == 0) { | |
| char *end; | |
| heap_size = strtol(argv[a + 1] + sizeof("heapsize=") - 1, &end, 0); | |
| // Don't bring unneeded libc dependencies like tolower() | |
| // If there's 'w' immediately after number, adjust it for | |
| // target word size. Note that it should be *before* size | |
| // suffix like K or M, to avoid confusion with kilowords, | |
| // etc. the size is still in bytes, just can be adjusted | |
| // for word size (taking 32bit as baseline). | |
| bool word_adjust = false; | |
| if ((*end | 0x20) == 'w') { | |
| word_adjust = true; | |
| end++; | |
| } | |
| if ((*end | 0x20) == 'k') { | |
| heap_size *= 1024; | |
| } else if ((*end | 0x20) == 'm') { | |
| heap_size *= 1024 * 1024; | |
| } else { | |
| // Compensate for ++ below | |
| --end; | |
| } | |
| if (*++end != 0) { | |
| goto invalid_arg; | |
| } | |
| if (word_adjust) { | |
| heap_size = heap_size * BYTES_PER_WORD / 4; | |
| } | |
| // If requested size too small, we'll crash anyway | |
| if (heap_size < 700) { | |
| goto invalid_arg; | |
| } | |
| #endif | |
| } else { | |
| invalid_arg: | |
| exit(invalid_args()); | |
| } | |
| a++; | |
| } | |
| } | |
| } | |
| } | |
| STATIC void set_sys_argv(char *argv[], int argc, int start_arg) { | |
| for (int i = start_arg; i < argc; i++) { | |
| mp_obj_list_append(mp_sys_argv, MP_OBJ_NEW_QSTR(qstr_from_str(argv[i]))); | |
| } | |
| } | |
| int mp_main (int argc, char **argv) | |
| { | |
| #if MICROPY_PY_THREAD | |
| mp_thread_init(); | |
| #endif | |
| // We should capture stack top ASAP after start, and it should be | |
| // captured guaranteedly before any other stack variables are allocated. | |
| // For this, actual main (renamed mp_main) should not be inlined into | |
| // this function. mp_main() itself may have other functions inlined (with | |
| // their own stack variables), that's why we need this main/mp_main split. | |
| mp_stack_ctrl_init(); | |
| #if MICROPY_PY_LWIP | |
| mp_init_lwip(); | |
| #endif | |
| #ifdef SIGPIPE | |
| // Do not raise SIGPIPE, instead return EPIPE. Otherwise, e.g. writing | |
| // to peer-closed socket will lead to sudden termination of MicroPython | |
| // process. SIGPIPE is particularly nasty, because unix shell doesn't | |
| // print anything for it, so the above looks like completely sudden and | |
| // silent termination for unknown reason. Ignoring SIGPIPE is also what | |
| // CPython does. Note that this may lead to problems using MicroPython | |
| // scripts as pipe filters, but again, that's what CPython does. So, | |
| // scripts which want to follow unix shell pipe semantics (where SIGPIPE | |
| // means "pipe was requested to terminate, it's not an error"), should | |
| // catch EPIPE themselves. | |
| signal(SIGPIPE, SIG_IGN); | |
| #endif | |
| mp_stack_set_limit(40000 * (BYTES_PER_WORD / 4)); | |
| pre_process_options(argc, argv); | |
| #if MICROPY_ENABLE_GC | |
| char *heap = malloc(heap_size); | |
| gc_init(heap, heap + heap_size); | |
| #endif | |
| #if MICROPY_ENABLE_PYSTACK | |
| static mp_obj_t pystack[1024]; | |
| mp_pystack_init(pystack, &pystack[MP_ARRAY_SIZE(pystack)]); | |
| #endif | |
| mp_init(); | |
| #if MICROPY_EMIT_NATIVE | |
| // Set default emitter options | |
| MP_STATE_VM(default_emit_opt) = emit_opt; | |
| #else | |
| (void)emit_opt; | |
| #endif | |
| #if MICROPY_VFS_POSIX | |
| { | |
| // Mount the host FS at the root of our internal VFS | |
| mp_obj_t args[2] = { | |
| mp_type_vfs_posix.make_new(&mp_type_vfs_posix, 0, 0, NULL), | |
| MP_OBJ_NEW_QSTR(MP_QSTR__slash_), | |
| }; | |
| mp_vfs_mount(2, args, (mp_map_t *)&mp_const_empty_map); | |
| MP_STATE_VM(vfs_cur) = MP_STATE_VM(vfs_mount_table); | |
| } | |
| #endif | |
| char *home = getenv("APPDATA"); | |
| char *path = getenv("MICROPYPATH"); | |
| if (path == NULL) { | |
| #ifdef MICROPY_PY_SYS_PATH_DEFAULT | |
| path = MICROPY_PY_SYS_PATH_DEFAULT; | |
| #else | |
| path = "~/.micropython/lib:/usr/lib/micropython"; | |
| #endif | |
| } | |
| size_t path_num = 1; // [0] is for current dir (or base dir of the script) | |
| if (*path == PATHLIST_SEP_CHAR) { | |
| path_num++; | |
| } | |
| for (char *p = path; p != NULL; p = strchr(p, PATHLIST_SEP_CHAR)) { | |
| path_num++; | |
| if (p != NULL) { | |
| p++; | |
| } | |
| } | |
| mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_path), path_num); | |
| mp_obj_t *path_items; | |
| mp_obj_list_get(mp_sys_path, &path_num, &path_items); | |
| path_items[0] = MP_OBJ_NEW_QSTR(MP_QSTR_); | |
| { | |
| char *p = path; | |
| for (mp_uint_t i = 1; i < path_num; i++) { | |
| char *p1 = strchr(p, PATHLIST_SEP_CHAR); | |
| if (p1 == NULL) { | |
| p1 = p + strlen(p); | |
| } | |
| if (p[0] == '~' && p[1] == '/' && home != NULL) { | |
| // Expand standalone ~ to $HOME | |
| int home_l = strlen(home); | |
| vstr_t vstr; | |
| vstr_init(&vstr, home_l + (p1 - p - 1) + 1); | |
| vstr_add_strn(&vstr, home, home_l); | |
| vstr_add_strn(&vstr, p + 1, p1 - p - 1); | |
| path_items[i] = mp_obj_new_str_from_vstr(&mp_type_str, &vstr); | |
| } else { | |
| path_items[i] = mp_obj_new_str_via_qstr(p, p1 - p); | |
| } | |
| p = p1 + 1; | |
| } | |
| } | |
| mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_argv), 0); | |
| // Here is some example code to create a class and instance of that class. | |
| // First is the Python, then the C code. | |
| // | |
| // class TestClass: | |
| // pass | |
| // test_obj = TestClass() | |
| // test_obj.attr = 42 | |
| // | |
| // mp_obj_t test_class_type, test_class_instance; | |
| // test_class_type = mp_obj_new_type(QSTR_FROM_STR_STATIC("TestClass"), mp_const_empty_tuple, mp_obj_new_dict(0)); | |
| // mp_store_name(QSTR_FROM_STR_STATIC("test_obj"), test_class_instance = mp_call_function_0(test_class_type)); | |
| // mp_store_attr(test_class_instance, QSTR_FROM_STR_STATIC("attr"), mp_obj_new_int(42)); | |
| /* | |
| printf("bytes:\n"); | |
| printf(" total %d\n", m_get_total_bytes_allocated()); | |
| printf(" cur %d\n", m_get_current_bytes_allocated()); | |
| printf(" peak %d\n", m_get_peak_bytes_allocated()); | |
| */ | |
| const int NOTHING_EXECUTED = -2; | |
| int ret = NOTHING_EXECUTED; | |
| bool inspect = false; | |
| for (int a = 1; a < argc; a++) { | |
| if (argv[a][0] == '-') { | |
| if (strcmp(argv[a], "-i") == 0) { | |
| inspect = true; | |
| } else if (strcmp(argv[a], "-c") == 0) { | |
| if (a + 1 >= argc) { | |
| return invalid_args(); | |
| } | |
| ret = do_str(argv[a + 1]); | |
| if (ret & FORCED_EXIT) { | |
| break; | |
| } | |
| a += 1; | |
| } else if (strcmp(argv[a], "-m") == 0) { | |
| if (a + 1 >= argc) { | |
| return invalid_args(); | |
| } | |
| mp_obj_t import_args[4]; | |
| import_args[0] = mp_obj_new_str(argv[a + 1], strlen(argv[a + 1])); | |
| import_args[1] = import_args[2] = mp_const_none; | |
| // Ask __import__ to handle imported module specially - set its __name__ | |
| // to __main__, and also return this leaf module, not top-level package | |
| // containing it. | |
| import_args[3] = mp_const_false; | |
| // TODO: https://docs.python.org/3/using/cmdline.html#cmdoption-m : | |
| // "the first element of sys.argv will be the full path to | |
| // the module file (while the module file is being located, | |
| // the first element will be set to "-m")." | |
| set_sys_argv(argv, argc, a + 1); | |
| mp_obj_t mod; | |
| nlr_buf_t nlr; | |
| bool subpkg_tried = false; | |
| reimport: | |
| if (nlr_push(&nlr) == 0) { | |
| mod = mp_builtin___import__(MP_ARRAY_SIZE(import_args), import_args); | |
| nlr_pop(); | |
| } else { | |
| // uncaught exception | |
| return handle_uncaught_exception(nlr.ret_val) & 0xff; | |
| } | |
| if (mp_obj_is_package(mod) && !subpkg_tried) { | |
| subpkg_tried = true; | |
| vstr_t vstr; | |
| int len = strlen(argv[a + 1]); | |
| vstr_init(&vstr, len + sizeof(".__main__")); | |
| vstr_add_strn(&vstr, argv[a + 1], len); | |
| vstr_add_strn(&vstr, ".__main__", sizeof(".__main__") - 1); | |
| import_args[0] = mp_obj_new_str_from_vstr(&mp_type_str, &vstr); | |
| goto reimport; | |
| } | |
| ret = 0; | |
| break; | |
| } else if (strcmp(argv[a], "-X") == 0) { | |
| a += 1; | |
| #if MICROPY_DEBUG_PRINTERS | |
| } else if (strcmp(argv[a], "-v") == 0) { | |
| mp_verbose_flag++; | |
| #endif | |
| } else if (strncmp(argv[a], "-O", 2) == 0) { | |
| if (unichar_isdigit(argv[a][2])) { | |
| MP_STATE_VM(mp_optimise_value) = argv[a][2] & 0xf; | |
| } else { | |
| MP_STATE_VM(mp_optimise_value) = 0; | |
| for (char *p = argv[a] + 1; *p && *p == 'O'; p++, MP_STATE_VM(mp_optimise_value)++) {; | |
| } | |
| } | |
| } else { | |
| return invalid_args(); | |
| } | |
| } else { | |
| char *pathbuf = malloc(PATH_MAX); | |
| char *basedir = realpath(argv[a], pathbuf); | |
| if (basedir == NULL) { | |
| mp_printf(&mp_stderr_print, "%s: can't open file '%s': [Errno %d] %s\n", argv[0], argv[a], errno, strerror(errno)); | |
| // CPython exits with 2 in such case | |
| ret = 2; | |
| break; | |
| } | |
| // Set base dir of the script as first entry in sys.path | |
| char *p = strrchr(basedir, '/'); | |
| path_items[0] = mp_obj_new_str_via_qstr(basedir, p - basedir); | |
| free(pathbuf); | |
| set_sys_argv(argv, argc, a); | |
| ret = do_file(argv[a]); | |
| break; | |
| } | |
| } | |
| const char *inspect_env = getenv("MICROPYINSPECT"); | |
| if (inspect_env && inspect_env[0] != '\0') { | |
| inspect = true; | |
| } | |
| if (ret == NOTHING_EXECUTED || inspect) { | |
| if (isatty(0) || inspect) { | |
| prompt_read_history(); | |
| ret = do_repl(); | |
| prompt_write_history(); | |
| } else { | |
| ret = execute_from_lexer(LEX_SRC_STDIN, NULL, MP_PARSE_FILE_INPUT, false); | |
| } | |
| } | |
| #if MICROPY_PY_SYS_SETTRACE | |
| MP_STATE_THREAD(prof_trace_callback) = MP_OBJ_NULL; | |
| #endif | |
| #if MICROPY_PY_SYS_ATEXIT | |
| // Beware, the sys.settrace callback should be disabled before running sys.atexit. | |
| if (mp_obj_is_callable(MP_STATE_VM(sys_exitfunc))) { | |
| mp_call_function_0(MP_STATE_VM(sys_exitfunc)); | |
| } | |
| #endif | |
| #if MICROPY_PY_MICROPYTHON_MEM_INFO | |
| if (mp_verbose_flag) { | |
| mp_micropython_mem_info(0, NULL); | |
| } | |
| #endif | |
| #if MICROPY_PY_THREAD | |
| mp_thread_deinit(); | |
| #endif | |
| mp_deinit(); | |
| #if MICROPY_ENABLE_GC && !defined(NDEBUG) | |
| // We don't really need to free memory since we are about to exit the | |
| // process, but doing so helps to find memory leaks. | |
| free(heap); | |
| #endif | |
| // printf("total bytes = %d\n", m_get_total_bytes_allocated()); | |
| return ret & 0xff; | |
| } | |
| int mp_import_stat(const char *path) { | |
| struct stat st; | |
| if (stat(path, &st) == 0) { | |
| if (S_ISDIR(st.st_mode)) { | |
| return MP_IMPORT_STAT_DIR; | |
| } else if (S_ISREG(st.st_mode)) { | |
| return MP_IMPORT_STAT_FILE; | |
| } | |
| } | |
| return MP_IMPORT_STAT_NO_EXIST; | |
| } | |
| #if MICROPY_PY_IO | |
| // Factory function for I/O stream classes, only needed if generic VFS subsystem isn't used. | |
| // Note: buffering and encoding are currently ignored. | |
| mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kwargs) { | |
| enum { ARG_file, ARG_mode }; | |
| STATIC const mp_arg_t allowed_args[] = { | |
| { MP_QSTR_file, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = MP_ROM_NONE} }, | |
| { MP_QSTR_mode, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_QSTR(MP_QSTR_r)} }, | |
| { MP_QSTR_buffering, MP_ARG_INT, {.u_int = -1} }, | |
| { MP_QSTR_encoding, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, | |
| }; | |
| mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; | |
| mp_arg_parse_all(n_args, pos_args, kwargs, MP_ARRAY_SIZE(allowed_args), allowed_args, args); | |
| return mp_vfs_posix_file_open(&mp_type_textio, args[ARG_file].u_obj, args[ARG_mode].u_obj); | |
| } | |
| MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); | |
| #endif | |
| void nlr_jump_fail(void *val) { | |
| fprintf(stderr, "FATAL: uncaught NLR %p\n", val); | |
| exit(1); | |
| } | |
| #if MICROPY_PY_LWIP /* Rest of file */ | |
| static void status_callback (struct netif *state_netif) | |
| { | |
| if (netif_is_up(state_netif)) | |
| { | |
| LWIP_DEBUGF (LWIP_DBG_TRACE, ("status_callback == UP, local interface IP is %s\n", | |
| ip4addr_ntoa(netif_ip4_addr(state_netif)))); | |
| #if LWIP_MDNS_RESPONDER | |
| // mdns_resp_netif_settings_changed (state_netif); | |
| #endif | |
| } | |
| else | |
| LWIP_DEBUGF (LWIP_DBG_TRACE, ("status_callback == DOWN\n")); | |
| } | |
| static void link_callback (struct netif *state_netif) | |
| { | |
| LWIP_DEBUGF (LWIP_DBG_TRACE, ("link_callback == %s\n", netif_is_link_up(state_netif) ? "UP" : "DOWN")); | |
| } | |
| /* This function initializes all network interfaces | |
| */ | |
| static void mp_netif_init (void) | |
| { | |
| ip4_addr_t ipaddr, netmask, gw; | |
| err_t err; | |
| #define NETIF_ADDRS &ipaddr, &netmask, &gw, | |
| ip4_addr_set_zero (&gw); | |
| ip4_addr_set_zero (&ipaddr); | |
| ip4_addr_set_zero (&netmask); | |
| #if LWIP_DHCP | |
| LWIP_DEBUGF (LWIP_DBG_TRACE, ("Starting lwIP, local interface IP is dhcp-enabled\n")); | |
| #elif LWIP_AUTOIP | |
| LWIP_DEBUGF (LWIP_DBG_TRACE, ("Starting lwIP, local interface IP is autoip-enabled\n")); | |
| #else | |
| LWIP_PORT_INIT_GW (&gw); | |
| LWIP_PORT_INIT_IPADDR (&ipaddr); | |
| LWIP_PORT_INIT_NETMASK (&netmask); | |
| LWIP_DEBUGF (LWIP_DBG_TRACE, ("Starting lwIP, local interface IP is %s\n", ip4addr_ntoa(&ipaddr))); | |
| #endif | |
| netif_set_default (netif_add(&netif, NETIF_ADDRS NULL, pcapif_init, tcpip_input)); | |
| #if LWIP_NETIF_STATUS_CALLBACK | |
| netif_set_status_callback (&netif, status_callback); | |
| #endif | |
| #if LWIP_NETIF_LINK_CALLBACK | |
| netif_set_link_callback (&netif, link_callback); | |
| #endif | |
| netif_set_up (&netif); | |
| if (lwip_cfg.ip4.fixed_addr) | |
| { | |
| netif_set_ipaddr (&netif, (const ip4_addr_t*) &lwip_cfg.ip4.fixed_addr); | |
| netif_set_netmask (&netif, (const ip4_addr_t*) &lwip_cfg.ip4.fixed_netmask); | |
| netif_set_gw (&netif, (const ip4_addr_t*) &lwip_cfg.ip4.fixed_gateway); | |
| } | |
| else | |
| { | |
| err = dhcp_start (&netif); | |
| LWIP_ASSERT ("dhcp_start failed", err == ERR_OK); | |
| } | |
| } | |
| /* This function initializes all network apps. | |
| * Which should we do? | |
| */ | |
| static void mp_apps_init (void) | |
| { | |
| } | |
| static void test_init (void *arg) | |
| { | |
| sys_sem_t *init_sem; | |
| LWIP_DEBUGF (LWIP_DBG_TRACE, ("In %s().\n", __FUNCTION__)); | |
| LWIP_ASSERT ("arg != NULL", arg != NULL); | |
| init_sem = (sys_sem_t*)arg; | |
| srand ((unsigned int)time(NULL)); | |
| mp_netif_init(); | |
| mp_apps_init(); | |
| sys_sem_signal (init_sem); | |
| } | |
| static void mp_init_lwip (void) | |
| { | |
| sys_sem_t init_sem; | |
| err_t err; | |
| _lwip_trace_start (0, NULL, 0); | |
| err = sys_sem_new (&init_sem, 0); | |
| LWIP_ASSERT ("failed to create init_sem", err == ERR_OK); | |
| tcpip_init (test_init, &init_sem); | |
| /* we have to wait for initialization to finish before | |
| * calling update_adapter()! | |
| */ | |
| sys_sem_wait (&init_sem); | |
| sys_sem_free (&init_sem); | |
| #if LWIP_NETCONN_SEM_PER_THREAD | |
| netconn_thread_init(); | |
| #endif | |
| #if LWIP_MDNS_RESPONDER | |
| // mdns_resp_init(); | |
| #endif | |
| } | |
| #endif /* MICROPY_PY_LWIP */ | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # | |
| # Gnu Makefile for MicroPython (MSVC or clang-cl). | |
| # | |
| # This Makefile MUST be placed in the root-directory of your MicroPython installation. | |
| # | |
| # By G. Vanem <[email protected]> 2020. | |
| # | |
| THIS_FILE = Makefile.Windows | |
| TODAY = $(shell date +%d-%B-%Y) | |
| # | |
| # Set 'MDEPEND=' to NOT rebuild everything when this file changes. | |
| # It might be a good idea to delete '.depend.Windows' too. | |
| # | |
| MDEPEND = $(THIS_FILE) | |
| # | |
| # Support for the 'MbedTLS' crypto library. | |
| # | |
| USE_MBEDTLS ?= 1 | |
| # | |
| # Support for the 'LwIP' tcp/ip-stack. | |
| # | |
| USE_LWIP ?= 1 | |
| # | |
| # Support for 'Virtual File System'. | |
| # | |
| USE_VFS ?= 1 | |
| # | |
| # Support for a builtin "help()" command in the console. | |
| # | |
| USE_HELP_MODULES ?= 1 | |
| # | |
| # Let 'microPython.exe' use 'uPython.dll' | |
| # | |
| USE_uPython_DLL ?= 1 | |
| # | |
| # Use only dynamic foreign libraries for 'uPython.dll' (and 'MicroPython.exe' if 'USE_uPython_DLL=0'). | |
| # | |
| # With this option (and 'USE_LWIP=1' and 'USE_MBEDTLS=1', the dependencies looks like this: | |
| # | |
| # MicroPython.exe 11 kB! | |
| # uPython.dll 599 kB | |
| # lwip32.dll 259 kB | |
| # wpcap.dll | |
| # packet.dll | |
| # mbedcrypto.dll 622 kB | |
| # mbedtls.dll 190 kB | |
| # mbedcrypto.dll | |
| # mbedx509.dll 68 kB | |
| # mbedcrypto.dll | |
| # | |
| # As opposed to a 'uPython.dll' linked to only static libraries (except wpcap.dll): | |
| # | |
| # MicroPython.exe still only 11 kB | |
| # uPython.dll 1327 kB | |
| # wpcap.dll | |
| # packet.dll | |
| # | |
| USE_FOREIGN_DLLs ?= 1 | |
| # | |
| # For the '%.i' pre-processing rules below. | |
| # | |
| USE_CLANG_FORMATER ?= 0 | |
| USE_GNU_INDENT ?= 0 | |
| # | |
| # Compile a lot faster; MSVC only. | |
| # | |
| USE_MP_COMPILE ?= 1 | |
| # | |
| # For generating a lot of stuff. | |
| # | |
| PYTHON ?= py -3 | |
| VPATH = ports/windows \ | |
| ports/windows/msvc \ | |
| ports/unix \ | |
| extmod \ | |
| py \ | |
| lib/embed \ | |
| lib/mp-readline \ | |
| lib/netutils \ | |
| lib/oofatfs \ | |
| lib/timeutils \ | |
| lib/utils | |
| # | |
| # Extract from 'py/mpconfig.h': | |
| # | |
| get_ver_digit = $(shell grep --max-count=1 '#define MICROPY_VERSION_$(strip $(1))' py/mpconfig.h | cut -d' ' -f3) | |
| VER_MAJOR = $(call get_ver_digit, MAJOR) | |
| VER_MINOR = $(call get_ver_digit, MINOR) | |
| VER_MICRO = $(call get_ver_digit, MICRO) | |
| VERSION = $(VER_MAJOR).$(VER_MINOR).$(VER_MICRO) | |
| # | |
| # Root directories; change to suite: | |
| # | |
| LWIP_ROOT ?= f:/MinGW32/src/inet/LwIP | |
| MBEDTLS_ROOT ?= f:/MinGW32/src/inet/Crypto/MbedTLS | |
| PCAP_ROOT ?= f:/MinGW32/src/inet/libpcap | |
| WINPCAP_ROOT ?= f:/MinGW32/src/inet/libpcap/WinPcap | |
| # | |
| # What to build: | |
| # | |
| # The static library cannot be called 'MicroPython.lib' since MSVC link | |
| # wants to export stuff in the 'link_EXE, MicroPython.exe' command. | |
| # But only when 'USE_uPython_DLL=0'. | |
| # | |
| STAT_LIB = uPython.lib | |
| IMP_LIB = uPython_imp.lib | |
| TARGETS = $(STAT_LIB) \ | |
| $(IMP_LIB) \ | |
| uPython.dll \ | |
| MicroPython.exe | |
| define Usage | |
| Usage: make -f $(THIS_FILE) CC=[cl | clang-cl] [all | depend | clean | vclean | examples] | |
| Specify CC=cl - use MSVC | |
| Specify CC=clang-cl - use clang-cl | |
| endef | |
| # | |
| # A list of .obj-files from .c-files: | |
| # | |
| c_to_obj = $(addprefix $(OBJ_DIR)/, $(notdir $(1:.c=.obj))) | |
| # | |
| # This confuses 'clang-cl'. Drop it. | |
| # | |
| export CL= | |
| ifeq ($(CC),cl) | |
| RCFLAGS = -nologo -D_MSC_VER | |
| else ifeq ($(CC),clang-cl) | |
| RCFLAGS = -nologo -D__clang__ | |
| USE_MP_COMPILE = 0 | |
| else | |
| $(error $(Usage)) | |
| endif | |
| OBJ_DIR = objects | |
| # | |
| # Made by '$(call make_pp_file ...)' rules below: | |
| # | |
| Preprocessed_files = $(addprefix $(OBJ_DIR)/genhdr/qstr/, \ | |
| $(LIB_SRC:.c=.pp) \ | |
| ports/unix/main.pp) | |
| # | |
| # The generate-order for these is important: | |
| # | |
| GENERATED = $(addprefix $(OBJ_DIR)/genhdr/, \ | |
| moduledefs.h \ | |
| mpversion.h) \ | |
| \ | |
| $(Preprocessed_files) \ | |
| \ | |
| $(addprefix $(OBJ_DIR)/genhdr/, \ | |
| qstrdefs.collected.h \ | |
| qstrdefs.generated.h \ | |
| qstrdefs.preprocessed.h) | |
| LDFLAGS = -nologo -debug -incremental:no -verbose -subsystem:console -safeseh | |
| CFLAGS = -nologo -MD -W3 -Zi -Zo \ | |
| -D_CRT_SECURE_NO_WARNINGS \ | |
| -D_CRT_SECURE_NO_WARNINGS \ | |
| -D_CRT_NONSTDC_NO_WARNINGS \ | |
| -D_WIN32_WINNT=0x0601 \ | |
| -Oi -Ot -Oy | |
| CFLAGS += -D_USE_MATH_DEFINES \ | |
| -I. -I./ports/windows \ | |
| -I./ports/windows/msvc \ | |
| -I./$(OBJ_DIR) | |
| ifeq ($(CC),clang-cl) | |
| CFLAGS += -ferror-limit=5 \ | |
| -fms-compatibility | |
| endif | |
| # | |
| # NLR = 'Non Local Return'. We MUST use 'setjmp()' + 'longjmp()'. | |
| # Add some debug to it too. | |
| # | |
| CFLAGS += -DMICROPY_NLR_SETJMP=1 \ | |
| -DMICROPY_DEBUG_NLR=1 | |
| # CFLAGS += -DMICROPY_CPYTHON_COMPAT=0 | |
| CFLAGS += -DFFCONF_H=\"lib/oofatfs/ffconf.h\" | |
| ifeq ($(CC),gcc) | |
| CFLAGS += -D__USE_MINGW_ANSI_STDIO=1 | |
| endif | |
| ifeq ($(USE_VFS),1) | |
| CFLAGS += -DMICROPY_VFS=1 \ | |
| -DMICROPY_VFS_FAT=1 \ | |
| -DMICROPY_FATFS_RPATH=2 | |
| endif | |
| # | |
| # Check if these are possible on Windows: | |
| # | |
| CFLAGS += -DMICROPY_PY_SYS_SETTRACE=1 \ | |
| -DMICROPY_PERSISTENT_CODE_SAVE=1 \ | |
| -DMICROPY_COMP_CONST=0 \ | |
| -DMICROPY_PY_SYS_ATEXIT=1 \ | |
| -DMICROPY_EMIT_X86=1 | |
| # | |
| # We should never need this. | |
| # | |
| LDFLAGS += -nodefaultlib:uuid.lib | |
| # | |
| # Warning control: | |
| # | |
| ifeq ($(CC),cl) | |
| CFLAGS += -wd4005 -wd4113 -wd4146 -wd4244 -wd4267 | |
| else | |
| CFLAGS += -Wno-microsoft-include \ | |
| -Wno-visibility \ | |
| -Wno-pragma-pack \ | |
| -Wno-pointer-sign \ | |
| -Wno-macro-redefined \ | |
| -Wno-incompatible-pointer-types | |
| endif | |
| # | |
| # $(LIB_SRC): .c-sources for 'MicroPython.lib' | |
| # | |
| LIB_SRC = $(addprefix ports/windows/, \ | |
| fmode.c \ | |
| init.c \ | |
| lib_main.c \ | |
| realpath.c \ | |
| sleep.c \ | |
| windows_mphal.c) | |
| ifneq ($(CC),gcc) | |
| LIB_SRC += $(addprefix ports/windows/msvc/, \ | |
| dirent.c \ | |
| gettimeofday.c) | |
| endif | |
| LIB_SRC += $(addprefix ports/unix/, \ | |
| gccollect.c \ | |
| input.c \ | |
| modos.c \ | |
| modtime.c \ | |
| modmachine.c \ | |
| moduselect.c \ | |
| modusocket.c) | |
| LIB_SRC += $(addprefix py/, \ | |
| argcheck.c \ | |
| asmbase.c \ | |
| asmx64.c \ | |
| asmx86.c \ | |
| bc.c \ | |
| binary.c \ | |
| builtinevex.c \ | |
| builtinhelp.c \ | |
| builtinimport.c \ | |
| compile.c \ | |
| emitbc.c \ | |
| emitcommon.c \ | |
| emitglue.c \ | |
| emitnative.c \ | |
| emitnx64.c \ | |
| emitnx86.c \ | |
| formatfloat.c \ | |
| frozenmod.c \ | |
| gc.c \ | |
| lexer.c \ | |
| malloc.c \ | |
| map.c \ | |
| modarray.c \ | |
| modbuiltins.c \ | |
| modcmath.c \ | |
| modcollections.c \ | |
| modgc.c \ | |
| modio.c \ | |
| modmath.c \ | |
| modmicropython.c \ | |
| modstruct.c \ | |
| modsys.c \ | |
| modthread.c \ | |
| moduerrno.c \ | |
| mpprint.c \ | |
| mpstate.c \ | |
| mpz.c \ | |
| nativeglue.c \ | |
| nlr.c \ | |
| nlrsetjmp.c \ | |
| nlrx64.c \ | |
| nlrx86.c \ | |
| obj.c \ | |
| objarray.c \ | |
| objattrtuple.c \ | |
| objbool.c \ | |
| objboundmeth.c \ | |
| objcell.c \ | |
| objclosure.c \ | |
| objcomplex.c \ | |
| objdeque.c \ | |
| objdict.c \ | |
| objenumerate.c \ | |
| objexcept.c \ | |
| objfilter.c \ | |
| objfloat.c \ | |
| objfun.c \ | |
| objgenerator.c \ | |
| objgetitemiter.c \ | |
| objint.c \ | |
| objint_longlong.c \ | |
| objint_mpz.c \ | |
| objlist.c \ | |
| objmap.c \ | |
| objmodule.c \ | |
| objnamedtuple.c \ | |
| objnone.c \ | |
| objobject.c \ | |
| objpolyiter.c \ | |
| objproperty.c \ | |
| objrange.c \ | |
| objreversed.c \ | |
| objset.c \ | |
| objsingleton.c \ | |
| objslice.c \ | |
| objstr.c \ | |
| objstringio.c \ | |
| objstrunicode.c \ | |
| objtuple.c \ | |
| objtype.c \ | |
| objzip.c \ | |
| opmethods.c \ | |
| pairheap.c \ | |
| parse.c \ | |
| parsenum.c \ | |
| parsenumbase.c \ | |
| persistentcode.c \ | |
| profile.c \ | |
| pystack.c \ | |
| qstr.c \ | |
| reader.c \ | |
| repl.c \ | |
| ringbuf.c \ | |
| runtime.c \ | |
| runtime_utils.c \ | |
| scheduler.c \ | |
| scope.c \ | |
| sequence.c \ | |
| showbc.c \ | |
| smallint.c \ | |
| stackctrl.c \ | |
| stream.c \ | |
| unicode.c \ | |
| vm.c \ | |
| vstr.c \ | |
| warning.c) | |
| LIB_SRC += $(addprefix extmod/, \ | |
| machine_mem.c \ | |
| machine_pinbase.c \ | |
| machine_pulse.c \ | |
| machine_signal.c \ | |
| modubinascii.c \ | |
| moducryptolib.c \ | |
| moductypes.c \ | |
| modframebuf.c \ | |
| moduhashlib.c \ | |
| moduheapq.c \ | |
| modujson.c \ | |
| modurandom.c \ | |
| modure.c \ | |
| modutimeq.c \ | |
| moduwebsocket.c \ | |
| modwebrepl.c \ | |
| moduzlib.c \ | |
| uos_dupterm.c \ | |
| utime_mphal.c \ | |
| vfs.c \ | |
| vfs_blockdev.c \ | |
| vfs_fat.c \ | |
| vfs_fat_diskio.c \ | |
| vfs_fat_file.c \ | |
| vfs_lfs.c \ | |
| vfs_posix.c \ | |
| vfs_posix_file.c \ | |
| vfs_reader.c \ | |
| virtpin.c) | |
| LIB_SRC += lib/embed/abort_.c \ | |
| lib/mp-readline/readline.c \ | |
| lib/timeutils/timeutils.c \ | |
| lib/utils/gchelper_generic.c \ | |
| lib/utils/printf.c | |
| # | |
| # VFS on Windows!!? Will it do anything sensible? | |
| # | |
| ifeq ($(USE_VFS),1) | |
| LIB_SRC += extmod/vfs_fat_diskio.c \ | |
| lib/oofatfs/ff.c \ | |
| lib/oofatfs/ffunicode.c \ | |
| ports/unix/fatfs_port.c | |
| endif | |
| # | |
| # We never need these on Windows: | |
| # | |
| # LIB_SRC += $(addprefix py/, \ | |
| # asmarm.c \ | |
| # asmthumb.c \ | |
| # asmxtensa.c \ | |
| # emitinlinethumb.c \ | |
| # emitinlinextensa.c \ | |
| # emitnarm.c \ | |
| # emitnthumb.c \ | |
| # emitnxtensa.c \ | |
| # emitnxtensawin.c) | |
| ifeq ($(USE_LWIP),1) | |
| LIB_SRC += extmod/modlwip.c \ | |
| lib/netutils/netutils.c | |
| CFLAGS += -I$(LWIP_ROOT)/src/include \ | |
| -I$(LWIP_ROOT)/src/include/Win32-hdr \ | |
| -I$(LWIP_ROOT)/contrib \ | |
| -I$(LWIP_ROOT)/src/include/compat/posix \ | |
| -DMICROPY_PY_LWIP=1 \ | |
| -DMICROPY_PY_LWIP_SOCK_RAW=1 \ | |
| -DMICROPY_ENABLE_SCHEDULER=1 \ | |
| -DMICROPY_HAVE_SYS_ARCH_PROTECT=1 \ | |
| -DMICROPY_HAVE_SYS_ARCH_UNPROTECT=1 \ | |
| -DMICROPY_LWIP_HAVE_SIO=1 \ | |
| -DMICROPY_PY_SOCKET=1 \ | |
| -DMICROPY_PY_USOCKET=1 \ | |
| -DMICROPY_PY_USELECT_POSIX=1 \ | |
| # -DMICROPY_PY_LWIP_SLIP=1 | |
| ifeq ($(USE_FOREIGN_DLLs),1) | |
| CFLAGS += -DLWIP_DYNAMIC | |
| LWIP_LIBS = $(LWIP_ROOT)/lwip32_imp.lib \ | |
| $(PCAP_ROOT)/wpcap.lib | |
| else | |
| LWIP_LIBS = $(LWIP_ROOT)/lwip32.lib \ | |
| $(PCAP_ROOT)/wpcap.lib \ | |
| $(WINPCAP_ROOT)/lib/Packet.lib | |
| endif | |
| LWIP_LIBS += advapi32.lib | |
| endif | |
| ifeq ($(USE_MBEDTLS),1) | |
| CFLAGS += -I$(MBEDTLS_ROOT)/include \ | |
| -DMICROPY_PY_USSL=1 \ | |
| -DMICROPY_PY_UHASHLIB_MD5=1 \ | |
| -DMICROPY_PY_UHASHLIB_SHA1=1 \ | |
| -DMICROPY_PY_UCRYPTOLIB=1 \ | |
| -DMICROPY_SSL_MBEDTLS=1 | |
| LIB_SRC += extmod/modussl_mbedtls.c | |
| ifeq ($(USE_FOREIGN_DLLs),1) | |
| MBEDTLS_LIBS = $(addprefix $(MBEDTLS_ROOT)/library/, \ | |
| mbedcrypto_imp.lib \ | |
| mbedtls_imp.lib \ | |
| mbedx509_imp.lib) | |
| else | |
| MBEDTLS_LIBS = $(addprefix $(MBEDTLS_ROOT)/library/, \ | |
| mbedcrypto.lib \ | |
| mbedtls.lib \ | |
| mbedx509.lib) \ | |
| advapi32.lib | |
| endif | |
| endif | |
| ifeq ($(USE_HELP_MODULES),1) | |
| CFLAGS += -DMICROPY_PY_BUILTINS_HELP=1 \ | |
| -DMICROPY_PY_BUILTINS_HELP_MODULES=1 | |
| endif | |
| # | |
| # Does not work: | |
| # | |
| VPATH += examples/embedding | |
| EXAMPLES_SRC = $(addprefix examples/, \ | |
| embedding/hello-embed.c) | |
| LIB_OBJ = $(call c_to_obj, $(LIB_SRC)) | |
| EXAMPLES_OBJ = $(call c_to_obj, $(EXAMPLES_SRC)) | |
| EXAMPLES = $(notdir $(EXAMPLES_OBJ:.obj=.exe)) | |
| # | |
| # The libraries for example programs: (not yet) | |
| # | |
| PROG_INT_LIB = $(STAT_LIB) | |
| PROG_EXT_LIBS = $(LWIP_LIBS) | |
| all: mk_dirs $(GENERATED) $(TARGETS) epilogue | |
| epilogue: | |
| $(call green_msg, Welcome to MicroPython (VERSION=$(VERSION), CC=$(CC)).) | |
| $(call green_msg, You could do a $(BRIGHT_YELLOW)make -f Makefile.Windows CC=$(CC) examples$(BRIGHT_GREEN) too.) | |
| mk_dirs: | |
| - @mkdir --parents $(OBJ_DIR)/genhdr/qstr/ports/windows/msvc | |
| - @mkdir $(OBJ_DIR)/genhdr/qstr/extmod \ | |
| $(OBJ_DIR)/genhdr/qstr/lib \ | |
| $(OBJ_DIR)/genhdr/qstr/lib/embed \ | |
| $(OBJ_DIR)/genhdr/qstr/lib/mp-readline \ | |
| $(OBJ_DIR)/genhdr/qstr/lib/netutils \ | |
| $(OBJ_DIR)/genhdr/qstr/lib/oofatfs \ | |
| $(OBJ_DIR)/genhdr/qstr/lib/timeutils \ | |
| $(OBJ_DIR)/genhdr/qstr/lib/utils \ | |
| $(OBJ_DIR)/genhdr/qstr/ports/unix \ | |
| $(OBJ_DIR)/genhdr/qstr/py | |
| examples: $(EXAMPLES) | |
| $(IMP_LIB): uPython.dll | |
| uPython.dll: $(OBJ_DIR)/uPython.def $(OBJ_DIR)/uPython_dll.res $(LIB_OBJ) | |
| $(call link_DLL, $@, $(IMP_LIB), -def:$^ $(LWIP_LIBS) $(MBEDTLS_LIBS)) | |
| ifeq ($(USE_uPython_DLL),1) | |
| MicroPython.exe: $(OBJ_DIR)/main.obj $(OBJ_DIR)/MicroPython_exe.res $(IMP_LIB) | |
| $(call link_EXE, $@, $^) | |
| else | |
| MicroPython.exe: $(OBJ_DIR)/main.obj $(OBJ_DIR)/MicroPython_exe.res $(STAT_LIB) | |
| $(call link_EXE, $@, $^ $(LWIP_LIBS) $(MBEDTLS_LIBS)) | |
| endif | |
| $(OBJ_DIR)/uPython.def: $(STAT_LIB) $(THIS_FILE) | |
| $(call make_def_file, $@, $<) | |
| $(STAT_LIB): $(LIB_OBJ) | |
| $(call create_lib, $@, $^) | |
| $(CC).args: $(THIS_FILE) | |
| $(call yellow_msg, All CFLAGS are in $@) | |
| $(call create_resp_file, $@, -c $(CFLAGS)) | |
| @echo | |
| $(OBJ_DIR)/genhdr/moduledefs.h: $(LIB_SRC) | |
| $(call Generate, $@, //) | |
| $(PYTHON) py/makemoduledefs.py $(LIB_SRC) >> $@ | |
| @echo | |
| # | |
| # Generate the list of 'QDEF()' from the preprocessed and collected 'Q()' list | |
| # | |
| $(OBJ_DIR)/genhdr/qstrdefs.generated.h: $(OBJ_DIR)/genhdr/qstrdefs.preprocessed.h $(OBJ_DIR)/genhdr/qstrdefs.collected.h | |
| $(call Generate, $@, //) | |
| $(PYTHON) py/makeqstrdata.py $^ >> $@ | |
| @echo | |
| $(OBJ_DIR)/genhdr/qstrdefs.collected.h: $(OBJ_DIR)/genhdr/qstr.i.last $(THIS_FILE) | |
| $(call green_msg, Creating $@ to extract all 'MP_QSTRxx' from $<...) | |
| $(PYTHON) py/makeqstrdefs.py split qstr $< $(OBJ_DIR)/genhdr/qstr _ | |
| $(PYTHON) py/makeqstrdefs.py cat qstr _ $(OBJ_DIR)/genhdr/qstr [email protected] | |
| sort [email protected] | uniq > $@ | |
| @echo | |
| $(OBJ_DIR)/genhdr/qstrdefs.preprocessed.h: py/qstrdefs.h ports/unix/qstrdefsport.h | |
| $(call make_pp_file, $@, $^) | |
| $(OBJ_DIR)/genhdr/qstr.i.last: $(Preprocessed_files) $(THIS_FILE) | |
| $(call green_msg, Creating $@ to extract all 'MP_QSTRxx' from $$(Preprocessed_files)...) | |
| grep --no-filename -P 'MP_QSTR|#' $(Preprocessed_files) > $@ | |
| @echo | |
| $(OBJ_DIR)/genhdr/mpversion.h: py/makeversionhdr.py $(THIS_FILE) | |
| $(call green_msg, Creating $@) | |
| $(PYTHON) $< $@ | |
| $(OBJ_DIR)/genhdr/qstr/py/%.pp: py/%.c | $(CC).args | |
| $(call make_pp_file, $@, $<) | |
| $(OBJ_DIR)/genhdr/qstr/extmod/%.pp: extmod/%.c | $(CC).args | |
| $(call make_pp_file, $@, $<) | |
| $(OBJ_DIR)/genhdr/qstr/lib/embed/%.pp: lib/embed/%.c | $(CC).args | |
| $(call make_pp_file, $@, $<) | |
| $(OBJ_DIR)/genhdr/qstr/lib/mp-readline/%.pp: lib/mp-readline/%.c | $(CC).args | |
| $(call make_pp_file, $@, $<) | |
| $(OBJ_DIR)/genhdr/qstr/lib/netutils/%.pp: lib/netutils/%.c | $(CC).args | |
| $(call make_pp_file, $@, $<) | |
| $(OBJ_DIR)/genhdr/qstr/lib/oofatfs/%.pp: lib/oofatfs/%.c | $(CC).args | |
| $(call make_pp_file, $@, $<) | |
| $(OBJ_DIR)/genhdr/qstr/lib/timeutils/%.pp: lib/timeutils/%.c | $(CC).args | |
| $(call make_pp_file, $@, $<) | |
| $(OBJ_DIR)/genhdr/qstr/lib/utils/%.pp: lib/utils/%.c | $(CC).args | |
| $(call make_pp_file, $@, $<) | |
| $(OBJ_DIR)/genhdr/qstr/ports/windows/%.pp: ports/windows/%.c | $(CC).args | |
| $(call make_pp_file, $@, $<) | |
| $(OBJ_DIR)/genhdr/qstr/ports/unix/%.pp: ports/unix/%.c | $(CC).args | |
| $(call make_pp_file, $@, $<) | |
| ifeq ($(USE_MP_COMPILE),1) | |
| SRC_chunk_1 = $(wordlist 1, 60, $(LIB_SRC)) | |
| SRC_chunk_2 = $(wordlist 61, 120, $(LIB_SRC)) | |
| SRC_chunk_3 = $(wordlist 121, 180, $(LIB_SRC)) | |
| OBJ_chunk_1 = $(call c_to_obj, $(SRC_chunk_1)) | |
| OBJ_chunk_2 = $(call c_to_obj, $(SRC_chunk_2)) | |
| OBJ_chunk_3 = $(call c_to_obj, $(SRC_chunk_3)) | |
| $(OBJ_chunk_1): $(SRC_chunk_1) | |
| $(call Compile_MP, $(SRC_chunk_1)) | |
| $(OBJ_chunk_2): $(SRC_chunk_2) | |
| $(call Compile_MP, $(SRC_chunk_2)) | |
| $(OBJ_chunk_3): $(SRC_chunk_3) | |
| $(call Compile_MP, $(SRC_chunk_3)) | |
| endif | |
| # | |
| # All sources in 'examples/embedding/*.c' use this rule and | |
| # the './examples/embedding/mpconfigport_minimal.h' config-file. | |
| # | |
| hello_CFLAGS = -I./examples/embedding \ | |
| -DNO_QSTR \ | |
| -DMP_ENDIANNESS_LITTLE=1 \ | |
| -DNORETURN=__declspec(noreturn) \ | |
| -DMICROPY_WARNINGS=1 \ | |
| -DMP_CONFIGFILE=\"./examples/embedding/mpconfigport_minimal.h\" | |
| hello-$(CC).args: $(THIS_FILE) | |
| $(call yellow_msg, All CFLAGS for 'examples/embedding/*.c' are in $@) | |
| $(call create_resp_file, $@, -c $(CFLAGS) $(hello_CFLAGS)) | |
| @echo | |
| hello-hacks.c: $(THIS_FILE) | |
| $(call Generate, $@, //) | |
| $(file >> $@, $(hello-hacks_c)) | |
| $(OBJ_DIR)/hello-%.obj: %.c | hello-$(CC).args hello-hacks.c | |
| $(strip $(CC) @hello-$(CC).args) -Fo./$@ $< | |
| @echo | |
| $(OBJ_DIR)/%.obj: %.c | $(CC).args | |
| $(strip $(CC) $(EXTRA_CFLAGS) @$(CC).args) -Fo./$@ $< | |
| @echo | |
| $(OBJ_DIR)/%.res: $(OBJ_DIR)/%.rc | |
| $(call make_res_file, $@, $<) | |
| hello-embed.exe: $(OBJ_DIR)/hello-embed.obj $(OBJ_DIR)/hello-hacks.obj $(STAT_LIB) | |
| $(call link_EXE, $@, $^ $(LWIP_LIBS) $(MBEDTLS_LIBS)) | |
| # | |
| # For .c-files in VPATH: | |
| # | |
| %.i: %.c $(GENERATED) cpp_filter.py $(CC).args FORCE | |
| $(call C_preprocess, $<, $@) | |
| FORCE: | |
| cpp_filter.py: $(THIS_FILE) | |
| $(call Generate, $@, #) | |
| $(file > $@,#!/usr/env/python) | |
| $(file >> $@,#) | |
| $(file >> $@,# DO NOT EDIT! This file was generated automatically from) | |
| $(file >> $@,# $(realpath $(THIS_FILE)) at $(TODAY).) | |
| $(file >> $@,#) | |
| $(file >> $@,from __future__ import print_function) | |
| $(file >> $@,if 1:) | |
| $(file >> $@,$(cpp_filter_py)) | |
| ifeq ($(USE_LWIP),1) | |
| RC_EXTRA_DESCRIPTION =, LwIP-support | |
| endif | |
| ifeq ($(USE_MBEDTLS),1) | |
| RC_EXTRA_DESCRIPTION +=, MbedTLS-support | |
| endif | |
| $(OBJ_DIR)/uPython_dll.rc: $(MDEPEND) | |
| $(call Generate, $@, //) | |
| $(file >> $@, #define RC_FILENAME "uPython.dll") | |
| $(file >> $@, #define RC_FILETYPE VFT_DLL) | |
| $(file >> $@, #define RC_EXTRA_DESCRIPTION "$(strip $(RC_EXTRA_DESCRIPTION)).") | |
| $(file >> $@, $(MicroPython_rc)) | |
| $(OBJ_DIR)/MicroPython_exe.rc: $(MDEPEND) | |
| $(call Generate, $@, //) | |
| $(file >> $@, #define RC_FILENAME "MicroPython.exe") | |
| $(file >> $@, #define RC_FILETYPE VFT_APP) | |
| $(file >> $@, #define RC_EXTRA_DESCRIPTION "$(strip $(RC_EXTRA_DESCRIPTION)).") | |
| $(file >> $@, $(MicroPython_rc)) | |
| OTHER_JUNK = .depend.Windows \ | |
| vc1*.pdb \ | |
| cpp_filter.py \ | |
| lib.args \ | |
| link.args \ | |
| link.tmp \ | |
| cl.args \ | |
| clang-cl.args \ | |
| hello-*.args \ | |
| hello-hacks.c \ | |
| MicroPython.map \ | |
| MicroPython.pdb \ | |
| MicroPython_imp.lib \ | |
| MicroPython_imp.exp | |
| clean: | |
| rm -fR $(OBJ_DIR)/* | |
| rm -f $(OTHER_JUNK) | |
| - rmdir $(OBJ_DIR) | |
| vclean realclean: clean | |
| - rm -f $(TARGETS) $(EXAMPLES) $(EXAMPLES:.exe=.map) $(EXAMPLES:.exe=.pdb) | |
| # | |
| # GNU-make macros: | |
| # | |
| # The following ESC-codes assumes you have MSys/Cygwin's echo with colour support. | |
| # | |
| BRIGHT_GREEN = \e[1;32m | |
| BRIGHT_YELLOW = \e[1;33m | |
| BRIGHT_WHITE = \e[1;37m | |
| colour_msg = @echo -e "$(1)\e[0m" | |
| green_msg = $(call colour_msg,$(BRIGHT_GREEN)$(strip $(1))) | |
| yellow_msg = $(call colour_msg,$(BRIGHT_YELLOW)$(strip $(1))) | |
| white_msg = $(call colour_msg,$(BRIGHT_WHITE)$(strip $(1))) | |
| define Warning | |
| $(1) | |
| $(1) DO NOT EDIT! This file was automatically generated | |
| $(1) from $(realpath $(THIS_FILE)) at $(TODAY). | |
| $(1) Edit that file instead. | |
| $(1) | |
| endef | |
| define Generate | |
| $(call green_msg, Generating $(1)) | |
| $(file > $(1),$(call Warning,$(2))) | |
| endef | |
| define Compile_MP | |
| $(call green_msg, Compiling $(words $(1)) files in one go...) | |
| $(CC) @$(CC).args -MP -Fo./$(OBJ_DIR)\\ $(1) | |
| @echo | |
| endef | |
| # | |
| # For C-preprocessing. | |
| # | |
| C_preprocess = $(strip $(CC) -E $(EXTRA_CFLAGS) @$(CC).args $(1)) | $(PYTHON) cpp_filter.py | |
| ifeq ($(USE_CLANG_FORMATER),1) | |
| C_preprocess += | clang-format -style=Mozilla -assume-filename=c > $(2) | |
| else ifeq ($(USE_GNU_INDENT),1) | |
| C_preprocess += | indent -st > $(2) | |
| else | |
| C_preprocess += > $(2) | |
| endif | |
| # | |
| # Create a response file $(1). | |
| # One word from $(2) per line. | |
| # | |
| define create_resp_file | |
| $(file > $(1)) | |
| $(foreach f, $(2), $(file >> $(1),$(strip $(f))) ) | |
| endef | |
| # | |
| # Create an EXE from objects: | |
| # arg1, $(1): The .exe file. | |
| # arg2, $(2): The .obj file(s), extra args and libs. | |
| # | |
| define link_EXE | |
| $(call green_msg, Linking $(1)) | |
| $(call create_resp_file, link.args, $(LDFLAGS) $(2)) | |
| link -out:$(strip $(1)) @link.args > link.tmp | |
| @cat link.tmp >> $(1:.exe=.map) | |
| @rm -f link.tmp | |
| $(call white_msg, Done.\n) | |
| endef | |
| # | |
| # Create a DLL + import-lib from objects .obj: | |
| # arg1, $(1): The .dll file. | |
| # arg2, $(2): The import-lib. | |
| # arg3, $(3): The .obj file(s), extra args and libs. | |
| # | |
| define link_DLL | |
| $(call green_msg, Linking $(1)) | |
| $(call create_resp_file, link.args, $(LDFLAGS) -dll -implib:$(strip $(2)) $(3)) | |
| link -out:$(strip $(1)) @link.args > link.tmp | |
| @cat link.tmp >> $(1:.dll=.map) | |
| @rm -f $(2:.lib=.exp) link.tmp | |
| $(call white_msg, Done.\n) | |
| endef | |
| # | |
| # Create a static library. | |
| # | |
| define create_lib | |
| $(call green_msg, Creating static lib $(1)) | |
| rm -f $(1) | |
| $(call create_resp_file, lib.args, $(2)) | |
| lib -nologo -out:$(strip $(1)) @lib.args | |
| @echo | |
| endef | |
| # | |
| # Create a .res-file: | |
| # arg1: $(1): the name of the .res-file. | |
| # arg2: $(2): the .rc-file. | |
| # | |
| define make_res_file | |
| rc $(RCFLAGS) -Fo./$(strip $(1)) $(2) | |
| @echo | |
| endef | |
| # | |
| # Preprocess a .c-file for all the 'Q(xx)' definitions | |
| # | |
| define make_pp_file | |
| $(call green_msg, Creating $(1) by preprocessing$(BRIGHT_WHITE)$(2).) | |
| $(CC) @$(CC).args -DNO_QSTR -E $(2) > $(1) | |
| @echo | |
| endef | |
| # | |
| # Create a .def-file: For 'x86' only | |
| # arg1: $(1): the name of the .def-file. | |
| # arg2: $(2): the .obj-files or library to extract symbols from. | |
| # | |
| filter_symbols = sed -e 's/^.* _/ /' \ | |
| -e 's/console_sighandler@4//' # 'stdcalls' are not right. Why? | |
| extract_symbols = nm $(1) | grep -e ' T _.*' | sed -e 's/^ T _/ /'| $(filter_symbols) | |
| extract_symbols = nm $(1) | grep -e ' T _mp_.*' | sed -e 's/^ T _/ /' | sed -e 's/^.* _/ /' | |
| define make_def_file | |
| $(call Generate, $(1), ;) | |
| $(file >> $(1), LIBRARY $(notdir $(1:.def=.dll))) | |
| $(file >> $(1), EXPORTS) | |
| $(call extract_symbols, $(2)) | sort | uniq >> $(1) | |
| endef | |
| ifeq ($(USER),gv) | |
| RC_PRIVATE_BUILD = "Private build of <[email protected]>." | |
| endif | |
| define MicroPython_rc | |
| #include <winver.h> | |
| #if defined(__clang__) | |
| #define RC_HOST "clang" | |
| #elif defined(_MSC_VER) | |
| #define RC_HOST "MSVC" | |
| #else | |
| #error "Unknown 'RC_HOST'." | |
| #endif | |
| #if !defined(RC_FILENAME) | |
| #error "define RC_FILENAME first" | |
| #endif | |
| #if !defined(RC_FILETYPE) | |
| #error "define RC_FILETYPE first" | |
| #endif | |
| #if !defined(RC_EXTRA_DESCRIPTION) | |
| #define RC_EXTRA_DESCRIPTION "" | |
| #endif | |
| #define RC_VERSION $(VER_MAJOR),$(VER_MINOR),$(VER_MICRO),0 | |
| #define RC_DESCRIPTION "A lean and efficient Python implementation" | |
| //APPICON ICON "MicroPython.ico" /** \todo Create and add a nice icon. */ | |
| VS_VERSION_INFO VERSIONINFO | |
| FILEVERSION RC_VERSION | |
| PRODUCTVERSION RC_VERSION | |
| FILEFLAGSMASK 0x3fL | |
| FILEFLAGS 0 | |
| FILEOS VOS__WINDOWS32 | |
| FILETYPE RC_FILETYPE | |
| FILESUBTYPE 0 | |
| BEGIN | |
| BLOCK "StringFileInfo" | |
| BEGIN | |
| BLOCK "040904b0" | |
| BEGIN | |
| VALUE "CompanyName", "MicroPython, https://github.com/micropython/micropython" | |
| VALUE "FileDescription", RC_DESCRIPTION RC_EXTRA_DESCRIPTION " (" RC_HOST ", x86)" | |
| VALUE "FileVersion", "$(VERSION)" | |
| VALUE "InternalName", "MicroPython" | |
| VALUE "OriginalFilename", RC_FILENAME | |
| VALUE "ProductName", RC_FILENAME | |
| VALUE "ProductVersion", "$(VERSION)" | |
| VALUE "LegalCopyright", "Copyright (c) 2013-2020 Damien P. George. MIT License" | |
| VALUE "PrivateBuild", $(RC_PRIVATE_BUILD) | |
| VALUE "Comments", "Built on $(TODAY)." | |
| END | |
| END | |
| BLOCK "VarFileInfo" | |
| BEGIN | |
| VALUE "Translation", 0x409, 1200 | |
| END | |
| END | |
| endef | |
| define hello-hacks_c | |
| #include <stdio.h> | |
| #include <unistd.h> | |
| #include "py/mperrno.h" | |
| #include "py/obj.h" | |
| static void stderr_print_strn (void *env, const char *str, size_t len) | |
| { | |
| (void) env; | |
| write (STDERR_FILENO, str, len); | |
| } | |
| const mp_print_t mp_stderr_print = { NULL, stderr_print_strn }; | |
| mp_obj_t mp_builtin_open (size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) | |
| { | |
| mp_raise_OSError (MP_EPERM); | |
| } | |
| MP_DEFINE_CONST_FUN_OBJ_KW (mp_builtin_open_obj, 1, mp_builtin_open); | |
| endef | |
| define cpp_filter_py | |
| # | |
| # A tool used in "$$(CC) -E" rules to remove empty | |
| # preproessor lines and make the output a bit more readable. | |
| # | |
| import sys, os | |
| try: | |
| import ntpath | |
| except ImportError as e: | |
| print ("Failed to import ntpath: %s" % e) | |
| sys.exit(1) | |
| def _win32_abspath (path): | |
| path = ntpath.abspath (path) | |
| return path.replace ('\\', '/') | |
| def skip_cwd (s1, s2): | |
| ''' Skip the leading part that is in common with s1 and s2 | |
| ''' | |
| i = 0 | |
| while i < len(s1) and s1[i] == s2[i]: | |
| i += 1 | |
| return s2[i:] | |
| cwd = _win32_abspath (os.getcwd()) + '/' | |
| last_line = '??' | |
| last_fname = '??' | |
| empty_lines = 0 | |
| while True: | |
| line = sys.stdin.readline() | |
| if not line: | |
| break | |
| if (line.startswith('\n') or line.startswith('\r')) and last_line[0] == '\r': | |
| empty_lines += 1 | |
| continue | |
| if line.lstrip().startswith("#line"): | |
| line = line.replace ("\\\\", "/") | |
| fname = None | |
| quote = line.find ('\"') | |
| if line.startswith("#line ") and quote > 0: | |
| fname = _win32_abspath (line[quote:]) | |
| last_fname = fname | |
| line = line [:quote] + skip_cwd (cwd, fname) | |
| if line.strip() != '' and last_line != '': | |
| if fname is None or fname != last_fname: | |
| print (line, end="") | |
| last_line = line | |
| if empty_lines > 0: | |
| sys.stderr.write ("Removed %d empty lines." % empty_lines) | |
| endef | |
| DEP_REPLACE = sed -e 's@\(.*\)\.o: @\n$$(OBJ_DIR)/\1\.obj: @' \ | |
| -e 's@$(LWIP_ROOT)@$$(LWIP_ROOT)@' \ | |
| -e 's@$(MBEDTLS_ROOT)@$$(MBEDTLS_ROOT)@' | |
| DEP_SOURCES = $(LIB_SRC) ports/windows/main.c \ | |
| $(EXAMPLES_SRC) | |
| # | |
| # The ouput gets filtered to *not* include some of the genearted files. | |
| # That would cause GNU-make to do too much work. | |
| # | |
| DEP_REPLACE += -e 's@$(OBJ_DIR)/genhdr/qstrdefs.generated.h@@g' | |
| depend: mk_dirs $(GENERATED) | |
| $(call green_msg, Generating dependencies for $(words $(DEP_SOURCES)) source files...) | |
| $(file > .depend.Windows,$(call Warning,#)) | |
| $(call create_resp_file, $(CC).args, -MM $(filter -I% -D%, $(CFLAGS))) | |
| gcc @$(CC).args $(DEP_SOURCES) | $(DEP_REPLACE) >> .depend.Windows | |
| -include .depend.Windows | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment