From d76c65f599b77aa275eda3d2248cde16f6be7e10 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20=C4=8Capek?= <jan.capek@braiins.cz>
Date: Thu, 10 Mar 2016 09:22:41 +0000
Subject: [PATCH] py: Add rules for automated extraction of qstrs from sources.

- add template rule that converts a specified source file into a qstring file

- add special rule for generating a central header that contains all
  extracted/autogenerated strings - defined by QSTR_DEFS_COLLECTED
  variable. Each platform appends a list of sources that may contain
  qstrings into a new build variable: SRC_QSTR. Any autogenerated
  prerequisities are should be appened to SRC_QSTR_AUTO_DEPS variable.

- remove most qstrings from py/qstrdefs, keep only qstrings that
  contain special characters - these cannot be easily detected in the
  sources without additional annotations

- remove most manual qstrdefs, use qstrdef autogen for: py, cc3200,
  stmhal, teensy, unix, windows, pic16bit:

   - remove all micropython generic qstrdefs except for the special strings that contain special characters (e.g. /,+,<,> etc.)
   - remove all port specific qstrdefs except for special strings
   - append sources for qstr generation in platform makefiles (SRC_QSTR)
---
 cc3200/application.mk   |   6 +
 cc3200/qstrdefsport.h   | 362 +------------------
 pic16bit/Makefile       |   6 +
 pic16bit/qstrdefsport.h |  16 -
 py/mkrules.mk           |  28 ++
 py/py.mk                |  12 +-
 py/qstrdefs.h           | 762 +---------------------------------------
 stmhal/Makefile         |   6 +
 stmhal/qstrdefsport.h   | 459 +-----------------------
 teensy/Makefile         |   6 +
 teensy/qstrdefsport.h   | 148 --------
 unix/Makefile           |   7 +
 unix/qstrdefsport.h     | 124 -------
 windows/Makefile        |   6 +
 14 files changed, 87 insertions(+), 1861 deletions(-)

diff --git a/cc3200/application.mk b/cc3200/application.mk
index 9e49a7c24..2eef3c8c3 100644
--- a/cc3200/application.mk
+++ b/cc3200/application.mk
@@ -171,6 +171,12 @@ OBJ += $(addprefix $(BUILD)/, $(APP_MODS_SRC_C:.c=.o) $(APP_CC3100_SRC_C:.c=.o)
 OBJ += $(addprefix $(BUILD)/, $(APP_MAIN_SRC_C:.c=.o) $(APP_LIB_SRC_C:.c=.o) $(APP_STM_SRC_C:.c=.o))
 OBJ += $(BUILD)/pins.o
 
+# List of sources for qstr extraction
+SRC_QSTR += $(APP_MODS_SRC_C) $(APP_MISC_SRC_C) $(APP_STM_SRC_C)
+# Append any auto-generated sources that are needed by sources listed in
+# SRC_QSTR
+SRC_QSTR_AUTO_DEPS +=
+
 # Add the linker script
 LINKER_SCRIPT = application.lds
 LDFLAGS += -T $(LINKER_SCRIPT)
diff --git a/cc3200/qstrdefsport.h b/cc3200/qstrdefsport.h
index 34fdcda58..2fc56668c 100644
--- a/cc3200/qstrdefsport.h
+++ b/cc3200/qstrdefsport.h
@@ -26,367 +26,7 @@
  */
 
 // for machine module
-Q(umachine)
-#ifdef DEBUG
-Q(info)
-#endif
-Q(reset)
-Q(main)
-Q(sync)
-Q(rng)
-Q(freq)
-Q(unique_id)
-Q(disable_irq)
-Q(enable_irq)
-Q(idle)
-Q(sleep)
-Q(deepsleep)
-Q(reset_cause)
-Q(wake_reason)
-Q(IDLE)
-Q(SLEEP)
-Q(DEEPSLEEP)
-Q(POWER_ON)
-Q(HARD_RESET)
-Q(WDT_RESET)
-Q(DEEPSLEEP_RESET)
-Q(SOFT_RESET)
-Q(WLAN_WAKE)
-Q(PIN_WAKE)
-Q(RTC_WAKE)
-
-// for wipy module
-Q(wipy)
-Q(heartbeat)
-
+Q(/)
 // entries for sys.path
 Q(/flash)
 Q(/flash/lib)
-
-// interactive help
-Q(help)
-
-// for module weak links
-Q(struct)
-Q(binascii)
-Q(re)
-Q(json)
-Q(heapq)
-//Q(hashlib)
-
-// for os module
-Q(os)
-Q(uos)
-Q(sysname)
-Q(nodename)
-Q(release)
-Q(version)
-Q(machine)
-Q(uname)
-Q(/)
-Q(flash)
-Q(chdir)
-Q(getcwd)
-Q(listdir)
-Q(mkdir)
-Q(rename)
-Q(remove)
-Q(rmdir)
-Q(unlink)
-Q(sep)
-Q(stat)
-Q(urandom)
-Q(mkfs)
-Q(mount)
-Q(unmount)
-Q(dupterm)
-Q(readonly)
-Q(readblocks)
-Q(writeblocks)
-Q(sync)
-Q(count)
-
-// for file class
-Q(seek)
-Q(tell)
-Q(input)
-Q(flush)
-
-// for Pin class
-Q(Pin)
-Q(board)
-Q(init)
-Q(value)
-Q(toggle)
-Q(id)
-Q(mode)
-Q(pull)
-Q(drive)
-Q(alt)
-Q(alt_list)
-Q(IN)
-Q(OUT)
-Q(OPEN_DRAIN)
-Q(ALT)
-Q(ALT_OPEN_DRAIN)
-Q(PULL_UP)
-Q(PULL_DOWN)
-Q(LOW_POWER)
-Q(MED_POWER)
-Q(HIGH_POWER)
-Q(IRQ_RISING)
-Q(IRQ_FALLING)
-Q(IRQ_LOW_LEVEL)
-Q(IRQ_HIGH_LEVEL)
-
-// for UART class
-Q(UART)
-Q(init)
-Q(deinit)
-Q(any)
-Q(sendbreak)
-Q(id)
-Q(baudrate)
-Q(bits)
-Q(stop)
-Q(parity)
-Q(pins)
-Q(EVEN)
-Q(ODD)
-Q(RX_ANY)
-
-// for I2C class
-Q(I2C)
-Q(id)
-Q(mode)
-Q(baudrate)
-Q(pins)
-Q(addr)
-Q(nbytes)
-Q(buf)
-Q(stop)
-Q(memaddr)
-Q(addrsize)
-Q(init)
-Q(deinit)
-Q(scan)
-Q(readfrom)
-Q(readfrom_into)
-Q(writeto)
-Q(readfrom_mem)
-Q(readfrom_mem_into)
-Q(writeto_mem)
-Q(MASTER)
-
-// for ADC class
-Q(ADC)
-Q(ADCChannel)
-Q(value)
-Q(init)
-Q(deinit)
-Q(channel)
-Q(id)
-Q(pin)
-
-// for SD class
-Q(SD)
-Q(init)
-Q(deinit)
-Q(id)
-Q(pins)
-
-// for RTC class
-Q(RTC)
-Q(id)
-Q(init)
-Q(alarm)
-Q(alarm_left)
-Q(alarm_cancel)
-Q(now)
-Q(deinit)
-Q(datetime)
-Q(repeat)
-Q(ALARM0)
-
-// for time class
-Q(time)
-Q(utime)
-Q(localtime)
-Q(mktime)
-Q(sleep)
-Q(sleep_ms)
-Q(sleep_us)
-Q(ticks_ms)
-Q(ticks_us)
-Q(ticks_cpu)
-Q(ticks_diff)
-
-// for select class
-Q(select)
-Q(uselect)
-Q(register)
-Q(unregister)
-Q(modify)
-Q(poll)
-Q(POLLIN)
-Q(POLLOUT)
-Q(POLLERR)
-Q(POLLHUP)
-
-// for socket class
-Q(socket)
-Q(usocket)
-Q(getaddrinfo)
-Q(family)
-Q(type)
-Q(send)
-Q(sendall)
-Q(sendto)
-Q(recv)
-Q(recvfrom)
-Q(listen)
-Q(accept)
-Q(bind)
-Q(settimeout)
-Q(setblocking)
-Q(setsockopt)
-Q(close)
-Q(makefile)
-Q(protocol)
-Q(error)
-Q(timeout)
-Q(AF_INET)
-Q(SOCK_STREAM)
-Q(SOCK_DGRAM)
-Q(IPPROTO_SEC)
-Q(IPPROTO_TCP)
-Q(IPPROTO_UDP)
-
-// for ssl class
-Q(ssl)
-Q(ussl)
-Q(wrap_socket)
-Q(sock)
-Q(keyfile)
-Q(certfile)
-Q(server_side)
-Q(cert_reqs)
-Q(ca_certs)
-Q(SSLError)
-Q(CERT_NONE)
-Q(CERT_OPTIONAL)
-Q(CERT_REQUIRED)
-
-// for network class
-Q(network)
-Q(Server)
-Q(init)
-Q(deinit)
-Q(login)
-Q(timeout)
-Q(isrunning)
-
-// for WLAN class
-Q(WLAN)
-Q(id)
-Q(init)
-Q(mode)
-Q(auth)
-Q(ssid)
-Q(bssid)
-Q(mac)
-Q(antenna)
-Q(scan)
-Q(connect)
-Q(isconnected)
-Q(disconnect)
-Q(sec)
-Q(channel)
-Q(rssi)
-Q(ifconfig)
-Q(config)
-//Q(connections)
-//Q(urn)
-Q(STA)
-Q(AP)
-Q(OPEN)
-Q(WEP)
-Q(WPA)
-Q(WPA2)
-Q(INT_ANT)
-Q(EXT_ANT)
-Q(ANY_EVENT)
-
-// for WDT class
-Q(WDT)
-Q(feed)
-Q(timeout)
-
-// for irq class
-Q(irq)
-Q(init)
-Q(enable)
-Q(disable)
-Q(flags)
-Q(trigger)
-Q(handler)
-Q(priority)
-Q(wake)
-
-// for SPI class
-Q(SPI)
-Q(id)
-Q(mode)
-Q(baudrate)
-Q(bits)
-Q(polarity)
-Q(phase)
-Q(firstbit)
-Q(init)
-Q(deinit)
-Q(write)
-Q(read)
-Q(readinto)
-Q(write_readinto)
-Q(nbytes)
-Q(buf)
-Q(MASTER)
-Q(MSB)
-
-// for Timer class
-Q(Timer)
-Q(TimerChannel)
-Q(init)
-Q(deinit)
-Q(freq)
-Q(period)
-Q(mode)
-Q(width)
-Q(channel)
-Q(polarity)
-Q(duty_cycle)
-Q(A)
-Q(B)
-Q(ONE_SHOT)
-Q(PERIODIC)
-Q(PWM)
-Q(POSITIVE)
-Q(NEGATIVE)
-Q(TIMEOUT)
-Q(MATCH)
-
-// for uhashlib module
-//Q(uhashlib)
-//Q(update)
-//Q(digest)
-//Q(md5)
-//Q(sha1)
-//Q(sha256)
-
-// for ubinascii module
-Q(ubinascii)
-Q(hexlify)
-Q(unhexlify)
-Q(a2b_base64)
-Q(b2a_base64)
-
diff --git a/pic16bit/Makefile b/pic16bit/Makefile
index a16a26386..cfe8af86e 100644
--- a/pic16bit/Makefile
+++ b/pic16bit/Makefile
@@ -49,6 +49,12 @@ SRC_S = \
 
 OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(SRC_S:.s=.o))
 
+# List of sources for qstr extraction
+SRC_QSTR += $(SRC_C)
+# Append any auto-generated sources that are needed by sources listed in
+# SRC_QSTR
+SRC_QSTR_AUTO_DEPS +=
+
 all: $(BUILD)/firmware.hex
 
 $(BUILD)/firmware.hex: $(BUILD)/firmware.elf
diff --git a/pic16bit/qstrdefsport.h b/pic16bit/qstrdefsport.h
index f532bb0b0..3ba897069 100644
--- a/pic16bit/qstrdefsport.h
+++ b/pic16bit/qstrdefsport.h
@@ -1,17 +1 @@
 // qstrs specific to this port
-
-Q(pyb)
-Q(millis)
-Q(elapsed_millis)
-Q(delay)
-Q(LED)
-Q(on)
-Q(off)
-Q(toggle)
-Q(Switch)
-Q(value)
-Q(readall)
-Q(readinto)
-Q(readline)
-Q(readlines)
-Q(FileIO)
diff --git a/py/mkrules.mk b/py/mkrules.mk
index 9cbef1ac5..eb4c48ece 100644
--- a/py/mkrules.mk
+++ b/py/mkrules.mk
@@ -46,10 +46,30 @@ vpath %.c . $(TOP)
 $(BUILD)/%.o: %.c
 	$(call compile_c)
 
+# A empty qstrdefs header is needed to properly preprocess every file
+EMPTY_QSTRDEFS_GENERATED_H = $(BUILD)/tmp/genhdr/qstrdefs.generated.h
+
+# List all native flags since the current build system doesn't have
+# the micropython configuration available. However, these flags are
+# needed to extract all qstrings
+QSTR_GEN_EXTRA_CFLAGS += -DN_X64 -DN_X86 -DN_THUMB -DN_ARM
+QSTR_GEN_EXTRA_CFLAGS += -I$(BUILD)/tmp
+
+vpath %.c . $(TOP)
+$(HEADER_BUILD)/%.qstr: % | $(EMPTY_QSTRDEFS_GENERATED_H) $(HEADER_BUILD)/mpversion.h $(SRC_QSTR_AUTO_DEPS)
+	  @mkdir -p $(dir $@);
+	  $(Q)$(CPP)  $(QSTR_GEN_EXTRA_CFLAGS) $(CFLAGS) $< -o - | $(PYTHON) $(PY_SRC)/makeqstrdefs.py -s -o $@
+
+
 $(BUILD)/%.pp: %.c
 	$(ECHO) "PreProcess $<"
 	$(Q)$(CC) $(CFLAGS) -E -Wp,-C,-dD,-dI -o $@ $<
 
+$(EMPTY_QSTRDEFS_GENERATED_H):
+	$(ECHO) "Generate empty $@ to satisfy qstr generator"
+	$(Q)mkdir -p $(dir $@)
+	$(Q)touch $@
+
 # The following rule uses | to create an order only prereuisite. Order only
 # prerequisites only get built if they don't exist. They don't cause timestamp
 # checking to be performed.
@@ -61,6 +81,14 @@ $(BUILD)/%.pp: %.c
 # to get built before we try to compile any of them.
 $(OBJ): | $(HEADER_BUILD)/qstrdefs.generated.h $(HEADER_BUILD)/mpversion.h
 
+# This rule joins all generated qstr files
+$(QSTR_DEFS_COLLECTED): $(addprefix $(HEADER_BUILD)/,$(addsuffix .qstr,$(SRC_QSTR))) $(PY_SRC)/mpconfig.h
+	$(ECHO) "GEN $@"
+	$(Q)cat $^ > $@
+
+
+#
+
 # $(sort $(var)) removes duplicates
 #
 # The net effect of this, is it causes the objects to depend on the
diff --git a/py/py.mk b/py/py.mk
index 599850e3d..185446174 100644
--- a/py/py.mk
+++ b/py/py.mk
@@ -7,6 +7,9 @@ HEADER_BUILD = $(BUILD)/genhdr
 # file containing qstr defs for the core Python bit
 PY_QSTR_DEFS = $(PY_SRC)/qstrdefs.h
 
+# All collected qstr defs
+QSTR_DEFS_COLLECTED = $(HEADER_BUILD)/qstrdefs.collected.h
+
 # some code is performance bottleneck and compiled with other optimization options
 CSUPEROPT = -O3
 
@@ -184,6 +187,10 @@ PY_O_BASENAME = \
 # prepend the build destination prefix to the py object files
 PY_O = $(addprefix $(PY_BUILD)/, $(PY_O_BASENAME))
 
+# Sources that may contain qstrings
+SRC_QSTR_IGNORE = nlr% emitnx% emitnthumb% emitnarm%
+SRC_QSTR = $(SRC_MOD) $(addprefix py/,$(filter-out $(SRC_QSTR_IGNORE),$(PY_O_BASENAME:.o=.c)) emitnative.c)
+
 # Anything that depends on FORCE will be considered out-of-date
 FORCE:
 .PHONY: FORCE
@@ -196,14 +203,13 @@ $(HEADER_BUILD)/mpversion.h: FORCE | $(HEADER_BUILD)
 MPCONFIGPORT_MK = $(wildcard mpconfigport.mk)
 
 # qstr data
-
 # Adding an order only dependency on $(HEADER_BUILD) causes $(HEADER_BUILD) to get
 # created before we run the script to generate the .h
 # Note: we need to protect the qstr names from the preprocessor, so we wrap
 # the lines in "" and then unwrap after the preprocessor is finished.
-$(HEADER_BUILD)/qstrdefs.generated.h: $(PY_QSTR_DEFS) $(QSTR_DEFS) $(PY_SRC)/makeqstrdata.py mpconfigport.h $(MPCONFIGPORT_MK) $(PY_SRC)/mpconfig.h | $(HEADER_BUILD)
+$(HEADER_BUILD)/qstrdefs.generated.h: $(PY_QSTR_DEFS) $(QSTR_DEFS) $(QSTR_DEFS_COLLECTED) $(PY_SRC)/makeqstrdata.py mpconfigport.h $(MPCONFIGPORT_MK) $(PY_SRC)/mpconfig.h | $(HEADER_BUILD)
 	$(ECHO) "GEN $@"
-	$(Q)cat $(PY_QSTR_DEFS) $(QSTR_DEFS) | $(SED) 's/^Q(.*)/"&"/' | $(CPP) $(CFLAGS) - | sed 's/^"\(Q(.*)\)"/\1/' > $(HEADER_BUILD)/qstrdefs.preprocessed.h
+	$(Q)cat $(PY_QSTR_DEFS) $(QSTR_DEFS) $(QSTR_DEFS_COLLECTED) | $(SED) 's/^Q(.*)/"&"/' | $(CPP) $(CFLAGS) - | sed 's/^"\(Q(.*)\)"/\1/' > $(HEADER_BUILD)/qstrdefs.preprocessed.h
 	$(Q)$(PYTHON) $(PY_SRC)/makeqstrdata.py $(HEADER_BUILD)/qstrdefs.preprocessed.h > $@
 
 # emitters
diff --git a/py/qstrdefs.h b/py/qstrdefs.h
index a3b68832c..c98a253a6 100644
--- a/py/qstrdefs.h
+++ b/py/qstrdefs.h
@@ -36,469 +36,11 @@ QCFG(BYTES_IN_HASH, MICROPY_QSTR_BYTES_IN_HASH)
 Q()
 Q(*)
 Q(_)
-Q(__build_class__)
-Q(__class__)
-Q(__doc__)
-Q(__import__)
-Q(__init__)
-Q(__new__)
-Q(__locals__)
-Q(__main__)
-Q(__module__)
-Q(__name__)
-Q(__dict__)
-Q(__hash__)
-Q(__next__)
-Q(__qualname__)
-Q(__path__)
-Q(__repl_print__)
-#if MICROPY_PY___FILE__
-Q(__file__)
-#endif
-
-Q(__bool__)
-Q(__contains__)
-Q(__enter__)
-Q(__exit__)
-Q(__len__)
-Q(__iter__)
-Q(__getitem__)
-Q(__setitem__)
-Q(__delitem__)
-Q(__add__)
-Q(__sub__)
-Q(__repr__)
-Q(__str__)
-#if MICROPY_PY_DESCRIPTORS
-Q(__get__)
-Q(__set__)
-Q(__delete__)
-#endif
-Q(__getattr__)
-Q(__del__)
-Q(__call__)
-Q(__lt__)
-Q(__gt__)
-Q(__eq__)
-Q(__le__)
-Q(__ge__)
-Q(__reversed__)
-#if MICROPY_PY_ALL_SPECIAL_METHODS
-Q(__mul__)
-Q(__truediv__)
-Q(__floordiv__)
-Q(__iadd__)
-Q(__isub__)
-Q(__invert__)
-Q(__neg__)
-Q(__pos__)
-#endif
-
-#if MICROPY_PY_ASYNC_AWAIT
-Q(__aiter__)
-Q(__anext__)
-Q(__aenter__)
-Q(__aexit__)
-Q(StopAsyncIteration)
-#endif
-
-Q(micropython)
-Q(bytecode)
-Q(const)
-
-#if MICROPY_EMIT_NATIVE
-Q(native)
-Q(viper)
-Q(uint)
-Q(ptr)
-Q(ptr8)
-Q(ptr16)
-Q(ptr32)
-#endif
-
-#if MICROPY_EMIT_INLINE_THUMB
-Q(asm_thumb)
-Q(label)
-Q(align)
-Q(data)
-Q(uint)
-Q(nop)
-Q(mov)
-Q(and_)
-Q(cmp)
-Q(add)
-Q(sub)
-Q(lsl)
-Q(lsr)
-Q(asr)
-Q(ldr)
-Q(ldrb)
-Q(ldrh)
-Q(str)
-Q(strb)
-Q(strh)
-Q(b)
-Q(bl)
-Q(bx)
-Q(push)
-Q(pop)
-Q(cpsid)
-Q(cpsie)
-Q(wfi)
-Q(clz)
-Q(rbit)
-Q(movw)
-Q(movt)
-Q(movwt)
-Q(mrs)
-Q(sdiv)
-Q(udiv)
-Q(ldrex)
-Q(strex)
-#if MICROPY_EMIT_INLINE_THUMB_FLOAT
-Q(vcmp)
-Q(vneg)
-Q(vcvt_f32_s32)
-Q(vcvt_s32_f32)
-Q(vsqrt)
-Q(vmov)
-Q(vmrs)
-Q(vldr)
-Q(vstr)
-#endif
-#endif
-
-Q(builtins)
-
-Q(Ellipsis)
-Q(StopIteration)
-#if MICROPY_PY_BUILTINS_NOTIMPLEMENTED
-Q(NotImplemented)
-#endif
-
-Q(BaseException)
-Q(ArithmeticError)
-Q(AssertionError)
-Q(AttributeError)
-Q(BufferError)
-Q(EOFError)
-Q(Exception)
-Q(FileExistsError)
-Q(FileNotFoundError)
-Q(FloatingPointError)
-Q(GeneratorExit)
-Q(ImportError)
-Q(IndentationError)
-Q(IndexError)
-Q(KeyboardInterrupt)
-Q(KeyError)
-Q(LookupError)
-Q(MemoryError)
-Q(NameError)
-Q(NotImplementedError)
-Q(OSError)
-#if MICROPY_PY_BUILTINS_TIMEOUTERROR
-Q(TimeoutError)
-#endif
-Q(OverflowError)
-Q(RuntimeError)
-Q(SyntaxError)
-Q(SystemExit)
-Q(TypeError)
-Q(UnboundLocalError)
-Q(ValueError)
-#if MICROPY_EMIT_NATIVE
-Q(ViperTypeError)
-#endif
-Q(ZeroDivisionError)
-#if MICROPY_PY_BUILTINS_STR_UNICODE
-Q(UnicodeError)
-#endif
-
-Q(None)
-Q(False)
-Q(True)
-Q(object)
-
-Q(NoneType)
-
-#if MICROPY_PY_COLLECTIONS_ORDEREDDICT
-Q(OrderedDict)
-#endif
-
-Q(abs)
-Q(all)
-Q(any)
-Q(args)
-#if MICROPY_PY_ARRAY
-Q(array)
-#endif
-Q(bin)
-Q({:#b})
-Q(bool)
-#if MICROPY_PY_BUILTINS_BYTEARRAY
-Q(bytearray)
-#endif
-#if MICROPY_PY_BUILTINS_MEMORYVIEW
-Q(memoryview)
-#endif
-Q(bytes)
-Q(callable)
-Q(chr)
-Q(classmethod)
-Q(_collections)
-#if MICROPY_PY_BUILTINS_COMPLEX
-Q(complex)
-Q(real)
-Q(imag)
-#endif
-Q(dict)
-Q(dir)
-Q(divmod)
-#if MICROPY_PY_BUILTINS_ENUMERATE
-Q(enumerate)
-#endif
-Q(eval)
-Q(exec)
-#if MICROPY_PY_BUILTINS_EXECFILE
-Q(execfile)
-#endif
-#if MICROPY_PY_BUILTINS_FILTER
-Q(filter)
-#endif
-#if MICROPY_PY_BUILTINS_FLOAT
-Q(float)
-#endif
-Q(from_bytes)
-Q(getattr)
-Q(setattr)
-Q(globals)
-Q(hasattr)
-Q(hash)
-Q(hex)
-Q(%#x)
-Q(id)
-Q(int)
-Q(isinstance)
-Q(issubclass)
-Q(iter)
-Q(len)
-Q(list)
-Q(locals)
-Q(map)
-#if MICROPY_PY_BUILTINS_MIN_MAX
-Q(max)
-Q(min)
-Q(default)
-#endif
-Q(namedtuple)
-Q(next)
-Q(oct)
 Q(%#o)
-Q(open)
-Q(ord)
-Q(path)
-Q(pow)
-Q(print)
-Q(range)
-Q(read)
-Q(repr)
-Q(reversed)
-Q(round)
-Q(sorted)
-Q(staticmethod)
-Q(sum)
-Q(super)
-Q(str)
-Q(sys)
-Q(to_bytes)
-Q(tuple)
-Q(type)
-Q(value)
-Q(write)
-Q(zip)
-
-#if MICROPY_PY_BUILTINS_COMPILE
-Q(compile)
-Q(code)
-Q(single)
-#endif
-
-Q(sep)
-Q(end)
-
-#if MICROPY_PY_BUILTINS_RANGE_ATTRS
-Q(step)
-Q(stop)
-#endif
-
-Q(clear)
-Q(copy)
-Q(fromkeys)
-Q(get)
-Q(items)
-Q(keys)
-Q(pop)
-Q(popitem)
-Q(setdefault)
-Q(update)
-Q(values)
-Q(append)
-Q(close)
-Q(send)
-Q(throw)
-Q(count)
-Q(extend)
-Q(index)
-Q(remove)
-Q(insert)
-Q(pop)
-Q(sort)
-Q(join)
-Q(strip)
-Q(lstrip)
-Q(rstrip)
-Q(format)
-Q(key)
-Q(reverse)
-Q(add)
-Q(clear)
-Q(copy)
-Q(pop)
-Q(remove)
-Q(find)
-Q(rfind)
-Q(rindex)
-Q(split)
-#if MICROPY_PY_BUILTINS_STR_SPLITLINES
-Q(splitlines)
-Q(keepends)
+Q(%#x)
+Q({:#b})
 Q(\n)
-#endif
-Q(rsplit)
-Q(startswith)
-Q(endswith)
-Q(replace)
-Q(partition)
-Q(rpartition)
-Q(lower)
-Q(upper)
-Q(isspace)
-Q(isalpha)
-Q(isdigit)
-Q(isupper)
-Q(islower)
-Q(iterable)
-Q(start)
-
-Q(bound_method)
-Q(closure)
-Q(dict_view)
-Q(function)
-Q(generator)
-Q(iterator)
-Q(module)
-Q(slice)
-
-#if MICROPY_PY_BUILTINS_SET
-Q(discard)
-Q(difference)
-Q(difference_update)
-Q(intersection)
-Q(intersection_update)
-Q(isdisjoint)
-Q(issubset)
-Q(issuperset)
-Q(set)
-Q(symmetric_difference)
-Q(symmetric_difference_update)
-Q(union)
-Q(update)
-#endif
-
-#if MICROPY_PY_BUILTINS_FROZENSET
-Q(frozenset)
-#endif
-
-#if MICROPY_PY_MATH || MICROPY_PY_CMATH
-Q(math)
-Q(e)
-Q(pi)
-Q(sqrt)
-Q(pow)
-Q(exp)
-#if MICROPY_PY_MATH_SPECIAL_FUNCTIONS
-Q(expm1)
-#endif
-Q(log)
-#if MICROPY_PY_MATH_SPECIAL_FUNCTIONS
-Q(log2)
-Q(log10)
-Q(cosh)
-Q(sinh)
-Q(tanh)
-Q(acosh)
-Q(asinh)
-Q(atanh)
-#endif
-Q(cos)
-Q(sin)
-Q(tan)
-Q(acos)
-Q(asin)
-Q(atan)
-Q(atan2)
-Q(ceil)
-Q(copysign)
-Q(fabs)
-Q(fmod)
-Q(floor)
-Q(isfinite)
-Q(isinf)
-Q(isnan)
-Q(trunc)
-Q(modf)
-Q(frexp)
-Q(ldexp)
-Q(degrees)
-Q(radians)
-#if MICROPY_PY_MATH_SPECIAL_FUNCTIONS
-Q(erf)
-Q(erfc)
-Q(gamma)
-Q(lgamma)
-#endif
-#endif
-
-#if MICROPY_PY_CMATH
-Q(cmath)
-Q(phase)
-Q(polar)
-Q(rect)
-#endif
-
-#if MICROPY_PY_MICROPYTHON_MEM_INFO
-#if MICROPY_MEM_STATS
-Q(mem_total)
-Q(mem_current)
-Q(mem_peak)
-#endif
-Q(mem_info)
-Q(qstr_info)
-#if MICROPY_STACK_CHECK
-Q(stack_use)
-#endif
-#endif
-#if MICROPY_ENABLE_GC
-Q(heap_lock)
-Q(heap_unlock)
-#endif
-
-#if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF && (MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE == 0)
-Q(alloc_emergency_exception_buf)
-#endif
 Q(maximum recursion depth exceeded)
-
 Q(<module>)
 Q(<lambda>)
 Q(<listcomp>)
@@ -507,298 +49,12 @@ Q(<setcomp>)
 Q(<genexpr>)
 Q(<string>)
 Q(<stdin>)
-
-#if MICROPY_CPYTHON_COMPAT
-Q(encode)
-Q(decode)
 Q(utf-8)
-#endif
 
-#if MICROPY_PY_SYS
-Q(argv)
-Q(byteorder)
-Q(big)
-Q(exit)
-Q(little)
-#ifdef MICROPY_PY_SYS_PLATFORM
-Q(platform)
-#endif
-Q(stdin)
-Q(stdout)
-Q(stderr)
-#if MICROPY_PY_SYS_STDIO_BUFFER
-Q(buffer)
-#endif
-Q(version)
-Q(version_info)
-#if MICROPY_PY_ATTRTUPLE
-Q(name)
-#endif
-Q(implementation)
-#if MICROPY_PY_SYS_MAXSIZE
-Q(maxsize)
-#endif
-#if MICROPY_PY_SYS_MODULES
-Q(modules)
-#endif
-#if MICROPY_PY_SYS_EXC_INFO
-Q(exc_info)
-#endif
-Q(print_exception)
-#endif
-
-#if MICROPY_PY_STRUCT
-Q(struct)
-Q(ustruct)
-Q(pack)
-Q(pack_into)
-Q(unpack)
-Q(unpack_from)
-Q(calcsize)
-#endif
-
-#if MICROPY_PY_UCTYPES
-Q(uctypes)
-Q(struct)
-Q(sizeof)
-Q(addressof)
-Q(bytes_at)
-Q(bytearray_at)
-
-Q(NATIVE)
-Q(LITTLE_ENDIAN)
-Q(BIG_ENDIAN)
-
-Q(VOID)
-
-Q(UINT8)
-Q(INT8)
-Q(UINT16)
-Q(INT16)
-Q(UINT32)
-Q(INT32)
-Q(UINT64)
-Q(INT64)
-
-Q(BFUINT8)
-Q(BFINT8)
-Q(BFUINT16)
-Q(BFINT16)
-Q(BFUINT32)
-Q(BFINT32)
-
-Q(FLOAT32)
-Q(FLOAT64)
-
-Q(ARRAY)
-Q(PTR)
-//Q(BITFIELD)
-
-Q(BF_POS)
-Q(BF_LEN)
-#endif
-
-#if MICROPY_PY_IO
-Q(_io)
-Q(readall)
-Q(readinto)
-Q(readline)
-Q(readlines)
-Q(seek)
-Q(tell)
-Q(FileIO)
-Q(TextIOWrapper)
-Q(StringIO)
-Q(BytesIO)
-Q(getvalue)
-Q(file)
-Q(mode)
-Q(r)
-Q(encoding)
-#if MICROPY_PY_IO_BUFFEREDWRITER
-Q(BufferedWriter)
-#endif
-#endif
-
-#if MICROPY_PY_GC
-Q(gc)
-Q(collect)
-Q(disable)
-Q(enable)
-Q(isenabled)
-Q(mem_free)
-Q(mem_alloc)
-#endif
-
-#if MICROPY_PY_BUILTINS_PROPERTY
-Q(property)
-Q(getter)
-Q(setter)
-Q(deleter)
-Q(doc)
-#endif
-
-#if MICROPY_PY_UZLIB
-Q(uzlib)
-Q(decompress)
-#endif
-
-#if MICROPY_PY_UJSON
-Q(ujson)
-Q(dumps)
-Q(loads)
-#endif
-
-#if MICROPY_PY_URE
-Q(ure)
-Q(compile)
-Q(match)
-Q(search)
-Q(group)
-Q(DEBUG)
-#endif
-
-#if MICROPY_PY_UHEAPQ
-Q(uheapq)
-Q(heappush)
-Q(heappop)
-Q(heapify)
-#endif
-
-#if MICROPY_PY_UHASHLIB
-Q(uhashlib)
-Q(update)
-Q(digest)
-Q(sha256)
-Q(sha1)
-#endif
-
-#if MICROPY_PY_UBINASCII
-Q(ubinascii)
-Q(hexlify)
-Q(unhexlify)
-Q(a2b_base64)
-Q(b2a_base64)
-#endif
-
-#if MICROPY_PY_MACHINE
-Q(umachine)
-Q(mem)
-Q(mem8)
-Q(mem16)
-Q(mem32)
-#endif
-
-#if MICROPY_PY_MACHINE_I2C
-Q(I2C)
-Q(init)
-Q(scl)
-Q(sda)
-Q(freq)
-Q(scan)
-Q(start)
-Q(stop)
-Q(read)
-Q(readinto)
-Q(write)
-Q(readfrom)
-Q(readfrom_into)
-Q(writeto)
-Q(readfrom_mem)
-Q(readfrom_mem_into)
-Q(writeto_mem)
-Q(addr)
-Q(memaddr)
-Q(n)
-Q(buf)
-#endif
-
-#if MICROPY_PY_USSL
-Q(ussl)
-Q(wrap_socket)
-#endif
-
-#if MICROPY_PY_LWIP
-// for lwip module
-Q(lwip)
-Q(reset)
-Q(callback)
-Q(socket)
-Q(AF_INET)
-Q(AF_INET6)
-Q(SOCK_STREAM)
-Q(SOCK_DGRAM)
-Q(SOCK_RAW)
-Q(SOL_SOCKET)
-Q(SO_REUSEADDR)
-// for lwip.socket
-Q(close)
-Q(bind)
-Q(listen)
-Q(accept)
-Q(connect)
-Q(send)
-Q(recv)
-Q(sendto)
-Q(recvfrom)
-Q(settimeout)
-Q(setsockopt)
-Q(makefile)
-#if MICROPY_PY_LWIP_SLIP
-// for lwip.slip
-Q(slip)
-Q(status)
-#endif
-#endif
-
-#if MICROPY_FSUSERMOUNT
-// for user-mountable block devices
-Q(mount)
-Q(umount)
-Q(readonly)
-Q(mkfs)
-Q(listdir)
-Q(mkdir)
-Q(remove)
-Q(rename)
-Q(readblocks)
-Q(writeblocks)
-Q(ioctl)
-Q(sync)
-Q(count)
-#endif
-
-#if MICROPY_PY_OS_DUPTERM
-Q(dupterm)
-#endif
-
-#if MICROPY_PY_URANDOM
-Q(urandom)
-Q(getrandbits)
-Q(seed)
-#if MICROPY_PY_URANDOM_EXTRA_FUNCS
-Q(randrange)
-Q(randint)
-Q(choice)
-Q(random)
-Q(uniform)
-#endif
-#endif
-
-#if MICROPY_VFS_FAT
-Q(VfsFat)
-Q(flush)
-#endif
-
-#if MICROPY_PY_WEBSOCKET
-Q(websocket)
-#endif
-
-#if MICROPY_PY_FRAMEBUF
-Q(framebuf)
-Q(FrameBuffer1)
-Q(fill)
-Q(pixel)
-Q(scroll)
-Q(text)
-#endif
+// The following qstrings not referenced from anywhere in the sources
+Q(__locals__)
+Q(BufferError)
+Q(FileExistsError)
+Q(FileNotFoundError)
+Q(FloatingPointError)
+Q(UnboundLocalError)
diff --git a/stmhal/Makefile b/stmhal/Makefile
index b305e4506..e157126f7 100644
--- a/stmhal/Makefile
+++ b/stmhal/Makefile
@@ -353,6 +353,12 @@ CDCINF_TEMPLATE = pybcdc.inf_template
 GEN_CDCINF_FILE = $(HEADER_BUILD)/pybcdc.inf
 GEN_CDCINF_HEADER = $(HEADER_BUILD)/pybcdc_inf.h
 
+# List of sources for qstr extraction
+SRC_QSTR += $(SRC_C) $(SRC_MOD) $(SRC_LIB)
+# Append any auto-generated sources that are needed by sources listed in
+# SRC_QSTR
+SRC_QSTR_AUTO_DEPS += $(GEN_CDCINF_HEADER)
+
 # Making OBJ use an order-only depenedency on the generated pins.h file
 # has the side effect of making the pins.h file before we actually compile
 # any of the objects. The normal dependency generation will deal with the
diff --git a/stmhal/qstrdefsport.h b/stmhal/qstrdefsport.h
index 9ef9f2224..1d83f43bd 100644
--- a/stmhal/qstrdefsport.h
+++ b/stmhal/qstrdefsport.h
@@ -26,46 +26,6 @@
 
 // qstrs specific to this port
 
-Q(help)
-Q(pyb)
-Q(umachine)
-Q(unique_id)
-Q(bootloader)
-Q(hard_reset)
-Q(info)
-Q(sd_test)
-Q(present)
-Q(power)
-Q(wfi)
-Q(disable_irq)
-Q(enable_irq)
-Q(reset)
-Q(irq_stats)
-Q(stop)
-Q(standby)
-Q(idle)
-Q(deepsleep)
-Q(main)
-Q(opt)
-Q(sync)
-Q(gc)
-Q(repl_info)
-Q(delay)
-Q(udelay)
-Q(servo)
-Q(pwm)
-Q(read)
-Q(readall)
-Q(readline)
-Q(write)
-Q(repl_uart)
-Q(time)
-Q(rng)
-Q(Flash)
-Q(SD)
-Q(SDCard)
-Q(FileIO)
-Q(flush)
 Q(boot.py)
 Q(main.py)
 // Entries for sys.path
@@ -73,428 +33,15 @@ Q(/flash)
 Q(/flash/lib)
 Q(/sd)
 Q(/sd/lib)
-Q(millis)
-Q(micros)
-Q(elapsed_millis)
-Q(elapsed_micros)
-
-// for module weak links
-Q(binascii)
-Q(re)
-Q(zlib)
-Q(json)
-Q(heapq)
-Q(hashlib)
-
-// for USB configuration
-Q(usb_mode)
-Q(mode)
-Q(vid)
-Q(pid)
-Q(hid)
-Q(hid_mouse)
-Q(hid_keyboard)
-
 // for usb modes
-Q(host)
-Q(VCP)
-Q(MSC)
-Q(HID)
 Q(MSC+HID)
 Q(VCP+MSC)
 Q(VCP+HID)
-// CDC is a synonym for VCP for backwards compatibility
-Q(CDC)
 Q(CDC+MSC)
 Q(CDC+HID)
-
-// for USB VCP class
-Q(USB_VCP)
-Q(setinterrupt)
-Q(isconnected)
-Q(have_cdc)
-Q(any)
-Q(send)
-Q(recv)
-Q(timeout)
-
-// for USB HID class
-Q(USB_HID)
-Q(any)
-Q(send)
-Q(recv)
-
-// for RTC class
-Q(RTC)
-Q(info)
-Q(datetime)
-Q(wakeup)
-Q(calibration)
-
-// for Pin class
-Q(Pin)
-Q(PinAF)
-Q(PinNamed)
-Q(init)
-Q(value)
-Q(alt)
-Q(low)
-Q(high)
-Q(name)
-Q(names)
-Q(af)
-Q(af_list)
-Q(port)
-Q(pin)
-Q(gpio)
-Q(mapper)
-Q(dict)
-Q(debug)
-Q(board)
-Q(cpu)
-Q(af)
-Q(mode)
-Q(pull)
-Q(index)
-Q(reg)
-Q(IN)
-Q(OUT)
-Q(OPEN_DRAIN)
-Q(ALT)
-Q(ALT_OPEN_DRAIN)
-Q(ANALOG)
-Q(PULL_UP)
-Q(PULL_DOWN)
-Q(OUT_PP)
-Q(OUT_OD)
-Q(AF_PP)
-Q(AF_OD)
-Q(PULL_NONE)
-
-// for LED object
-Q(LED)
-Q(on)
-Q(off)
-Q(toggle)
-Q(intensity)
-
-// for Switch class
-Q(Switch)
-Q(callback)
-
-// for UART class
-Q(UART)
-Q(baudrate)
-Q(bits)
-Q(stop)
-Q(parity)
-Q(flow)
-Q(read_buf_len)
-Q(buf)
-Q(len)
-Q(timeout)
-Q(timeout_char)
-Q(init)
-Q(deinit)
-Q(any)
-Q(writechar)
-Q(readchar)
-Q(readinto)
-Q(sendbreak)
-Q(RTS)
-Q(CTS)
-
-// for CAN class
-#if MICROPY_HW_ENABLE_CAN
-Q(CAN)
-Q(prescaler)
-Q(init)
-Q(deinit)
-Q(all)
-Q(send)
-Q(recv)
-Q(addr)
-Q(fifo)
-Q(timeout)
-Q(extframe)
-Q(sjw)
-Q(bs1)
-Q(bs2)
-Q(bank)
-Q(params)
-Q(initfilterbanks)
-Q(clearfilter)
-Q(setfilter)
-Q(rxcallback)
-Q(rtr)
-Q(NORMAL)
-Q(LOOPBACK)
-Q(SILENT)
-Q(SILENT_LOOPBACK)
-Q(MASK16)
-Q(LIST16)
-Q(MASK32)
-Q(LIST32)
-#endif
-
-// for Timer class
-Q(Timer)
-Q(init)
-Q(deinit)
-Q(channel)
-Q(counter)
-Q(source_freq)
-Q(prescaler)
-Q(period)
-Q(callback)
-Q(freq)
-Q(mode)
-Q(div)
-Q(UP)
-Q(DOWN)
-Q(CENTER)
-Q(IC)
-Q(PWM)
-Q(PWM_INVERTED)
-Q(OC_TIMING)
-Q(OC_ACTIVE)
-Q(OC_INACTIVE)
-Q(OC_TOGGLE)
-Q(OC_FORCED_ACTIVE)
-Q(OC_FORCED_INACTIVE)
-Q(ENC_A)
-Q(ENC_B)
-Q(ENC_AB)
-Q(HIGH)
-Q(LOW)
-Q(RISING)
-Q(FALLING)
-Q(BOTH)
-
-// for TimerChannel class
-Q(TimerChannel)
-Q(pulse_width)
-Q(pulse_width_percent)
-Q(compare)
-Q(capture)
-Q(polarity)
-Q(deadtime)
-
-// for ExtInt class
-Q(ExtInt)
-Q(pin)
-Q(mode)
-Q(pull)
-Q(callback)
-Q(line)
-Q(enable)
-Q(disable)
-Q(swint)
-Q(regs)
-Q(IRQ_RISING)
-Q(IRQ_FALLING)
-Q(IRQ_RISING_FALLING)
-Q(EVT_RISING)
-Q(EVT_FALLING)
-Q(EVT_RISING_FALLING)
-
-// for I2C object
-Q(I2C)
-Q(mode)
-Q(addr)
-Q(baudrate)
-Q(gencall)
-Q(data)
-Q(memaddr)
-Q(addr_size)
-Q(timeout)
-Q(init)
-Q(deinit)
-Q(is_ready)
-Q(scan)
-Q(send)
-Q(recv)
-Q(mem_read)
-Q(mem_write)
-
-// for SPI class
-Q(SPI)
-Q(init)
-Q(deinit)
-Q(send)
-Q(recv)
-Q(send_recv)
-Q(mode)
-Q(baudrate)
-Q(polarity)
-Q(phase)
-Q(dir)
-Q(bits)
-Q(nss)
-Q(firstbit)
-Q(ti)
-Q(crc)
-Q(MASTER)
-Q(SLAVE)
-Q(MSB)
-Q(LSB)
-
-// for Accel object
-Q(Accel)
-Q(x)
-Q(y)
-Q(z)
-Q(tilt)
-Q(filtered_xyz)
-
-// for ADC object
-Q(ADC)
-Q(ADCAll)
-Q(read_timed)
-Q(read_channel)
-Q(read_core_temp)
-Q(read_core_vbat)
-Q(read_core_vref)
-
-// for DAC class
-Q(DAC)
-Q(noise)
-Q(triangle)
-Q(write)
-Q(write_timed)
-Q(data)
-Q(freq)
-Q(mode)
-Q(NORMAL)
-Q(CIRCULAR)
-
-// for Servo object
-Q(Servo)
-Q(pulse_width)
-Q(calibration)
-Q(angle)
-Q(speed)
-
-// for os module
-Q(uos)
-Q(os)
 Q(/)
-Q(flash)
-Q(sd)
-Q(sysname)
-Q(nodename)
-Q(release)
-Q(version)
-Q(machine)
-Q(uname)
-Q(chdir)
-Q(getcwd)
-Q(listdir)
-Q(mkdir)
-Q(rename)
-Q(remove)
-Q(rmdir)
-Q(unlink)
-Q(sep)
-Q(stat)
-Q(statvfs)
-Q(urandom)
-Q(dupterm)
-
-// for time module
-Q(utime)
-Q(time)
-Q(localtime)
-Q(mktime)
-Q(sleep)
-Q(sleep_ms)
-Q(sleep_us)
-Q(ticks_ms)
-Q(ticks_us)
-Q(ticks_cpu)
-Q(ticks_diff)
 
-// for select module
-Q(uselect)
-Q(select)
-Q(poll)
-Q(register)
-Q(unregister)
-Q(modify)
-Q(POLLIN)
-Q(POLLOUT)
-Q(POLLERR)
-Q(POLLHUP)
 
-// for input
-Q(input)
-
-// for LCD class
-Q(LCD)
-Q(command)
-Q(contrast)
-Q(light)
-Q(fill)
-Q(get)
-Q(pixel)
-Q(text)
-Q(show)
-
-// for usocket module
-Q(usocket)
-Q(socket)
-Q(getaddrinfo)
-Q(bind)
-Q(listen)
-Q(accept)
-Q(connect)
-Q(send)
-Q(recv)
-Q(sendto)
-Q(recvfrom)
-Q(setblocking)
-Q(setsockopt)
-Q(settimeout)
-Q(close)
-Q(AF_INET)
-Q(AF_INET6)
-Q(SOCK_STREAM)
-Q(SOCK_DGRAM)
-Q(SOCK_RAW)
-
-// for network module
-Q(network)
-Q(route)
-
-// for WIZNET5K class
-#if MICROPY_PY_WIZNET5K
-Q(WIZNET5K)
-Q(regs)
-Q(ifconfig)
-Q(ipaddr)
-#endif
-
-// for CC3K class
-#if MICROPY_PY_CC3K
-Q(CC3K)
-Q(connect)
-Q(disconnect)
-Q(isconnected)
-Q(ifconfig)
-Q(patch_version)
-Q(patch_program)
-Q(WEP)
-Q(WPA)
-Q(WPA2)
-Q(ssid)
-Q(key)
-Q(security)
-Q(bssid)
-#endif
-
-// for stm module
-Q(stm)
-Q(mem)
-Q(mem8)
-Q(mem16)
-Q(mem32)
+// The following qstrings not referenced from anywhere in the sources
+Q(CDC)
+Q(flash)
diff --git a/teensy/Makefile b/teensy/Makefile
index 5a03f28ee..de7036571 100644
--- a/teensy/Makefile
+++ b/teensy/Makefile
@@ -218,6 +218,12 @@ GEN_PINS_QSTR = $(BUILD)/pins_qstr.h
 GEN_PINS_AF_CONST = $(HEADER_BUILD)/pins_af_const.h
 GEN_PINS_AF_PY = $(BUILD)/pins_af.py
 
+# List of sources for qstr extraction
+SRC_QSTR += $(SRC_C) $(STM_SRC_C)
+# Append any auto-generated sources that are needed by sources listed in
+# SRC_QSTR
+SRC_QSTR_AUTO_DEPS +=
+
 # Making OBJ use an order-only depenedency on the generated pins.h file
 # has the side effect of making the pins.h file before we actually compile
 # any of the objects. The normal dependency generation will deal with the
diff --git a/teensy/qstrdefsport.h b/teensy/qstrdefsport.h
index aa466624a..3ba897069 100644
--- a/teensy/qstrdefsport.h
+++ b/teensy/qstrdefsport.h
@@ -1,149 +1 @@
 // qstrs specific to this port
-
-Q(help)
-Q(pyb)
-Q(info)
-Q(sd_test)
-Q(stop)
-Q(standby)
-Q(source_dir)
-Q(main)
-Q(sync)
-Q(gc)
-Q(delay)
-Q(switch)
-Q(servo)
-Q(pwm)
-Q(accel)
-Q(mma_read)
-Q(mma_mode)
-Q(hid)
-Q(time)
-Q(rand)
-Q(LED)
-Q(led)
-Q(Servo)
-Q(I2C)
-Q(gpio)
-Q(Usart)
-Q(ADC)
-Q(open)
-Q(analogRead)
-Q(analogWrite)
-Q(analogWriteResolution)
-Q(analogWriteFrequency)
-Q(on)
-Q(off)
-Q(toggle)
-Q(readall)
-Q(readinto)
-Q(readline)
-Q(readlines)
-Q(FileIO)
-Q(input)
-Q(os)
-Q(bootloader)
-Q(unique_id)
-Q(freq)
-Q(repl_info)
-Q(wfi)
-Q(disable_irq)
-Q(enable_irq)
-Q(usb_mode)
-Q(have_cdc)
-Q(millis)
-Q(micros)
-Q(elapsed_millis)
-Q(elapsed_micros)
-Q(udelay)
-Q(UART)
-
-// for Pin class
-Q(Pin)
-Q(PinAF)
-Q(PinNamed)
-Q(init)
-Q(value)
-Q(alt)
-Q(low)
-Q(high)
-Q(name)
-Q(names)
-Q(af)
-Q(af_list)
-Q(port)
-Q(pin)
-Q(gpio)
-Q(mapper)
-Q(dict)
-Q(debug)
-Q(board)
-Q(cpu)
-Q(mode)
-Q(pull)
-Q(index)
-Q(reg)
-Q(IN)
-Q(OUT)
-Q(OPEN_DRAIN)
-Q(ALT)
-Q(ALT_OPEN_DRAIN)
-Q(ANALOG)
-Q(PULL_UP)
-Q(PULL_DOWN)
-Q(OUT_PP)
-Q(OUT_OD)
-Q(AF_PP)
-Q(AF_OD)
-Q(PULL_NONE)
-
-// for Timer class
-Q(Timer)
-Q(init)
-Q(deinit)
-Q(channel)
-Q(counter)
-Q(prescaler)
-Q(period)
-Q(callback)
-Q(freq)
-Q(mode)
-Q(reg)
-Q(UP)
-Q(CENTER)
-Q(IC)
-Q(PWM)
-Q(PWM_INVERTED)
-Q(OC_TIMING)
-Q(OC_ACTIVE)
-Q(OC_INACTIVE)
-Q(OC_TOGGLE)
-Q(OC_FORCED_ACTIVE)
-Q(OC_FORCED_INACTIVE)
-Q(HIGH)
-Q(LOW)
-Q(RISING)
-Q(FALLING)
-Q(BOTH)
-
-// for TimerChannel class
-Q(TimerChannel)
-Q(pulse_width)
-Q(pulse_width_percent)
-Q(compare)
-Q(capture)
-Q(polarity)
-t
-// for UART class
-Q(UART)
-Q(baudrate)
-Q(bits)
-Q(stop)
-Q(parity)
-Q(init)
-Q(deinit)
-Q(all)
-Q(send)
-Q(recv)
-Q(timeout)
-
diff --git a/unix/Makefile b/unix/Makefile
index 6d6239f78..dbb88b714 100644
--- a/unix/Makefile
+++ b/unix/Makefile
@@ -170,6 +170,13 @@ OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
 OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o))
 OBJ += $(addprefix $(BUILD)/, $(STMHAL_SRC_C:.c=.o))
 
+# List of sources for qstr extraction
+SRC_QSTR += $(SRC_C) $(LIB_SRC_C)
+# Append any auto-generated sources that are needed by sources listed in
+# SRC_QSTR
+SRC_QSTR_AUTO_DEPS +=
+
+
 include ../py/mkrules.mk
 
 .PHONY: test
diff --git a/unix/qstrdefsport.h b/unix/qstrdefsport.h
index 36126a3b2..8ab2db58f 100644
--- a/unix/qstrdefsport.h
+++ b/unix/qstrdefsport.h
@@ -23,127 +23,3 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-
-// qstrs specific to this port
-
-Q(Test)
-
-Q(fileno)
-Q(makefile)
-Q(buffering)
-
-Q(FileIO)
-Q(flush)
-
-Q(uos)
-Q(stat)
-#if MICROPY_PY_OS_STATVFS
-Q(statvfs)
-#endif
-Q(system)
-Q(unlink)
-Q(getenv)
-Q(mkdir)
-Q(ilistdir)
-Q(errno)
-#if MICROPY_FSUSERMOUNT
-Q(vfs_mount)
-Q(vfs_umount)
-Q(vfs_mkfs)
-#endif
-#if MICROPY_VFS_FAT
-Q(VfsFat)
-#endif
-#if MICROPY_PY_OS_DUPTERM
-Q(dupterm)
-#endif
-
-Q(uselect)
-Q(poll)
-Q(register)
-Q(unregister)
-Q(modify)
-Q(POLLIN)
-Q(POLLOUT)
-Q(POLLERR)
-Q(POLLHUP)
-
-Q(ffi)
-Q(ffimod)
-Q(ffifunc)
-Q(fficallback)
-Q(ffivar)
-Q(as_bytearray)
-Q(callback)
-Q(addr)
-Q(func)
-Q(var)
-Q(get)
-Q(set)
-
-Q(input)
-Q(utime)
-Q(time)
-Q(clock)
-Q(sleep)
-Q(sleep_ms)
-Q(sleep_us)
-Q(ticks_ms)
-Q(ticks_us)
-Q(ticks_diff)
-Q(strftime)
-
-Q(socket)
-Q(sockaddr)
-Q(htons)
-Q(inet_pton)
-Q(inet_ntop)
-Q(gethostbyname)
-Q(getaddrinfo)
-Q(usocket)
-Q(connect)
-Q(bind)
-Q(listen)
-Q(accept)
-Q(recv)
-Q(recvfrom)
-Q(sendto)
-Q(setsockopt)
-Q(setblocking)
-
-Q(AF_UNIX)
-Q(AF_INET)
-Q(AF_INET6)
-Q(SOCK_STREAM)
-Q(SOCK_DGRAM)
-Q(SOCK_RAW)
-
-Q(MSG_DONTROUTE)
-Q(MSG_DONTWAIT)
-
-Q(SOL_SOCKET)
-Q(SO_BROADCAST)
-Q(SO_ERROR)
-Q(SO_KEEPALIVE)
-Q(SO_LINGER)
-Q(SO_REUSEADDR)
-
-#if MICROPY_PY_TERMIOS
-Q(termios)
-Q(tcgetattr)
-Q(tcsetattr)
-Q(setraw)
-Q(TCSANOW)
-Q(B9600)
-Q(B57600)
-Q(B115200)
-#endif
-
-#if MICROPY_PY_JNI
-Q(jni)
-Q(cls)
-Q(env)
-Q(jclass)
-Q(jobject)
-Q(jmethod)
-#endif
diff --git a/windows/Makefile b/windows/Makefile
index ba89fccae..68de66a07 100644
--- a/windows/Makefile
+++ b/windows/Makefile
@@ -56,4 +56,10 @@ endif
 
 LIB += -lws2_32
 
+# List of sources for qstr extraction
+SRC_QSTR += $(SRC_C)
+# Append any auto-generated sources that are needed by sources listed in
+# SRC_QSTR
+SRC_QSTR_AUTO_DEPS +=
+
 include ../py/mkrules.mk
-- 
GitLab