跪拜 Guibai
← All articles
Embedded

Linking lwIP as a Library: A Standalone TCP Client on Windows

By NiCo ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Moving lwIP out of the example_app and into a library-style build is the step that separates a learning sandbox from a real project skeleton. The three build pitfalls are not lwIP bugs but undocumented coupling points in the win32 Filelists—anyone following the official BUILDING docs will hit them on the first `cmake` invocation.

Summary

The lwIP stack moves out of the bundled example_app and into a standalone CMake project that links only the protocol core and the win32 port library. The build pulls in exactly two Filelists—one for lwipcore, one for the pcapif driver and sys_arch layer—and leaves the rest of the contrib tree out. A 159-line main.c handles the four required init steps, then spawns a thread that opens a socket to 1.1.1.1:80 and sends an HTTP GET.

Three build-breaking pitfalls surface immediately when the example scaffolding is removed: a win32 Filelists script references a target that doesn't exist unless the full contrib tree is included, PPP source files still demand a `ppp_settings.h` header even with `PPP_SUPPORT=0`, and roughly 40 errno macros collide with UCRT64's system headers unless lwIP includes come first. Each fix is a small patch or a one-line reorder, but together they expose the hidden assumptions that the example_app build quietly papers over.

The result is a clean baseline where lwIP behaves like a normal library dependency. From here, functional trimming happens entirely through `lwipopts.h` switches—disable IPv6, disable PPP, drop unused stats—and each change can be verified by recompiling and re-running the client.

Takeaways
lwIP integrates via CMake Filelists: include `src/Filelists.cmake` for lwipcore and `contrib/ports/win32/Filelists.cmake` for the win32 port library, then link both.
A minimal lwIP application needs exactly four pieces: lwipcore, a sys_arch layer, a netif driver, and two config headers (lwipopts.h and lwipcfg.h).
`PPP_SUPPORT=0` disables PPP logic but does not remove PPP source files from the compilation list; `ppp_settings.h` must still be present or the build fails.
Including lwIP headers before system headers prevents ~40 errno macro redefinition errors under `-Werror` on UCRT64.
The win32 port's Filelists script assumes the full contrib tree is included and will error on a missing `lwipcontribaddons` target unless guarded with `if(TARGET ...)`.
Under `-Werror -Wunreachable-code`, a `for(;;)` loop cannot be followed by a `return` statement—the compiler proves it unreachable and treats it as an error.
The `lwipcfg.h` for a pcapif-based build only needs three things: adapter GUID, static IP config, and a MAC address with the last byte decremented by one.
Conclusions

lwIP's official BUILDING documentation describes a clean library-integration path, but the win32 Filelists carry an undocumented dependency on the full contrib tree that breaks the moment you follow that path literally.

The three pitfalls all share a root cause: the example_app build is a monolith that never exercises the partial-include scenario, so upstream never sees these failures.

Functional compile-time switches in lwIP (`PPP_SUPPORT`, `LWIP_IPV6`) control logic but not file inclusion—the compilation list is fixed at the Filelists level, which means unused code still compiles unless you manually exclude directories.

The errno collision is a systemic tension between lwIP's own errno values and the C library's, and the `#undef` workaround from Part 1 was always a fragile stopgap that doesn't scale past two or three macros.

Concepts & terms
lwIP Filelists
CMake scripts shipped with lwIP (e.g., `src/Filelists.cmake`, `contrib/ports/win32/Filelists.cmake`) that define library targets and their source files. Projects include them to pull in the protocol stack or port layers without manually listing every .c file.
sys_arch porting layer
The OS abstraction layer lwIP requires for threading, semaphores, and mailbox queues. On bare-metal or RTOS targets it must be hand-written; the win32 port provides a ready-made implementation using Windows threads.
pcapif
A win32-specific netif driver that sends and receives real Ethernet frames through Npcap, allowing lwIP to use a physical network adapter on Windows without a custom MAC/DMA driver.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗