From ef5bc352fbe76eeaf412677c9718cbaead59785b Mon Sep 17 00:00:00 2001 From: Dirk Ziegelmeier Date: Mon, 8 Oct 2018 22:17:03 +0200 Subject: [PATCH] Document CMake build system --- BUILDING | 107 ++++++++++++++++++ CMakeLists.txt | 5 +- contrib/ports/unix/example_app/CMakeLists.txt | 12 +- .../ports/win32/example_app/CMakeLists.txt | 12 +- doc/doxygen/main_page.h | 75 ++++++------ 5 files changed, 163 insertions(+), 48 deletions(-) create mode 100644 BUILDING diff --git a/BUILDING b/BUILDING new file mode 100644 index 00000000..01037e27 --- /dev/null +++ b/BUILDING @@ -0,0 +1,107 @@ +Building lwIP +============= + +lwIP uses a CMake based build system. + +The CMake files in this project are designed to +be included into your own CMake files. They are +mainly variable definitions containing a list of +source files and predefined static libraries to +be linked against application code. + +1) lwIP sources: + src/Filelists.cmake provides file lists containing + the lwIP core library. + The file also contains two static libraries, lwipcore + and lwipallapps, where you can link your app against. + This is the file that is useful to all lwIP users. + +2) Example applications: + contrib/Filelists.cmake provides several file lists + containing the example applications. + The file also contains several static libraries + for these example apps. + This file is only useful for you, if you can use one + of the examples in your application, which is normally + not the case. + +3) OS/platform port: + Usually the OS port needs to be provided by the user. + If a port to Linux, Windows or MacOS is useful for + you, you can use + contrib/ports/{win32, unix}/Filelists.cmake + that contains file lists and libraries for + these operating systems. + +VARIABLES +========= +In all cases, you need to provide two variables. + +"LWIP_DIR" pointing to the lwIP directory +Example: +set(LWIP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lwip) + +"LWIP_INCLUDE_DIRS" that contains the include base paths +- for lwIP itself (${LWIP_DIR}/src/include) +- for lwIP contrib if you use it (${LWIP_CONTRIB_DIR}/) +- to a directory for an lwIP OS port +- to a directory containing lwipopts.h + +Example: +set (LWIP_INCLUDE_DIRS + "${LWIP_DIR}/src/include" + "${LWIP_DIR}/contrib" + "${LWIP_DIR}/contrib/ports/unix/port/include" + "${LWIP_DIR}/contrib/examples/example_app" +) + +Putting it all together +======================= +To get a working application, your CMake system +needs to provide the variables described above, e.g. +set (LWIP_DIR ) +set (LWIP_INCLUDE_DIRS + "${LWIP_DIR}/src/include" + "${LWIP_DIR}/contrib" + "/include" + "" +) + +You may add some defines: +set (LWIP_DEFINITIONS LWIP_DEBUG=1) + +Then include the filelists you need: +include(${LWIP_DIR}/src/Filelists.cmake) +include(${LWIP_DIR}/contrib/Filelists.cmake) + +Then, declare you executable: +add_executable(my_app ) + +Add lwIP include dirs to your app: +target_include_directories(my_app PRIVATE ${LWIP_INCLUDE_DIRS}) + +Link your app against the lwIP libs from the filelists you need: +target_link_libraries(my_app lwipcontribapps lwipallapps lwipcore) + +Working example +=============== +Working build examples can be found in the +contrib/ports/{win32, unix}/example_app +subdirectory. +To use them, create a build directory and call cmake with +the lwIP root dir: + +- mkdir build +- cd build +- cmake +- cmake --build + +The CMakeLists.txt will autoselect the correct port +for your system. + +Makefile based build system +=========================== +lwIP also maintains file lists for Makefile-based +build systems. Look for Filelists.mk files +in the source tree. We try to maintain them, +but lwIP's mainly focused build system is CMake. diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ec3ebf8..7ffcfba6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,8 +9,10 @@ set (LWIP_DEFINITIONS LWIP_DEBUG=1) if (${CMAKE_SYSTEM_NAME} STREQUAL Windows) add_subdirectory(${LWIP_DIR}/contrib/ports/win32/example_app) -else() +elseif(${CMAKE_SYSTEM_NAME} STREQUAL Linux OR ${CMAKE_SYSTEM_NAME} STREQUAL Darwin) add_subdirectory(${LWIP_DIR}/contrib/ports/unix/example_app) +else() + message(WARNING "Host ${CMAKE_SYSTEM_NAME} is not supported to build example_app") endif() # Source package generation @@ -24,5 +26,6 @@ set(CPACK_SOURCE_PACKAGE_FILE_NAME "lwip-${LWIP_VERSION_MAJOR}.${LWIP_VERSION_MI include(CPack) # Target for package generation +include(src/Filelists.cmake) add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source) add_dependencies(dist lwipdocs) diff --git a/contrib/ports/unix/example_app/CMakeLists.txt b/contrib/ports/unix/example_app/CMakeLists.txt index 0e59a52f..5fa92862 100644 --- a/contrib/ports/unix/example_app/CMakeLists.txt +++ b/contrib/ports/unix/example_app/CMakeLists.txt @@ -2,16 +2,16 @@ include(${LWIP_DIR}/contrib/ports/CMakeCommon.cmake) set (LWIP_INCLUDE_DIRS "${LWIP_DIR}/src/include" - "${LWIP_CONTRIB_DIR}/" - "${LWIP_CONTRIB_DIR}/ports/unix/port/include" - "${LWIP_CONTRIB_DIR}/examples/example_app" + "${LWIP_DIR}/contrib/" + "${LWIP_DIR}/contrib/ports/unix/port/include" + "${LWIP_DIR}/contrib/examples/example_app" ) include(${LWIP_DIR}/src/Filelists.cmake) -include(${LWIP_CONTRIB_DIR}/Filelists.cmake) -include(${LWIP_CONTRIB_DIR}/ports/unix/Filelists.cmake) +include(${LWIP_DIR}/contrib/Filelists.cmake) +include(${LWIP_DIR}/contrib/ports/unix/Filelists.cmake) -add_executable(example_app ${LWIP_CONTRIB_DIR}/examples/example_app/test.c default_netif.c) +add_executable(example_app ${LWIP_DIR}/contrib/examples/example_app/test.c default_netif.c) target_include_directories(example_app PRIVATE ${LWIP_INCLUDE_DIRS}) target_compile_options(example_app PRIVATE ${LWIP_COMPILER_FLAGS}) target_compile_definitions(example_app PRIVATE ${LWIP_DEFINITIONS} ${LWIP_MBEDTLS_DEFINITIONS}) diff --git a/contrib/ports/win32/example_app/CMakeLists.txt b/contrib/ports/win32/example_app/CMakeLists.txt index a7173a3a..34a9221e 100644 --- a/contrib/ports/win32/example_app/CMakeLists.txt +++ b/contrib/ports/win32/example_app/CMakeLists.txt @@ -2,16 +2,16 @@ include(${LWIP_DIR}/contrib/ports/CMakeCommon.cmake) set (LWIP_INCLUDE_DIRS "${LWIP_DIR}/src/include" - "${LWIP_CONTRIB_DIR}/" - "${LWIP_CONTRIB_DIR}/ports/win32/include" - "${LWIP_CONTRIB_DIR}/examples/example_app" + "${LWIP_DIR}/contrib/" + "${LWIP_DIR}/contrib/ports/win32/include" + "${LWIP_DIR}/contrib/examples/example_app" ) include(${LWIP_DIR}/src/Filelists.cmake) -include(${LWIP_CONTRIB_DIR}/Filelists.cmake) -include(${LWIP_CONTRIB_DIR}/ports/win32/Filelists.cmake) +include(${LWIP_DIR}/contrib/Filelists.cmake) +include(${LWIP_DIR}/contrib/ports/win32/Filelists.cmake) -add_executable(example_app ${LWIP_CONTRIB_DIR}/examples/example_app/test.c default_netif.c) +add_executable(example_app ${LWIP_DIR}/contrib/examples/example_app/test.c default_netif.c) target_include_directories(example_app PRIVATE ${LWIP_INCLUDE_DIRS}) target_compile_options(example_app PRIVATE ${LWIP_COMPILER_FLAGS}) target_compile_definitions(example_app PRIVATE ${LWIP_DEFINITIONS} ${LWIP_MBEDTLS_DEFINITIONS}) diff --git a/doc/doxygen/main_page.h b/doc/doxygen/main_page.h index 883112e2..55b36b15 100644 --- a/doc/doxygen/main_page.h +++ b/doc/doxygen/main_page.h @@ -2,14 +2,14 @@ * @defgroup lwip lwIP * * @defgroup infrastructure Infrastructure - * + * * @defgroup api APIs * lwIP provides three Application Program's Interfaces (APIs) for programs * to use for communication with the TCP/IP code: * - low-level "core" / "callback" or @ref callbackstyle_api. * - higher-level @ref sequential_api. * - BSD-style @ref socket. - * + * * The raw TCP/IP interface allows the application program to integrate * better with the TCP/IP code. Program execution is event based by * having callback functions being called from within the TCP/IP @@ -17,23 +17,23 @@ * thread. The sequential API has a much higher overhead and is not very * well suited for small systems since it forces a multithreaded paradigm * on the application. - * + * * The raw TCP/IP interface is not only faster in terms of code execution * time but is also less memory intensive. The drawback is that program * development is somewhat harder and application programs written for * the raw TCP/IP interface are more difficult to understand. Still, this * is the preferred way of writing applications that should be small in * code size and memory usage. - * + * * All APIs can be used simultaneously by different application * programs. In fact, the sequential API is implemented as an application * program using the raw TCP/IP interface. - * + * * Do not confuse the lwIP raw API with raw Ethernet or IP sockets. * The former is a way of interfacing the lwIP network stack (including * TCP and UDP), the latter refers to processing raw Ethernet or IP data * instead of TCP connections or UDP packets. - * + * * Raw API applications may never block since all packet processing * (input and output) as well as timer processing (TCP mainly) is done * in a single execution context. @@ -59,7 +59,7 @@ * receive. This API is also used by the core stack for interaction between * the various protocols. It is the only API available when running lwIP * without an operating system. - * + * * @defgroup sequential_api Sequential-style APIs * @ingroup api * Sequential-style APIs, blocking functions. More overhead, but can be called @@ -70,7 +70,7 @@ * paradigm. Since the TCP/IP stack is event based by nature, the TCP/IP * code and the application program must reside in different execution * contexts (threads). - * + * * @defgroup socket Socket API * @ingroup api * BSD-style socket API.\n @@ -83,9 +83,9 @@ * on other platforms (e.g. unix / windows etc.). However, due to limitations * in the specification of this API, there might be incompatibilities * that require small modifications of existing programs. - * + * * @defgroup netifs NETIFs - * + * * @defgroup apps Applications */ @@ -112,7 +112,7 @@ * * Add sys_mbox_trypost_fromisr() and tcpip_callbackmsg_trycallback_fromisr() * (for FreeRTOS, mainly) * * socket API: support poll(), sendmsg() and recvmsg(); fix problems on close - * + * * Detailed Changelog * ------------------ * @verbinclude "CHANGELOG" @@ -123,6 +123,11 @@ * @verbinclude "contrib.txt" */ +/** + * @page cmake CMake build system + * @verbinclude "BUILDING" + */ + /** * @page pitfalls Common pitfalls * @@ -131,21 +136,21 @@ * * The most common source of lwIP problems is to have multiple execution contexts * inside the lwIP code. - * - * lwIP can be used in two basic modes: @ref lwip_nosys (no OS/RTOS + * + * lwIP can be used in two basic modes: @ref lwip_nosys (no OS/RTOS * running on target system) or @ref lwip_os (there is an OS running * on the target system). - * + * * See also: @ref multithreading (especially the part about @ref LWIP_ASSERT_CORE_LOCKED()!) * * Mainloop Mode * ------------- * In mainloop mode, only @ref callbackstyle_api can be used. - * The user has two possibilities to ensure there is only one + * The user has two possibilities to ensure there is only one * exection context at a time in lwIP: * * 1) Deliver RX ethernet packets directly in interrupt context to lwIP - * by calling netif->input directly in interrupt. This implies all lwIP + * by calling netif->input directly in interrupt. This implies all lwIP * callback functions are called in IRQ context, which may cause further * problems in application code: IRQ is blocked for a long time, multiple * execution contexts in application code etc. When the application wants @@ -171,7 +176,7 @@ * implemented in tcpip_input().​​ * Again, ensure lwIP is _NEVER_ called from an interrupt, e.g. * some SPI IRQ wants to forward data to udp_send() or tcp_write()! - * + * * 1) tcpip_callback() can be used get called back from TCPIP thread, * it is safe to call any @ref callbackstyle_api from there. * @@ -186,7 +191,7 @@ * * DMA-capable ethernet hardware and zero-copy RX * ---------------------------------------------- - * + * * lwIP changes the content of RECEIVED pbufs in the TCP code path. * This implies one or more cacheline(s) of the RX pbuf become dirty * and need to be flushed before the memory is handed over to the @@ -225,7 +230,7 @@ * *not* *from* *interrupt* *context*. You can allocate a @ref pbuf in interrupt * context and put them into a queue which is processed from mainloop.\n * Call sys_check_timeouts() periodically in the mainloop.\n - * Porting: implement all functions in @ref sys_time, @ref sys_prot and + * Porting: implement all functions in @ref sys_time, @ref sys_prot and * @ref compiler_abstraction.\n * You can only use @ref callbackstyle_api in this mode.\n * Sample code:\n @@ -265,12 +270,12 @@ Call these functions in the order of appearance: The init function pointer must point to a initialization function for your Ethernet netif interface. The following code illustrates its use. - + @code{.c} err_t netif_if_init(struct netif *netif) { u8_t i; - + for (i = 0; i < ETHARP_HWADDR_LEN; i++) { netif->hwaddr[i] = some_eth_addr[i]; } @@ -278,11 +283,11 @@ Call these functions in the order of appearance: return ERR_OK; } @endcode - + For Ethernet drivers, the input function pointer must point to the lwIP function ethernet_input() declared in "netif/etharp.h". Other drivers must use ip_input() declared in "lwip/ip.h". - + - netif_set_default(struct netif *netif) Registers the default network interface. @@ -317,7 +322,7 @@ Call these functions in the order of appearance: * from pbuf- and memory management functions). Application threads using * the sequential- or socket API communicate with this main thread through * message passing. - * + * * As such, the list of functions that may be called from * other threads or an ISR is very limited! Only functions * from these API header files are thread-safe: @@ -328,43 +333,43 @@ Call these functions in the order of appearance: * - pppapi.h * - sockets.h * - sys.h - * + * * Additionaly, memory (de-)allocation functions may be * called from multiple threads (not ISR!) with NO_SYS=0 * since they are protected by @ref SYS_LIGHTWEIGHT_PROT and/or * semaphores. - * + * * Netconn or Socket API functions are thread safe against the * core thread but they are not reentrant at the control block * granularity level. That is, a UDP or TCP control block must * not be shared among multiple threads without proper locking. - * + * * If @ref SYS_LIGHTWEIGHT_PROT is set to 1 and * @ref LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT is set to 1, * pbuf_free() may also be called from another thread or * an ISR (since only then, mem_free - for PBUF_RAM - may * be called from an ISR: otherwise, the HEAP is only * protected by semaphores). - * + * * How to get threading done right * ------------------------------- - * + * * It is strongly recommended to implement the LWIP_ASSERT_CORE_LOCKED() * macro in an application that uses multithreading. lwIP code has * several places where a check for a correct thread context is * implemented which greatly helps the user to get threading done right. - * See the example sys_arch.c files in unix and Win32 port + * See the example sys_arch.c files in unix and Win32 port * in the lwIP/contrib subdirectory. - * - * In short: Copy the functions sys_mark_tcpip_thread() and + * + * In short: Copy the functions sys_mark_tcpip_thread() and * sys_check_core_locking() to your port and modify them to work with your OS. * Then let @ref LWIP_ASSERT_CORE_LOCKED() and @ref LWIP_MARK_TCPIP_THREAD() * point to these functions. - * + * * If you use @ref LWIP_TCPIP_CORE_LOCKING, you also need to copy and adapt * the functions sys_lock_tcpip_core() and sys_unlock_tcpip_core(). - * Let @ref LOCK_TCPIP_CORE() and @ref UNLOCK_TCPIP_CORE() point - * to these functions. + * Let @ref LOCK_TCPIP_CORE() and @ref UNLOCK_TCPIP_CORE() point + * to these functions. */ /**