跪拜 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.
From the discussion

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.

The repository link in the article is currently broken and will be corrected the following day.
Full source code download will be available once the author finishes updating the repository.
Featured comments
浪花一朵朵2026

Can the entire source code be downloaded from the repository?

NiCo

Yeah, gotta wait until I finish updating it [grin][grin]

See top comments, translated →
Source: juejin.cn ↗ Google Translate ↗ Backup ↗