From 01a9f178251ef1157e26e26bb40420c9cee72bf0 Mon Sep 17 00:00:00 2001 From: Kefu Chai Date: Wed, 15 Nov 2017 20:54:46 +0800 Subject: [PATCH] cmake: build spdk/dpdk in cmake modules Signed-off-by: Kefu Chai Signed-off-by: wanjun.lp Signed-off-by: Ziye Yang --- CMakeLists.txt | 3 +- cmake/modules/BuildDPDK.cmake | 118 ++++++++++++++++++++++++++++++++++ cmake/modules/BuildSPDK.cmake | 33 ++++++++++ cmake/modules/FindCUnit.cmake | 23 +++++++ src/os/CMakeLists.txt | 21 ++---- 5 files changed, 181 insertions(+), 17 deletions(-) create mode 100644 cmake/modules/BuildDPDK.cmake create mode 100644 cmake/modules/BuildSPDK.cmake create mode 100644 cmake/modules/FindCUnit.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 5a9360b604c..520c7020077 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -217,7 +217,8 @@ endif() option(WITH_SPDK "Enable SPDK" OFF) if(WITH_SPDK) - find_package(dpdk REQUIRED) + include(BuildSPDK) + build_spdk() set(HAVE_SPDK TRUE) endif(WITH_SPDK) diff --git a/cmake/modules/BuildDPDK.cmake b/cmake/modules/BuildDPDK.cmake new file mode 100644 index 00000000000..4ae38caa20a --- /dev/null +++ b/cmake/modules/BuildDPDK.cmake @@ -0,0 +1,118 @@ +function(do_build_dpdk dpdk_dir) + if(CMAKE_SYSTEM_PROCESSOR MATCHES "i386") + set(arch "x86_64") + set(machine "default") + set(machine_tmpl "native") + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "i686") + set(arch "i686") + set(machine "default") + set(machine_tmpl "native") + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64|x86_64|AMD64") + set(arch "x86_64") + set(machine "default") + set(machine_tmpl "native") + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "arm|ARM") + set(arch "arm") + set(machine "armv7a") + set(machine_tmpl "armv7a") + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|AARCH64") + set(arch "arm64") + set(machine "armv8a") + set(machine_tmpl "armv8a") + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "(powerpc|ppc)64") + set(arch "ppc_64") + set(machine "power8") + set(machine_tmpl "power8") + else() + message(FATAL_ERROR "not able to build DPDK support: " + "unknown arch \"${CMAKE_SYSTEM_PROCESSOR}\"") + endif() + + if(CMAKE_SYSTEM_NAME MATCHES "Linux") + set(execenv "linuxapp") + elseif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + set(execenv "bsdapp") + else() + message(FATAL_ERROR "not able to build DPDK support: " + "unsupported OS \"${CMAKE_SYSTEM_NAME}\"") + endif() + + if(CMAKE_C_COMPILER_ID STREQUAL GNU) + set(toolchain "gcc") + elseif(CMAKE_C_COMPILER_ID STREQUAL Clang) + set(toolchain "clang") + elseif(CMAKE_C_COMPILER_ID STREQUAL Intel) + set(toolchain "icc") + else() + message(FATAL_ERROR "not able to build DPDK support: " + "unknown compiler \"${CMAKE_C_COMPILER_ID}\"") + endif() + + set(target "${arch}-${machine_tmpl}-${execenv}-${toolchain}") + + execute_process( + COMMAND make showconfigs + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src/spdk/dpdk + OUTPUT_VARIABLE supported_targets + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(REPLACE "\n" ";" supported_targets "${supported_targets}") + list(FIND supported_targets ${target} found) + if(found EQUAL -1) + message(FATAL_ERROR "not able to build DPDK support: " + "unsupported target \"${target}\"") + endif() + + if(WITH_KERNEL_DIR) + if(NOT IS_DIRECTORY ${WITH_KERNEL_DIR}) + message(FATAL "not able to build DPDK support: " + "WITH_KERNEL_DIR=\"${WITH_KERNEL_DIR}\" does not exist") + endif() + else() + execute_process( + COMMAND uname -r + OUTPUT_VARIABLE kernel_release + OUTPUT_STRIP_TRAILING_WHITESPACE) + set(kernel_header_dir "/lib/modules/${kernel_release}/build") + if(NOT IS_DIRECTORY ${kernel_header_dir}) + message(FATAL "not able to build DPDK support: " + "\"${kernel_header_dir}\" does not exist. DPDK uses it for building " + "kernel modules. Please either disable WITH_DPDK and WITH_SPDK, " + "or install linux-headers of the kernel version of the target machine, " + "and specify \"-DWITH_RTE_KERNEL_DIR= " + "when running \"cmake\"") + endif() + set(WITH_KERNEL_DIR ${kernel_header_dir}) + endif(WITH_KERNEL_DIR) + include(ExternalProject) + ExternalProject_Add(dpdk-ext + SOURCE_DIR ${CMAKE_SOURCE_DIR}/src/spdk/dpdk + CONFIGURE_COMMAND $(MAKE) config O=${dpdk_dir} T=${target} + BUILD_COMMAND env CC=${CMAKE_C_COMPILER} $(MAKE) O=${dpdk_dir} EXTRA_CFLAGS=-fPIC RTE_KERNELDIR=${WITH_KERNEL_DIR} + BUILD_IN_SOURCE 1 + INSTALL_COMMAND "true") + ExternalProject_Add_Step(dpdk-ext patch-config + COMMAND ${CMAKE_MODULE_PATH}/patch-dpdk-conf.sh ${dpdk_dir} ${machine} + DEPENDEES configure + DEPENDERS build) + # easier to adjust the config + ExternalProject_Add_StepTargets(dpdk-ext configure patch-config build) +endfunction() + +macro(build_dpdk) + set(DPDK_DIR ${CMAKE_BINARY_DIR}/src/dpdk) + do_build_dpdk(${DPDK_DIR}) + set(DPDK_INCLUDE_DIR ${DPDK_DIR}/include) + # create the directory so cmake won't complain when looking at the imported + # target + file(MAKE_DIRECTORY ${DPDK_INCLUDE_DIR}) + foreach(c eal mempool mempool_ring mempool_stack ring) + add_library(dpdk::${c} STATIC IMPORTED) + add_dependencies(dpdk::${c} dpdk-ext) + set(dpdk_${c}_LIBRARY + "${DPDK_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}rte_${c}${CMAKE_STATIC_LIBRARY_SUFFIX}") + set_target_properties(dpdk::${c} PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES ${DPDK_INCLUDE_DIR} + IMPORTED_LOCATION "${dpdk_${c}_LIBRARY}") + list(APPEND DPDK_LIBRARIES dpdk::${c}) + endforeach() +endmacro() diff --git a/cmake/modules/BuildSPDK.cmake b/cmake/modules/BuildSPDK.cmake new file mode 100644 index 00000000000..4209d4826d4 --- /dev/null +++ b/cmake/modules/BuildSPDK.cmake @@ -0,0 +1,33 @@ +macro(build_spdk) + if(NOT TARGET dpdk-ext) + include(BuildDPDK) + build_dpdk() + endif() + find_package(CUnit REQUIRED) + include(ExternalProject) + ExternalProject_Add(spdk-ext + DEPENDS dpdk-ext + SOURCE_DIR ${CMAKE_SOURCE_DIR}/src/spdk + CONFIGURE_COMMAND ./configure --with-dpdk=${DPDK_DIR} + # unset $CFLAGS, otherwise it will interfere with how SPDK sets + # its include directory. + # unset $LDFLAGS, otherwise SPDK will fail to mock some functions. + BUILD_COMMAND env -i PATH=$ENV{PATH} CC=${CMAKE_C_COMPILER} $(MAKE) EXTRA_CFLAGS="-fPIC" + BUILD_IN_SOURCE 1 + INSTALL_COMMAND "true") + ExternalProject_Get_Property(spdk-ext source_dir) + foreach(c nvme log env_dpdk util) + add_library(spdk::${c} STATIC IMPORTED) + add_dependencies(spdk::${c} spdk-ext) + set_target_properties(spdk::${c} PROPERTIES + IMPORTED_LOCATION "${source_dir}/build/lib/${CMAKE_STATIC_LIBRARY_PREFIX}spdk_${c}${CMAKE_STATIC_LIBRARY_SUFFIX}" + INTERFACE_INCLUDE_DIRECTORIES "${source_dir}/include") + list(APPEND SPDK_LIBRARIES spdk::${c}) + endforeach() + list(APPEND iface_libs ${DPDK_LIBRARIES} rt) + set_target_properties(spdk::env_dpdk PROPERTIES + INTERFACE_LINK_LIBRARIES "${iface_libs}") + set(SPDK_INCLUDE_DIR "${source_dir}/include") + unset(source_dir) + unset(iface_libs) +endmacro() diff --git a/cmake/modules/FindCUnit.cmake b/cmake/modules/FindCUnit.cmake new file mode 100644 index 00000000000..26fea552ec9 --- /dev/null +++ b/cmake/modules/FindCUnit.cmake @@ -0,0 +1,23 @@ +# Try to find CUnit +# +# Once done, this will define +# +# CUNIT_FOUND + +find_path(CUNIT_INCLUDE_DIR NAMES CUnit/CUnit.h) + +find_library(CUNIT_LIBRARY NAMES + cunit + libcunit + cunitlib) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(CUnit + DEFAULT_MSG CUNIT_LIBRARY CUNIT_INCLUDE_DIR) + +if(CUNIT_FOUND) + set(CUNIT_LIBRARIES ${CUNIT_LIBRARY}) + set(CUNIT_INCLUDE_DIRS ${CUNIT_INCLUDE_DIR}) +endif() + +mark_as_advanced(CUNIT_INCLUDE_DIR CUNIT_LIBRARY) diff --git a/src/os/CMakeLists.txt b/src/os/CMakeLists.txt index 07442725347..16ac95d0cd7 100644 --- a/src/os/CMakeLists.txt +++ b/src/os/CMakeLists.txt @@ -90,8 +90,9 @@ if(HAVE_LIBZFS) endif() if(WITH_SPDK) + # librt is used by libspdk_env_dpdk target_link_libraries(os - ${SPDK_LIBRARIES} + ${SPDK_LIBRARIES} rt ${DPDK_LIBRARIES}) target_include_directories(os SYSTEM @@ -119,22 +120,10 @@ if(WITH_BLUESTORE) endif() if(WITH_SPDK) - include_directories(SYSTEM "${CMAKE_SOURCE_DIR}/src/spdk/include") - add_custom_target(build_spdk - COMMAND - $(MAKE) DPDK_INC_DIR=${DPDK_INCLUDE_DIR} - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src/spdk/lib - COMMENT "spdk building") - # TODO: should use add_library(spdk INTERFACE IMPORTED) instead in new cmake, - # if INTERFACE is supported. + include(BuildSPDK) + include_directories(SYSTEM ${SPDK_INCLUDE_DIR}) foreach(lib nvme log env_dpdk util) - add_library(spdk_${lib} STATIC IMPORTED) - add_dependencies(spdk_${lib} build_spdk) - target_link_libraries(os PRIVATE spdk_${lib}) - set_target_properties(spdk_${lib} PROPERTIES - IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/src/spdk/build/lib/libspdk_${lib}.a" - INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/src/spdk/include") - list(APPEND SPDK_LIBRARIES spdk_${lib}) + target_link_libraries(os spdk_${lib}) endforeach() endif(WITH_SPDK) -- 2.39.5