esp32: Fix link failure due to link library order.

When a wrapped symbol is provided in its own file, it's possible for the
linker to skip that file entirely and not return to it depending on the
order of libraries passed on the linker command line.

This is because these wrapped symbols create linker cycles (libmain_espXX
depends on liblwip but liblwip now also depends on libmain for the wrapped
functions in lwip_patch.c, for example.)

Linker failure for symbols in lwip_patch.c was reproducible if mDNS was
disabled in the board configuration.

This commit adds an explicit undefined symbol for each file, to ensure
the linker will add the wrapped objects on its first pass.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
diff --git a/ports/esp32/esp32_common.cmake b/ports/esp32/esp32_common.cmake
index 9d51a03..0a6b299 100644
--- a/ports/esp32/esp32_common.cmake
+++ b/ports/esp32/esp32_common.cmake
@@ -242,12 +242,19 @@
 target_link_libraries(${MICROPY_TARGET} micropy_extmod_btree)
 target_link_libraries(${MICROPY_TARGET} usermod)
 
-# Enable the panic handler wrapper
-idf_build_set_property(LINK_OPTIONS "-Wl,--wrap=esp_panic_handler" APPEND)
+# Extra linker options
+# (when wrap symbols are in standalone files, --undefined ensures
+# the linker doesn't skip that file.)
+target_link_options(${MICROPY_TARGET} PUBLIC
+  # Patch LWIP memory pool allocators (see lwip_patch.c)
+  -Wl,--undefined=memp_malloc
+  -Wl,--wrap=memp_malloc
+  -Wl,--wrap=memp_free
 
-# Patch LWIP memory pool allocators (see lwip_patch.c)
-idf_build_set_property(LINK_OPTIONS "-Wl,--wrap=memp_malloc" APPEND)
-idf_build_set_property(LINK_OPTIONS "-Wl,--wrap=memp_free" APPEND)
+  # Enable the panic handler wrapper
+  -Wl,--undefined=esp_panic_handler
+  -Wl,--wrap=esp_panic_handler
+)
 
 # Collect all of the include directories and compile definitions for the IDF components,
 # including those added by the IDF Component Manager via idf_components.yaml.