diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b08be5941..837a8c0b8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -83,6 +83,11 @@ parameter is added into `spdk_app_opts_init` function. Change the return type of function `spdk_nbd_stop` from void to int. And update the `spdk_nbd_fini` with two parameters to make its behavior from sync to async. +### build + +SPDK now generates pkg-config files to simplify the process of determining which +libraries must be linked into an SPDK application. + ### nvmf nvmf_fc_lld_fini() now takes callback and hence updating FC Broadcom LLD driver diff --git a/Makefile b/Makefile index e1a49bceb4..a50fa94359 100644 --- a/Makefile +++ b/Makefile @@ -91,6 +91,7 @@ clean: $(DIRS-y) $(Q)rm -rf build/fio $(Q)rm -rf build/examples $(Q)rm -rf build/include + $(Q)rm -rf build/lib/pkgconfig $(Q)find build/lib ! -name .gitignore -type f -delete install: all @@ -119,7 +120,7 @@ mk/cc.mk: false build_dir: mk/cc.mk - $(Q)mkdir -p build/lib + $(Q)mkdir -p build/lib/pkgconfig $(Q)mkdir -p build/bin $(Q)mkdir -p build/fio $(Q)mkdir -p build/examples diff --git a/doc/Doxyfile b/doc/Doxyfile index 1b1850a250..69f5a59263 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -833,6 +833,7 @@ INPUT += \ nvmf_tracing.md \ overview.md \ peer_2_peer.md \ + pkgconfig.md \ porting.md \ shfmt.md \ spdkcli.md \ diff --git a/doc/pkgconfig.md b/doc/pkgconfig.md new file mode 100644 index 0000000000..5cde70a173 --- /dev/null +++ b/doc/pkgconfig.md @@ -0,0 +1,55 @@ +# Linking SPDK applications with pkg-config {#pkgconfig} + +The SPDK build system generates pkg-config files to facilitate linking +applications with the correct set of SPDK and DPDK libraries. Using pkg-config +in your build system will ensure you do not need to make modifications +when SPDK adds or modifies library dependencies. + +If your application is using the SPDK nvme library, you would use the following +to get the list of required SPDK libraries: + +~~~ +PKG_CONFIG_PATH=/path/to/spdk/build/lib/pkgconfig pkg-config --libs spdk_nvme +~~~ + +To get the list of required SPDK and DPDK libraries to use the DPDK-based +environment layer: + +~~~ +PKG_CONFIG_PATH=/path/to/spdk/build/lib/pkgconfig pkg-config --libs spdk_env_dpdk +~~~ + +When linking with static libraries, the dependent system libraries must also be +specified. To get the list of required system libraries: + +~~~ +PKG_CONFIG_PATH=/path/to/spdk/build/lib/pkgconfig pkg-config --libs spdk_syslibs +~~~ + +Note that SPDK libraries use constructor functions liberally, so you must surround +the library list with extra linker options to ensure these functions are not dropped +from the resulting application binary. Here is an example Makefile snippet that +shows how to use pkg-config to link an application that uses the SPDK nvme shared +library: + +~~~ +PKG_CONFIG_PATH = $(SPDK_DIR)/build/lib/pkgconfig +SPDK_LIB := $(shell PKG_CONFIG_PATH="$(PKG_CONFIG_PATH)" pkg-config --libs spdk_nvme +DPDK_LIB := $(shell PKG_CONFIG_PATH="$(PKG_CONFIG_PATH)" pkg-config --libs spdk_env_dpdk + +app: + $(CC) -o app app.o -pthread -Wl,--no-as-needed $(SPDK_LIB) $(DPDK_LIB) -Wl,--as-needed +~~~ + +If using the SPDK nvme static library: + +~~~ +PKG_CONFIG_PATH = $(SPDK_DIR)/build/lib/pkgconfig +SPDK_LIB := $(shell PKG_CONFIG_PATH="$(PKG_CONFIG_PATH)" pkg-config --libs spdk_nvme +DPDK_LIB := $(shell PKG_CONFIG_PATH="$(PKG_CONFIG_PATH)" pkg-config --libs spdk_env_dpdk +SYS_LIB := $(shell PKG_CONFIG_PATH="$(PKG_CONFIG_PATH)" pkg-config --libs --static spdk_syslibs + +app: + $(CC) -o app app.o -pthread -Wl,--whole-archive $(SPDK_LIB) $(DPDK_LIB) -Wl,--no-whole-archive \ + $(SYS_LIB) +~~~ diff --git a/doc/user_guides.md b/doc/user_guides.md index e392c81e7b..adf4465e6b 100644 --- a/doc/user_guides.md +++ b/doc/user_guides.md @@ -2,6 +2,7 @@ - @subpage system_configuration - @subpage libraries +- @subpage pkgconfig - @subpage app_overview - @subpage iscsi - @subpage nvmf diff --git a/lib/env_dpdk/Makefile b/lib/env_dpdk/Makefile index 738cb88807..f29182a5ab 100644 --- a/lib/env_dpdk/Makefile +++ b/lib/env_dpdk/Makefile @@ -45,3 +45,12 @@ LIBNAME = env_dpdk SPDK_MAP_FILE = $(abspath $(CURDIR)/spdk_env_dpdk.map) include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk + +LIBDPDK_PKGCONFIG = $(call pkgconfig_filename,spdk_dpdklibs) + +$(LIBDPDK_PKGCONFIG): $(PKGCONFIG) + $(Q)$(SPDK_ROOT_DIR)/scripts/pc_libs.sh \ + "-L$(DPDK_ABS_DIR)/lib $(DPDK_LIB_LIST:%=-l%)" "" DPDK spdk_dpdklibs > $@ + $(Q)echo Requires: spdk_dpdklibs >> $(PKGCONFIG) + +all : $(LIBDPDK_PKGCONFIG) diff --git a/mk/spdk.common.mk b/mk/spdk.common.mk index 5c1f34d8ad..f43f3f6935 100644 --- a/mk/spdk.common.mk +++ b/mk/spdk.common.mk @@ -413,3 +413,7 @@ endef define add_whole_archive -Wl,--whole-archive $(1) -Wl,--no-whole-archive endef + +define pkgconfig_filename +$(SPDK_ROOT_DIR)/build/lib/pkgconfig/$(1).pc +endef diff --git a/mk/spdk.lib.mk b/mk/spdk.lib.mk index aab386cc2f..75af2d9a58 100644 --- a/mk/spdk.lib.mk +++ b/mk/spdk.lib.mk @@ -33,7 +33,7 @@ include $(SPDK_ROOT_DIR)/mk/spdk.common.mk include $(SPDK_ROOT_DIR)/mk/spdk.lib_deps.mk - +include $(SPDK_ROOT_DIR)/mk/spdk.modules.mk ifeq ($(SPDK_MAP_FILE),) $(error SPDK_MAP_FILE is not set for lib $(LIBNAME)) @@ -53,10 +53,12 @@ LIB := $(call spdk_lib_list_to_static_libs,$(LIBNAME)) SHARED_LINKED_LIB := $(LIB:.a=.so) SHARED_REALNAME_LIB := $(SHARED_LINKED_LIB:.so=.so.$(SO_SUFFIX)) +PKGCONFIG = $(call pkgconfig_filename,spdk_$(LIBNAME)) + ifeq ($(CONFIG_SHARED),y) -DEP := $(SHARED_LINKED_LIB) +DEP := $(SHARED_LINKED_LIB) $(PKGCONFIG) else -DEP := $(LIB) +DEP := $(LIB) $(PKGCONFIG) endif ifeq ($(OS),FreeBSD) @@ -80,6 +82,13 @@ ifeq ($(SPDK_NO_LIB_DEPS),) SPDK_DEP_LIBS = $(call spdk_lib_list_to_shared_libs,$(DEPDIRS-$(LIBNAME))) endif +MODULES-bdev = spdk_bdev_modules +MODULES-sock = spdk_sock_modules +MODULES-accel = spdk_accel_modules +ifeq ($(SPDK_ROOT_DIR)/lib/env_dpdk,$(CONFIG_ENV)) +MODULES-event = spdk_env_dpdk_rpc +endif + .PHONY: all clean $(DIRS-y) all: $(BUILD_DEP) @@ -95,6 +104,11 @@ $(SHARED_REALNAME_LIB): $(LIB) $(Q)echo " SO $(notdir $@)"; \ $(call spdk_build_realname_shared_lib,$^,$(SPDK_MAP_FILE),$(LOCAL_SYS_LIBS),$(SPDK_DEP_LIBS)) +$(PKGCONFIG): $(LIB) + $(Q)$(SPDK_ROOT_DIR)/scripts/pc.sh $(SPDK_ROOT_DIR) $(LIBNAME) $(SO_SUFFIX) \ + "$(DEPDIRS-$(LIBNAME):%=spdk_%) $(MODULES-$(LIBNAME))" \ + "" > $@ + $(LIB): $(OBJS) $(LIB_C) diff --git a/module/Makefile b/module/Makefile index 5662634b73..45badef255 100644 --- a/module/Makefile +++ b/module/Makefile @@ -33,6 +33,7 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/..) include $(SPDK_ROOT_DIR)/mk/spdk.common.mk +include $(SPDK_ROOT_DIR)/mk/spdk.modules.mk DIRS-y = bdev blob blobfs accel event sock ifeq ($(SPDK_ROOT_DIR)/lib/env_dpdk,$(CONFIG_ENV)) @@ -49,7 +50,33 @@ DEPDIRS-event := bdev blob .PHONY: all clean $(DIRS-y) -all: $(DIRS-y) +BDEV_MODULES_PKGCONFIG = $(call pkgconfig_filename,spdk_bdev_modules) +ACCEL_MODULES_PKGCONFIG = $(call pkgconfig_filename,spdk_accel_modules) +SOCK_MODULES_PKGCONFIG = $(call pkgconfig_filename,spdk_sock_modules) +SYSLIBS_PKGCONFIG = $(call pkgconfig_filename,spdk_syslibs) + +PRIVATE_SYSLIBS = $(SYS_LIBS) +ifeq ($(SPDK_ROOT_DIR)/lib/env_dpdk,$(CONFIG_ENV)) +PRIVATE_SYSLIBS += $(DPDK_PRIVATE_LINKER_ARGS) +endif + +MODULES_PKGCONFIG = $(BDEV_MODULES_PKGCONFIG) $(ACCEL_MODULES_PKGCONFIG) +MODULES_PKGCONFIG += $(SOCK_MODULES_PKGCONFIG) $(SYSLIBS_PKGCONFIG) + +$(BDEV_MODULES_PKGCONFIG): + $(Q)$(SPDK_ROOT_DIR)/scripts/pc_modules.sh bdev "$(BLOCKDEV_MODULES_LIST:%=spdk_%)" > $@ + +$(ACCEL_MODULES_PKGCONFIG): + $(Q)$(SPDK_ROOT_DIR)/scripts/pc_modules.sh accel "$(ACCEL_MODULES_LIST:%=spdk_%)" > $@ + +$(SOCK_MODULES_PKGCONFIG): + $(Q)$(SPDK_ROOT_DIR)/scripts/pc_modules.sh sock "$(SOCK_MODULES_LIST:%=spdk_%)" > $@ + +$(SYSLIBS_PKGCONFIG): + $(Q)$(SPDK_ROOT_DIR)/scripts/pc_libs.sh "" "$(PRIVATE_SYSLIBS)" System spdk_syslibs > $@ + +all: $(DIRS-y) $(MODULES_PKGCONFIG) + clean: $(DIRS-y) include $(SPDK_ROOT_DIR)/mk/spdk.subdirs.mk diff --git a/scripts/pc.sh b/scripts/pc.sh new file mode 100755 index 0000000000..53bff26d16 --- /dev/null +++ b/scripts/pc.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +cat << EOF +Description: SPDK $2 library +Name: spdk_$2 +Version: $3 +Libs: -L$1/build/lib -lspdk_$2 +Requires: $4 +Libs.private: $5 +Cflags: -I$1/build/include +EOF diff --git a/scripts/pc_libs.sh b/scripts/pc_libs.sh new file mode 100755 index 0000000000..6a0cfb117e --- /dev/null +++ b/scripts/pc_libs.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +cat << EOF +Description: $3 libraries used by SPDK +Name: $4 +Version: 1.0 +Libs: $1 +Libs.private: $2 +EOF diff --git a/scripts/pc_modules.sh b/scripts/pc_modules.sh new file mode 100755 index 0000000000..295ba0fab8 --- /dev/null +++ b/scripts/pc_modules.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +cat << EOF +Description: SPDK $1 modules +Name: spdk_$1_modules +Version: 1.0 +Requires: $2 +EOF diff --git a/test/external_code/hello_world/Makefile b/test/external_code/hello_world/Makefile index a75e0681cf..be17800fd7 100644 --- a/test/external_code/hello_world/Makefile +++ b/test/external_code/hello_world/Makefile @@ -31,9 +31,11 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -DPDK_LIB = -lspdk_env_dpdk -lrte_eal -lrte_mempool -lrte_ring -lrte_mbuf -lrte_mempool_ring -lrte_pci -DPDK_LIB += -lrte_bus_pci -lrte_kvargs -lrte_vhost -lrte_net -lrte_hash -lrte_telemetry -DPDK_LIB += -lrte_cryptodev -lrte_power -lrte_rcu +PKG_CONFIG_PATH = $(SPDK_LIB_DIR)/pkgconfig + +DPDK_LIB := $(shell PKG_CONFIG_PATH="$(PKG_CONFIG_PATH)" pkg-config --libs spdk_env_dpdk) +SPDK_BDEV_LIB := $(shell PKG_CONFIG_PATH="$(PKG_CONFIG_PATH)" pkg-config --libs spdk_event_bdev) +SYS_LIB := $(shell PKG_CONFIG_PATH="$(PKG_CONFIG_PATH)" pkg-config --libs --static spdk_syslibs) # Shows how to compile both an external bdev and an external application against the SPDK combined shared object and dpdk shared objects. bdev_shared_combo: @@ -42,9 +44,9 @@ bdev_shared_combo: # Shows how to compile both an external bdev and an external application against the SPDK individual shared objects and dpdk shared objects. bdev_shared_iso: - $(CC) $(COMMON_CFLAGS) -L../passthru -Wl,-rpath=$(SPDK_LIB_DIR),--no-as-needed -o hello_bdev ./hello_bdev.c \ - -lpassthru_external -lspdk_event_bdev -lspdk_event_accel -lspdk_event_vmd -lspdk_bdev -lspdk_bdev_malloc -lspdk_log -lspdk_thread -lspdk_util -lspdk_event \ - $(DPDK_LIB) -Wl,--no-whole-archive -lnuma + $(CC) $(COMMON_CFLAGS) -L../passthru -Wl,--no-as-needed -o hello_bdev ./hello_bdev.c \ + -lpassthru_external $(SPDK_BDEV_LIB) \ + $(DPDK_LIB) # Shows how to compile an external application against the SPDK combined shared object and dpdk shared objects. alone_shared_combo: @@ -52,19 +54,15 @@ alone_shared_combo: # Shows how to compile an external application against the SPDK individual shared objects and dpdk shared objects. alone_shared_iso: - $(CC) $(COMMON_CFLAGS) -Wl,-rpath=$(SPDK_LIB_DIR),--no-as-needed -o hello_bdev ./hello_bdev.c -lspdk_event_bdev \ - -lspdk_event_accel -lspdk_event_vmd -lspdk_bdev -lspdk_bdev_malloc -lspdk_log -lspdk_thread -lspdk_util -lspdk_event $(DPDK_LIB) + $(CC) $(COMMON_CFLAGS) -Wl,-rpath=$(SPDK_LIB_DIR),--no-as-needed -o hello_bdev ./hello_bdev.c \ + $(SPDK_BDEV_LIB) $(DPDK_LIB) # Shows how to compile an external application against the SPDK archives. alone_static: - $(CC) $(COMMON_CFLAGS) -o hello_bdev ./hello_bdev.c -pthread -Wl,--whole-archive,-Bstatic -lspdk_bdev_malloc -lspdk_event_bdev -lspdk_event_accel -lspdk_event_vmd \ - -lspdk_event_sock -lspdk_bdev -lspdk_accel -lspdk_event -lspdk_thread -lspdk_util -lspdk_conf -lspdk_trace -lspdk_log -lspdk_json \ - -lspdk_jsonrpc -lspdk_rpc -lspdk_sock -lspdk_notify -lspdk_vmd \ - $(DPDK_LIB) -Wl,--no-whole-archive,-Bdynamic -lnuma -luuid -ldl -lrt + $(CC) $(COMMON_CFLAGS) -o hello_bdev ./hello_bdev.c -pthread -Wl,--whole-archive,-Bstatic $(SPDK_BDEV_LIB) \ + $(DPDK_LIB) -Wl,--no-whole-archive,-Bdynamic $(SYS_LIB) # Shows how to compile and external bdev and application sgainst the SPDK archives. bdev_static: - $(CC) $(COMMON_CFLAGS) -L../passthru -o hello_bdev ./hello_bdev.c -pthread -Wl,--whole-archive,-Bstatic -lpassthru_external -lspdk_bdev_malloc -lspdk_event_bdev \ - -lspdk_event_accel -lspdk_event_vmd -lspdk_event_sock -lspdk_bdev -lspdk_accel -lspdk_event -lspdk_thread -lspdk_util -lspdk_conf -lspdk_trace \ - -lspdk_log -lspdk_json -lspdk_jsonrpc -lspdk_rpc -lspdk_sock -lspdk_notify -lspdk_vmd $(DPDK_LIB) \ - -Wl,--no-whole-archive,-Bdynamic -lnuma -luuid -ldl -lrt + $(CC) $(COMMON_CFLAGS) -L../passthru -o hello_bdev ./hello_bdev.c -pthread -Wl,--whole-archive,-Bstatic -lpassthru_external $(SPDK_BDEV_LIB) $(DPDK_LIB) \ + -Wl,--no-whole-archive,-Bdynamic $(SYS_LIB)