dnl CF_WITH_VERSIONED_SYMS version: 14 updated: 2024/08/03 12:34:02
dnl ----------------------
dnl Use this when building shared library with ELF, to markup symbols with the
dnl version identifier from the given input file.  Generally that identifier is
dnl the same as the SONAME at which the symbol was first introduced.
dnl
dnl $1 = basename of the ".map" file (default $PACKAGE)
AC_DEFUN([CF_WITH_VERSIONED_SYMS],
[AC_REQUIRE([AC_PROG_FGREP])dnl
AC_REQUIRE([AC_PROG_EGREP])dnl
AC_REQUIRE([CF_GLOB_FULLPATH])dnl

AC_MSG_CHECKING(if versioned-symbols file should be used)
AC_ARG_WITH(versioned-syms,
	[[  --with-versioned-syms[=MAP-FILE] version ELF shared library symbols per MAP-FILE]],
	[with_versioned_syms=$withval],
	[with_versioned_syms=no])
case "x$with_versioned_syms" in
(xyes)
	with_versioned_syms='${top_srcdir}/package/ifelse($1,,${PACKAGE},[$1]).map'
	AC_SUBST(PACKAGE)
	;;
(xno)
	;;
(x$GLOB_FULLPATH_POSIX|x$GLOB_FULLPATH_OTHER)
	test -f "$with_versioned_syms" || AC_MSG_ERROR(expected a filename: $with_versioned_syms)
	;;
(*)
	test -f "$with_versioned_syms" || AC_MSG_ERROR(expected a filename: $with_versioned_syms)
	with_versioned_syms=`pwd`/"$with_versioned_syms"
	;;
esac
AC_MSG_RESULT($with_versioned_syms)

RESULTING_SYMS=
VERSIONED_SYMS=
WILDCARD_SYMS=

if test "x$with_versioned_syms" != xno
then
	RESULTING_SYMS=$with_versioned_syms
	case "x$MK_SHARED_LIB" in
	(*-Wl,*)
		VERSIONED_SYMS="-Wl,--version-script,\${RESULTING_SYMS}"
		MK_SHARED_LIB=`echo "$MK_SHARED_LIB" | sed -e "s%-Wl,%\\[$]{VERSIONED_SYMS} -Wl,%"`
		CF_VERBOSE(MK_SHARED_LIB:  $MK_SHARED_LIB)
		;;
	(*-dy\ *)
		VERSIONED_SYMS="-Wl,-M,\${RESULTING_SYMS}"
		MK_SHARED_LIB=`echo "$MK_SHARED_LIB" | sed -e "s%-dy%\\[$]{VERSIONED_SYMS} -dy%"`
		CF_VERBOSE(MK_SHARED_LIB:  $MK_SHARED_LIB)
		;;
	(*)
		AC_MSG_WARN(this system does not support versioned-symbols)
		;;
	esac

	# Linux ld can selectively override scope, e.g., of symbols beginning with
	# "_" by first declaring some as global, and then using a wildcard to
	# declare the others as local.  Some other loaders cannot do this.  Check
	# by constructing a (very) simple shared library and inspecting its
	# symbols.
	if test "x$VERSIONED_SYMS" != "x"
	then
		AC_MSG_CHECKING(if wildcards can be used to selectively omit symbols)
		WILDCARD_SYMS=no

		# make sources
		rm -f conftest.*

		cat >conftest.ver <<EOF
module_1.0 {
global:
	globalf1;
local:
	localf1;
};
module_2.0 {
global:
	globalf2;
local:
	localf2;
	_*;
} module_1.0;
submodule_1.0 {
global:
	subglobalf1;
	_ismissing;
local:
	sublocalf1;
};
submodule_2.0 {
global:
	subglobalf2;
local:
	sublocalf2;
	_*;
} submodule_1.0;
EOF
		cat >conftest.$ac_ext <<EOF
#line __oline__ "configure"
extern int _ismissing(void);    int _ismissing(void)  { return 1; }
extern int _localf1(void);      int _localf1(void)    { return 1; }
extern int _localf2(void);      int _localf2(void)    { return 2; }
extern int globalf1(void);      int globalf1(void)    { return 1; }
extern int globalf2(void);      int globalf2(void)    { return 2; }
extern int _sublocalf1(void);   int _sublocalf1(void) { return 1; }
extern int _sublocalf2(void);   int _sublocalf2(void) { return 2; }
extern int subglobalf1(void);   int subglobalf1(void) { return 1; }
extern int subglobalf2(void);   int subglobalf2(void) { return 2; }
EOF
		cat >conftest.mk <<EOF
CC=${CC}
CFLAGS=${CFLAGS}
CPPFLAGS=${CPPFLAGS}
LDFLAGS=${LDFLAGS}
LIBS=${LIBS}
VERSIONED_SYMS=${VERSIONED_SYMS}
RESULTING_SYMS=conftest.ver
MK_SHARED_LIB=${MK_SHARED_LIB}
conftest.so: conftest.$ac_cv_objext
		\$(MK_SHARED_LIB) conftest.$ac_cv_objext
EOF

		# compile source, make library
		if make -f conftest.mk 2>&AC_FD_CC >/dev/null
		then
			# test for missing symbol in either Data or Text section
			cf_missing="`nm -P conftest.so 2>&AC_FD_CC |${FGREP-fgrep} _ismissing | ${EGREP-egrep} '[[ 	]][[DT]][[ 	]]'`"
			test -n "$cf_missing" && WILDCARD_SYMS=yes
		fi
		AC_MSG_RESULT($WILDCARD_SYMS)
		rm -f conftest.*
	fi
fi
AC_SUBST(RESULTING_SYMS)
AC_SUBST(VERSIONED_SYMS)
AC_SUBST(WILDCARD_SYMS)
])dnl
