Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 140 additions & 1 deletion buildlib/tools/builds.sh
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,144 @@ check_no_gda() {
fi
}

check_elf_soname() {
lib_path=$1
soname=$2

if [ ! -f "$lib_path" ]; then
azure_log_error "Missing library $lib_path"
exit 1
fi

if ! readelf -d "$lib_path" | grep -q "Library soname: \\[$soname\\]"; then
azure_log_error "Library $lib_path does not have SONAME $soname"
exit 1
fi
}

check_elf_needed() {
binary_path=$1
needed=$2

if [ ! -f "$binary_path" ]; then
azure_log_error "Missing binary $binary_path"
exit 1
fi

if ! readelf -d "$binary_path" | grep -q "Shared library: \\[$needed\\]"; then
azure_log_error "Binary $binary_path is not linked to $needed"
exit 1
fi
}

check_linker_symlink() {
link_path=$1
target_pattern=$2

if [ ! -L "$link_path" ]; then
azure_log_error "Missing linker symlink $link_path"
exit 1
fi

if ! readlink "$link_path" | grep -q "$target_pattern"; then
azure_log_error "Linker symlink $link_path does not point to $target_pattern"
exit 1
fi
}

build_soname_suffix() {
suffix=ci
foreign_build_dir=${ucx_build_dir}/foreign
foreign_inst=${ucx_build_dir}/foreign-install

echo "==== Build foreign UCX without SONAME suffix ===="
mkdir -p $foreign_build_dir
pushd $foreign_build_dir
${WORKSPACE}/contrib/configure-release --prefix=$foreign_inst \
--without-java \
--without-go \
--without-verbs \
--without-rdmacm \
--without-cuda \
--without-rocm \
--without-xpmem \
--without-knem \
--disable-doxygen-doc
$MAKEP
$MAKEP install
popd

echo "==== Build with SONAME suffix and module deepbind ===="
${WORKSPACE}/contrib/configure-release --prefix=$ucx_inst \
--enable-gtest \
--enable-test-apps \
--with-soname-suffix=$suffix \
--enable-module-deepbind \
--without-java \
--without-go \
--without-verbs \
--without-rdmacm \
--without-cuda \
--without-rocm \
--without-xpmem \
--without-knem \
--disable-doxygen-doc
$MAKEP
$MAKEP install

grep "#define UCX_MODULE_FILE_SUFFIX \"-$suffix\"" config.h
grep "#define UCX_MODULE_DLOPEN_DEEPBIND 1" config.h

for lib in ucm ucs uct ucp; do
check_elf_soname \
"${ucx_inst}/lib/lib${lib}-${suffix}.so.0.0.0" \
"lib${lib}-${suffix}.so.0"
check_linker_symlink \
"${ucx_inst}/lib/lib${lib}.so" \
"lib${lib}-${suffix}\\.so"
done

check_elf_soname \
"${ucx_inst}/lib/ucx/libuct_cma-${suffix}.so.0.0.0" \
"libuct_cma-${suffix}.so.0"
check_elf_needed \
"${ucx_inst}/lib/ucx/libuct_cma-${suffix}.so.0.0.0" \
"libuct-${suffix}.so.0"
check_elf_needed \
"${ucx_inst}/lib/ucx/libuct_cma-${suffix}.so.0.0.0" \
"libucs-${suffix}.so.0"
check_elf_soname \
"${ucx_build_dir}/test/gtest/ucs/test_module/.libs/libtest_module-${suffix}.so.0.0.0" \
"libtest_module-${suffix}.so.0"
check_elf_needed \
"${ucx_inst}/lib/libucp-${suffix}.so.0.0.0" \
"libuct-${suffix}.so.0"
check_elf_needed \
"${ucx_inst}/lib/libucp-${suffix}.so.0.0.0" \
"libucs-${suffix}.so.0"
check_elf_needed \
"${ucx_inst}/bin/ucx_info" \
"libucp-${suffix}.so.0"
check_elf_needed \
"${ucx_inst}/bin/ucx_info" \
"libuct-${suffix}.so.0"
check_elf_needed \
"${ucx_inst}/bin/ucx_info" \
"libucs-${suffix}.so.0"
check_elf_needed \
"${ucx_build_dir}/test/apps/.libs/libtest_ucx_isolation_plugin.so" \
"libucp-${suffix}.so.0"

LD_LIBRARY_PATH="${ucx_inst}/lib:${foreign_inst}/lib${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}" \
"${ucx_build_dir}/test/apps/test_ucx_dlopen_isolation" \
"${foreign_inst}/lib/libucp.so.0.0.0" \
"${ucx_build_dir}/test/apps/.libs/libtest_ucx_isolation_plugin.so" \
"$suffix" deepbind

GTEST_FILTER=test_sys.module_file_suffix:test_sys.module \
$MAKE -C test/gtest test
}

az_init_modules
prepare_build

Expand Down Expand Up @@ -522,7 +660,8 @@ long)
'build_no_openmp' \
'build_gcc_debug_opt_with_dndebug' \
'build_clang' \
'build_armclang')
'build_armclang'\
'build_soname_suffix')
;;
compilers)
tests=('build_icc' 'build_pgi')
Expand Down
44 changes: 44 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,40 @@ AC_SUBST(EXTRA_VERSION)
AC_SUBST(SCM_VERSION)
AC_SUBST(SOVERSION)

UCX_LT_RELEASE=
ucx_soname_suffix_summary="<disabled>"
ucx_module_deepbind_summary="no"
AC_ARG_WITH([soname-suffix],
AS_HELP_STRING([--with-soname-suffix=SUFFIX],
[Append SUFFIX to UCX installed shared library names and SONAMEs. Disabled by default. [default=NO]]),
[], [with_soname_suffix=no])
AS_IF([test "x$with_soname_suffix" != xno],
[AS_IF([test "x$with_soname_suffix" = xyes],
[AC_MSG_ERROR([--with-soname-suffix requires an explicit suffix value])])
case "$with_soname_suffix" in
@<:@A-Za-z0-9@:>@*) ;;
*) AC_MSG_ERROR([--with-soname-suffix must start with a letter or digit]) ;;
esac
case "$with_soname_suffix" in
*@<:@!A-Za-z0-9_-@:>@*)
AC_MSG_ERROR([--with-soname-suffix must contain only letters, digits, underscores, and dashes])
;;
esac
UCX_LT_RELEASE="-release $with_soname_suffix"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 BLOCKER

libtool's -release changes the installed library filename (e.g. libucp-SUFFIX.so.0), not just the SONAME. With this set, ucx.pc (which emits -lucp) and cmake/ucx-targets.cmake.in (which hardcodes libucp.so/libucs.so/libuct.so) will fail to locate the libs for downstream consumers. Either also template these files with the suffix, or use a mechanism that only alters the SONAME (e.g., -Wl,-soname=...) if the intent really is SONAME-only as the option name suggests.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ INFO

only the four core libs (ucm/ucp/ucs/uct) get $(UCX_LT_RELEASE); the per-transport module libs (e.g. src/uct/ib/Makefile.am, src/ucm/cuda/Makefile.am, …) still use plain -version-info $(SOVERSION). is the asymmetry intentional? if two UCX trees with different suffixes are installed in the same prefix, the modules will collide.

AC_DEFINE_UNQUOTED([UCX_MODULE_FILE_SUFFIX],
["-$with_soname_suffix"],
[Suffix appended to private UCX module file names])
ucx_soname_suffix_summary="$with_soname_suffix"])
AC_SUBST([UCX_LT_RELEASE])

AC_ARG_ENABLE([module-deepbind],
AS_HELP_STRING([--enable-module-deepbind],
[Load UCX modules with RTLD_DEEPBIND. Intended for private UCX bundles. Disabled by default. [default=NO]]),
[], [enable_module_deepbind=no])
AS_IF([test "x$enable_module_deepbind" = xyes],
[AS_IF([test "x$with_soname_suffix" = xno],
[AC_MSG_ERROR([--enable-module-deepbind requires --with-soname-suffix])])])

AC_PROG_CC
AC_PROG_CXX
AC_OPENMP
Expand All @@ -87,6 +121,14 @@ AC_FUNC_STRERROR_R

AC_PATH_TOOL([PKG_CONFIG], [pkg-config], [pkg-config])

AS_IF([test "x$enable_module_deepbind" = xyes],
[AC_CHECK_DECLS([RTLD_DEEPBIND],
[AC_DEFINE([UCX_MODULE_DLOPEN_DEEPBIND], [1],
[Load UCX modules with RTLD_DEEPBIND])
ucx_module_deepbind_summary="yes"],
[AC_MSG_ERROR([--enable-module-deepbind requires RTLD_DEEPBIND support from <dlfcn.h>])],
[[#include <dlfcn.h>]])])
Comment thread
roiedanino marked this conversation as resolved.


#
# Define SHARED_LIB preprocessor macro when building a shared library
Expand Down Expand Up @@ -434,6 +476,8 @@ AC_MSG_NOTICE([ Multi-thread: ${mt_enable}])
AC_MSG_NOTICE([ MPI tests: ${mpi_enable}])
AC_MSG_NOTICE([ VFS support: ${vfs_enable}])
AC_MSG_NOTICE([ Devel headers: ${enable_devel_headers}])
AC_MSG_NOTICE([ SONAME suffix: ${ucx_soname_suffix_summary}])
AC_MSG_NOTICE([ Module deepbind: ${ucx_module_deepbind_summary}])
AC_MSG_NOTICE([io_demo CUDA support: ${with_iodemo_cuda}])
AC_MSG_NOTICE([ Bindings: <$(echo ${build_bindings}|tr ':' ' ') >])
AC_MSG_NOTICE([ UCS modules: <$(echo ${ucs_modules}|tr ':' ' ') >])
Expand Down
3 changes: 2 additions & 1 deletion src/tools/perf/cuda/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ if HAVE_CUDA
module_LTLIBRARIES = libucx_perftest_cuda.la
libucx_perftest_cuda_la_CPPFLAGS = $(BASE_CPPFLAGS) $(CUDA_CPPFLAGS)
libucx_perftest_cuda_la_CFLAGS = $(BASE_CFLAGS) $(CUDA_CFLAGS) $(LT_CFLAGS)
libucx_perftest_cuda_la_LDFLAGS = $(CUDA_LDFLAGS) -version-info $(SOVERSION)
libucx_perftest_cuda_la_LDFLAGS = $(CUDA_LDFLAGS) -version-info $(SOVERSION) \
$(UCX_LT_RELEASE)
libucx_perftest_cuda_la_LIBADD = $(CUDART_LIBS)
libucx_perftest_cuda_la_SOURCES = cuda_alloc.c

Expand Down
3 changes: 2 additions & 1 deletion src/tools/perf/mad/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ module_LTLIBRARIES = libucx_perftest_mad.la
libucx_perftest_mad_la_CPPFLAGS = $(BASE_CPPFLAGS)
libucx_perftest_mad_la_CFLAGS = $(BASE_CFLAGS) $(MAD_CFLAGS) \
$(OPENMP_CFLAGS) $(LT_CFLAGS)
libucx_perftest_mad_la_LDFLAGS = $(MAD_LDFLAGS) -version-info $(SOVERSION)
libucx_perftest_mad_la_LDFLAGS = $(MAD_LDFLAGS) -version-info $(SOVERSION) \
$(UCX_LT_RELEASE)
libucx_perftest_mad_la_LIBADD = $(MAD_LIBS)
libucx_perftest_mad_la_SOURCES = perftest_mad.c

Expand Down
1 change: 1 addition & 0 deletions src/tools/perf/rocm/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ libucx_perftest_rocm_la_CPPFLAGS = $(BASE_CPPFLAGS) $(HIP_CPPFLAGS)
libucx_perftest_rocm_la_CFLAGS = $(BASE_CFLAGS) $(HIP_CFLAGS) \
$(LT_CFLAGS)
libucx_perftest_rocm_la_LDFLAGS = $(HIP_LDFLAGS) $(HIP_LIBS) -version-info $(SOVERSION) \
$(UCX_LT_RELEASE) \
$(patsubst %, -Xlinker %, -L$(ROCM_ROOT)/lib -rpath $(ROCM_ROOT)/hip/lib -rpath $(ROCM_ROOT)/lib) \
$(patsubst %, -Xlinker %, --enable-new-dtags) \
$(patsubst %, -Xlinker %, -rpath $(ROCM_ROOT)/lib64)
Expand Down
3 changes: 2 additions & 1 deletion src/tools/perf/ze/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ module_LTLIBRARIES = libucx_perftest_ze.la
libucx_perftest_ze_la_CPPFLAGS = $(BASE_CPPFLAGS) $(ZE_CPPFLAGS)
libucx_perftest_ze_la_CFLAGS = $(BASE_CFLAGS) $(ZE_CFLAGS) \
$(LT_CFLAGS)
libucx_perftest_ze_la_LDFLAGS = $(ZE_LDFLAGS) $(ZE_LIBS) -version-info $(SOVERSION)
libucx_perftest_ze_la_LDFLAGS = $(ZE_LDFLAGS) $(ZE_LIBS) \
-version-info $(SOVERSION) $(UCX_LT_RELEASE)
libucx_perftest_ze_la_SOURCES = ze_alloc.c

include $(top_srcdir)/config/module.am
Expand Down
2 changes: 1 addition & 1 deletion src/ucm/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ SUBDIRS = . cuda rocm ze
lib_LTLIBRARIES = libucm.la
libucm_ladir = $(includedir)/ucm
libucm_la_LDFLAGS = $(UCM_MODULE_LDFLAGS) \
-ldl -version-info $(SOVERSION)
-ldl -version-info $(SOVERSION) $(UCX_LT_RELEASE)
libucm_la_CPPFLAGS = $(BASE_CPPFLAGS) -DUCM_MALLOC_PREFIX=ucm_dl
libucm_la_CFLAGS = $(BASE_CFLAGS) $(CFLAGS_NO_DEPRECATED) \
$(LT_CFLAGS)
Expand Down
2 changes: 1 addition & 1 deletion src/ucm/cuda/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ libucm_cuda_la_CFLAGS = $(BASE_CFLAGS) $(CUDA_CFLAGS) $(LT_CFLAGS)
libucm_cuda_la_LIBADD = ../libucm.la $(CUDA_LIBS) $(CUDART_LIBS)
libucm_cuda_la_LDFLAGS = $(UCM_MODULE_LDFLAGS) \
$(patsubst %, -Xlinker %, $(CUDA_LDFLAGS)) \
-version-info $(SOVERSION)
-version-info $(SOVERSION) $(UCX_LT_RELEASE)

noinst_HEADERS = \
cudamem.h
Expand Down
1 change: 1 addition & 0 deletions src/ucm/rocm/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ libucm_rocm_la_CFLAGS = $(BASE_CFLAGS) $(ROCM_CFLAGS) $(LT_CFLAGS)
libucm_rocm_la_LIBADD = ../libucm.la
libucm_rocm_la_LDFLAGS = $(UCM_MODULE_LDFLAGS) \
$(ROCM_LDFLAGS) $(ROCM_LIBS) -version-info $(SOVERSION) \
$(UCX_LT_RELEASE) \
$(patsubst %, -Xlinker %, -L$(ROCM_ROOT)/lib -rpath $(ROCM_ROOT)/hip/lib -rpath $(ROCM_ROOT)/lib) \
$(patsubst %, -Xlinker %, --enable-new-dtags) \
$(patsubst %, -Xlinker %, -rpath $(ROCM_ROOT)/lib64)
Expand Down
2 changes: 1 addition & 1 deletion src/ucm/ze/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ libucm_ze_la_CFLAGS = $(BASE_CFLAGS) $(ZE_CFLAGS) $(LT_CFLAGS)
libucm_ze_la_LIBADD = ../libucm.la $(ZE_LIBS)
libucm_ze_la_LDFLAGS = $(UCM_MODULE_LDFLAGS) \
$(patsubst %, -Xlinker %, $(ZE_LDFLAGS)) \
-version-info $(SOVERSION)
-version-info $(SOVERSION) $(UCX_LT_RELEASE)

noinst_HEADERS = \
zemem.h
Expand Down
2 changes: 1 addition & 1 deletion src/ucp/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ lib_LTLIBRARIES = libucp.la
libucp_la_CFLAGS = $(BASE_CFLAGS) $(LT_CFLAGS)
libucp_la_LIBS =
libucp_la_CPPFLAGS = $(BASE_CPPFLAGS)
libucp_la_LDFLAGS = -ldl -version-info $(SOVERSION)
libucp_la_LDFLAGS = -ldl -version-info $(SOVERSION) $(UCX_LT_RELEASE)
libucp_la_LIBADD = ../ucs/libucs.la ../uct/libuct.la
libucp_ladir = $(includedir)/ucp

Expand Down
3 changes: 2 additions & 1 deletion src/ucs/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ libucs_la_CPPFLAGS = $(BASE_CPPFLAGS) $(BFD_CPPFLAGS) \
-DUCX_MODULE_DIR=\"$(moduledir)\" \
-DUCX_CONFIG_DIR=\"$(ucx_config_dir)\"
libucs_la_CFLAGS = $(BASE_CFLAGS) $(LT_CFLAGS)
libucs_la_LDFLAGS = -ldl $(BFD_LDFLAGS) -version-info $(SOVERSION)
libucs_la_LDFLAGS = -ldl $(BFD_LDFLAGS) -version-info $(SOVERSION) $(UCX_LT_RELEASE)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] [important] libucs_signal is left unsuffixed

The new suffix is applied to libucm/libucs/libuct/libucp, but libucs_signal is also an installed versioned UCX shared library. If the goal is avoiding collisions with already-loaded UCX DSOs, leaving this SONAME as libucs_signal.so.0 keeps one UCX entry point outside the suffix scheme. Add $(UCX_LT_RELEASE) here as well, or explicitly document that this option is limited to the four core libraries.

libucs_ladir = $(includedir)/ucs
libucs_la_LIBADD = $(LIBM) $(top_builddir)/src/ucm/libucm.la $(BFD_LIBS)

Expand Down Expand Up @@ -130,6 +130,7 @@ noinst_HEADERS = \
sys/compiler.h \
sys/lib.h \
sys/module.h \
sys/module_int.h \
sys/sys.h \
sys/iovec.h \
sys/iovec.inl \
Expand Down
2 changes: 1 addition & 1 deletion src/ucs/signal/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ lib_LTLIBRARIES = libucs_signal.la

libucs_signal_la_CPPFLAGS = $(BASE_CPPFLAGS)
libucs_signal_la_CFLAGS = $(BASE_CFLAGS) $(LT_CFLAGS)
libucs_signal_la_LDFLAGS = -version-info $(SOVERSION)
libucs_signal_la_LDFLAGS = -version-info $(SOVERSION) $(UCX_LT_RELEASE)
libucs_signal_la_LIBADD = $(top_builddir)/src/ucs/libucs.la
libucs_signal_la_SOURCES = signal.c
5 changes: 5 additions & 0 deletions src/ucs/sys/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#endif

#include "module.h"
#include "module_int.h"

#include <ucs/sys/preprocessor.h>
#include <ucs/datastruct/string_buffer.h>
Expand Down Expand Up @@ -245,6 +246,9 @@ static int ucs_module_flags_to_dlopen_mode(unsigned flags)
} else {
mode |= RTLD_LOCAL;
}
#if defined(UCX_MODULE_DLOPEN_DEEPBIND) && defined(RTLD_DEEPBIND)
mode |= RTLD_DEEPBIND;
#endif

return mode;
}
Expand Down Expand Up @@ -324,6 +328,7 @@ static void ucs_module_load_from_dir(const char *dir, const char *framework,
}

ucs_module_filename_to_base(entry->d_name, base, sizeof(base));
ucs_module_normalize_base(base);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ MINOR

ucs_module_normalize_base will also strip the configured suffix from any unrelated module name that happens to end with it (e.g. a third-party libuct_foo-ci.so not built with --with-soname-suffix=ci). Worth scoping on the -<suffix> separator anchored to the framework prefix, or at least a comment that such collisions are accepted.

if (strchr(base + prefix_len, '_') != NULL) {
ucs_module_debug("module name contains '_': %s, skipping", base + prefix_len);
continue;
Expand Down
32 changes: 32 additions & 0 deletions src/ucs/sys/module_int.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Copyright (c) NVIDIA CORPORATION & AFFILIATES, 2026. ALL RIGHTS RESERVED.
*
* See file LICENSE for terms.
*/

#ifndef UCS_MODULE_INT_H_
#define UCS_MODULE_INT_H_

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <string.h>


static inline void ucs_module_normalize_base(char *base)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ INFO

minor: a dedicated header for a single 8-line static inline helper feels heavy. It exists only so test_sys.cc can reach the function — could keep the helper static in module.c and expose a test hook, or declare it non-inline in module.h.

{
#ifdef UCX_MODULE_FILE_SUFFIX
size_t suffix_len = strlen(UCX_MODULE_FILE_SUFFIX);
size_t base_len = strlen(base);

/* Expected input after stripping .so is lib<framework>_<module>-<suffix>. */
if ((base_len > suffix_len) &&
!strcmp(base + base_len - suffix_len, UCX_MODULE_FILE_SUFFIX)) {
base[base_len - suffix_len] = '\0';
}
#endif
}


#endif
3 changes: 2 additions & 1 deletion src/ucs/vfs/fuse/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ libucs_fuse_la_CFLAGS = $(BASE_CFLAGS) $(LT_CFLAGS)
libucs_fuse_la_LIBADD = $(FUSE3_LIBS) \
$(top_builddir)/src/ucs/vfs/sock/libucs_vfs_sock.la \
$(top_builddir)/src/ucs/libucs.la
libucs_fuse_la_LDFLAGS = $(FUSE3_LDFLAGS) -version-info $(SOVERSION)
libucs_fuse_la_LDFLAGS = $(FUSE3_LDFLAGS) -version-info $(SOVERSION) \
$(UCX_LT_RELEASE)
libucs_fuse_la_SOURCES = vfs_fuse.c

PKG_CONFIG_NAME=fuse
Expand Down
Loading