Commit d76c65f5 authored by Jan Čapek's avatar Jan Čapek Committed by Damien George
Browse files

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 m...
parent dbbf0827
......@@ -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)
......
......@@ -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)
......@@ -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
......
// 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)
......@@ -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
......
......@@ -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
......
......@@ -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