Linking lwIP as a Library: A Standalone TCP Client on Windows
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.
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.
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.
The discussion is minimal. One person asks whether the full source code can be downloaded from the repository. The author confirms it will be available after an update, and notes a broken repository link that needs fixing.
Can the entire source code be downloaded from the repository?
Yeah, gotta wait until I finish updating it [grin][grin]