Skip to content

tst_udf_self_load fails on static-only builds (--disable-shared) #3287

@edhartnett

Description

@edhartnett

Bug: tst_udf_self_load fails on static-only builds (--disable-shared)

Summary

tst_udf_self_load fails on any build configured with --disable-shared because
the test calls dlopen() on a shared library plugin (.so) that is never built
in a static-only configuration. The test was unconditionally included in the test
suite regardless of whether shared library support was enabled.

Observed failure

On the big-endian CI job (s390x, built with --disable-shared --enable-static):

ERR: dlopen failed for /home/runner/work/netcdf-c/netcdf-c/nc_test4/.libs/tst_udf_self_load_plugin.so: \
  /home/runner/work/netcdf-c/netcdf-c/nc_test4/.libs/tst_udf_self_load_plugin.so: \
  cannot open shared object file: No such file or directory

*** Testing UDF self-registration plugin loading.
*** testing plugin loader with NC_Dispatch*-returning init...Sorry! Unexpected result, tst_udf_self_load.c, line: 68
FAIL tst_udf_self_load (exit status: 2)

The .so file does not exist because libtool does not build shared modules when
--disable-shared is passed to configure.

Root cause

In nc_test4/Makefile.am, tst_udf_self_load was listed unconditionally in
NC4_TESTS:

tst_put_vars tst_elatefill tst_udf tst_put_vars_two_unlim_dim \
tst_bug1442 tst_quantize tst_h_transient_types tst_udf_self_load

The associated plugin (tst_udf_self_load_plugin.la) was also built
unconditionally via check_LTLIBRARIES. When --disable-shared is in effect,
libtool builds only a static archive for check_LTLIBRARIES targets and does
not install a .so into .libs/. The test binary is compiled and linked, but
at runtime dlopen() cannot find the plugin file, causing an immediate failure.

Proposed fix

Add an AM_CONDITIONAL for enable_shared in configure.ac:

AM_CONDITIONAL(ENABLE_SHARED, [test "x$enable_shared" = xyes])

Then guard the test and its plugin in nc_test4/Makefile.am under that
conditional:

# UDF self-registration plugin loading test.
# Requires a shared library build: the test dlopen()s a .so plugin.
# Skip entirely when built with --disable-shared.
if ENABLE_SHARED
NC4_TESTS += tst_udf_self_load
check_LTLIBRARIES = tst_udf_self_load_plugin.la
tst_udf_self_load_plugin_la_SOURCES = tst_udf_self_load_plugin.c
tst_udf_self_load_plugin_la_LDFLAGS = -module -avoid-version -shared -no-undefined -rpath /tmp
tst_udf_self_load_plugin_la_LIBADD = ${top_builddir}/liblib/libnetcdf.la
tst_udf_self_load_CPPFLAGS = $(AM_CPPFLAGS) -DTEST_PLUGIN_PATH=\"$(abs_builddir)/.libs/tst_udf_self_load_plugin@MODULE_EXT@\"
endif # ENABLE_SHARED

This ensures the test and plugin are only built and run when shared libraries
are enabled, which is the only configuration where dlopen() can succeed.

Affected files

  • configure.ac — add AM_CONDITIONAL(ENABLE_SHARED, ...)
  • nc_test4/Makefile.am — guard tst_udf_self_load and its plugin under if ENABLE_SHARED

Reproducer

Configure netCDF-C with shared libraries disabled and run the nc_test4 suite:

./configure --enable-hdf5 --disable-shared --enable-static
make check -C nc_test4 TESTS=tst_udf_self_load

The test can also be reproduced under QEMU emulation using the CI workflow
.github/workflows/run_tests_bigendian.yml, which passes --disable-shared.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions