# versioning_script.at -- test the libtool versioning script: libtool-next-version -*- Autotest -*- # # Copyright (C) 2025-2026 Free Software Foundation, Inc. # # This file is part of GNU Libtool. # # GNU Libtool is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # # GNU Libtool is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool. If not, see . #### #### AT_SETUP([Test libtool-next-version script]) AT_KEYWORDS([libtool]) # Testing the script. Let's create an old library and a new library. eval `$LIBTOOL --config | $EGREP '^(libname_spec|libext)='` mkdir -p libexample/src mkdir -p new_libexample/src mkdir libexample/m4 mkdir new_libexample/m4 touch libexample/src/Makefile.am new_libexample/src/Makefile.am AT_DATA([libexample/Makefile.am], [[ # Makefile.am ACLOCAL_AMFLAGS = -I m4 SUBDIRS = src # Enable subdir-objects option AM_CFLAGS = -I$(srcdir)/src # Enable subdir-objects AUTOMAKE_OPTIONS = subdir-objects lib_LTLIBRARIES = libexample.la libexample_la_SOURCES = src/example.c src/example.h ]]) AT_DATA([new_libexample/Makefile.am], [[ # Makefile.am ACLOCAL_AMFLAGS = -I m4 SUBDIRS = src # Enable subdir-objects option AM_CFLAGS = -I$(srcdir)/src # Enable subdir-objects AUTOMAKE_OPTIONS = subdir-objects lib_LTLIBRARIES = libexample.la libexample_la_SOURCES = src/example.c src/example.h ]]) AT_DATA([libexample/configure.ac], [[ # configure.ac AC_INIT([libexample], [1.0]) AM_INIT_AUTOMAKE([-Wall -Werror foreign]) # Add the macro directory AC_CONFIG_MACRO_DIRS([m4]) # Initialize the archiver AM_PROG_AR AC_PROG_CC # Set Libtool versioning LT_INIT AC_CONFIG_SRCDIR([src/example.c]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_FILES([Makefile src/Makefile]) AC_OUTPUT ]]) AT_DATA([new_libexample/configure.ac], [[ # configure.ac AC_INIT([libexample], [1.0]) AM_INIT_AUTOMAKE([-Wall -Werror foreign]) # Add the macro directory AC_CONFIG_MACRO_DIRS([m4]) # Initialize the archiver AM_PROG_AR AC_PROG_CC # Set Libtool versioning LT_INIT AC_CONFIG_SRCDIR([src/example.c]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_FILES([Makefile src/Makefile]) AC_OUTPUT ]]) AT_DATA([libexample/src/example.c], [[ // src/example.c #include void example_function() { printf("Hello from example_function!\n"); } ]]) AT_DATA([libexample/src/example.h], [[ // src/example.h #ifndef EXAMPLE_H #define EXAMPLE_H void example_function(); #endif // EXAMPLE_H ]]) AT_DATA([new_libexample/src/example.c], [[ // src/example.c #include void example_function() { printf("Hello from example_function!\n"); } void new_function() { printf("new\n"); } ]]) AT_DATA([new_libexample/src/example.h], [[ // src/example.h // #ifndef EXAMPLE_H #define EXAMPLE_H void example_function(); void new_function(); #endif // EXAMPLE_H ]]) echo "Running autoreconf on libexample directory, the original library" ( cd libexample LT_AT_LIBTOOLIZE([--copy --ltdl]) LT_AT_AUTORECONF([-ivf]) LT_AT_CONFIGURE([], [configure]) LT_AT_MAKE([]) ) echo "Running autoreconf on new_libexample directory, the updated library" ( cd new_libexample LT_AT_LIBTOOLIZE([--copy --ltdl]) LT_AT_AUTORECONF([-ivf]) LT_AT_CONFIGURE([], [configure]) LT_AT_MAKE([]) ) remove_whitespace() { input_string=$1 echo "$input_string" | tr -d '[[:space:]]' } # Check if the version script exists if test -f "$_lt_pkgdatadir/libtool-next-version"; then script_path=$_lt_pkgdatadir/libtool-next-version elif test -f "$abs_builddir/../libtool-next-version"; then script_path=$abs_builddir/../libtool-next-version elif test -f "../../../libtool-next-version"; then script_path=../../../libtool-next-version else echo "Couldn't find script" fi AT_CHECK([test -f "$script_path"]) name=example eval libname=\"$libname_spec\" # Set version to 1.0.0. Select the default options for determining the new version of the library. (echo "1"; echo "0"; echo "0"; echo yes; echo no; echo no; echo yes) \ | $script_path libexample/.libs/$libname.$libext new_libexample/.libs/$libname.$libext > actual tr -d '[[:space:]]' < actual > temp && mv temp actual # Verify --help works $script_path --help > actual tr -d '[[:space:]]' < actual > temp && mv temp actual expected="Options: --help print this help and exit --version print version information and exit" expected=$(remove_whitespace "$expected") echo "expected is $expected" AT_CHECK([$GREP -i $expected actual], [0], [ignore]) # Verify --version works $script_path --version > actual tr -d '[[:space:]]' < actual > temp && mv temp actual expected="libtool-next-version (GNU libtool)" expected=$(remove_whitespace "$expected") echo "expected is $expected" AT_CHECK([$GREP -i $expected actual], [0], [ignore]) # Try each possible answer to the version script. # Case 1: Indicate to the script that there has not been any code change. (echo "1"; echo "0"; echo "0"; echo no) \ | $script_path libexample/.libs/$libname.$libext new_libexample/.libs/$libname.$libext > actual tr -d '[[:space:]]' < actual > temp && mv temp actual expected_version="This is the libtool version of the library for the new release: LTV_CURRENT=1 LTV_REVISION=0 LTV_AGE=0" expected_version=$(echo "$expected_version" | tr -d '[[:space:]]') AT_CHECK([$GREP -i $expected_version actual], [0], [ignore]) # Case 2: There is a code change. An interface has been removed. (echo "1"; echo "0"; echo "0"; echo yes; echo yes) \ | $script_path libexample/.libs/$libname.$libext new_libexample/.libs/$libname.$libext > actual tr -d '[[:space:]]' < actual > temp && mv temp actual expected_version="This is the libtool version of the library for the new release: LTV_CURRENT=2 LTV_REVISION=0 LTV_AGE=0" expected_version=$(echo "$expected_version" | tr -d '[[:space:]]') AT_CHECK([$GREP -i $expected_version actual], [0], [ignore]) # Case 3: There is a code change. No interfaces have been removed. An interface has changed. (echo "1"; echo "0"; echo "0"; echo yes; echo no; echo yes) \ | $script_path libexample/.libs/$libname.$libext new_libexample/.libs/$libname.$libext> actual tr -d '[[:space:]]' < actual > temp && mv temp actual expected_version="This is the libtool version of the library for the new release: LTV_CURRENT=2 LTV_REVISION=0 LTV_AGE=0" expected_version=$(echo "$expected_version" | tr -d '[[:space:]]') AT_CHECK([$GREP -i $expected_version actual], [0], [ignore]) # Case 4: There is a code change. No interfaces have been removed. No interfaces have changed. An interface has been added. (echo "1"; echo "0"; echo "0"; echo yes; echo no; echo no; echo yes) \ | $script_path libexample/.libs/$libname.$libext new_libexample/.libs/$libname.$libext > actual tr -d '[[:space:]]' < actual > temp && mv temp actual expected_version="This is the libtool version of the library for the new release: LTV_CURRENT=2 LTV_REVISION=0 LTV_AGE=1" expected_version=$(echo "$expected_version" | tr -d '[[:space:]]') AT_CHECK([$GREP -i $expected_version actual], [0], [ignore]) # Case 5: There is a code change. No interfaces have been removed. No interfaces have changed. No interfaces have been added. (echo "1"; echo "0"; echo "0"; echo yes; echo no; echo no; echo no; echo yes) \ | $script_path libexample/.libs/$libname.$libext new_libexample/.libs/$libname.$libext > actual tr -d '[[:space:]]' < actual > temp && mv temp actual expected_version="This is the libtool version of the library for the new release: LTV_CURRENT=1 LTV_REVISION=1 LTV_AGE=0" expected_version=$(echo "$expected_version" | tr -d '[[:space:]]') AT_CHECK([$GREP -i $expected_version actual], [0], [ignore]) case $host_os in mingw* | windows* | cygwin* | solaris* | linux-musl*) echo "Version script not testing code change differences on Solaris, Alpine Linux, and Windows platforms". ;; *) echo "Version script testing code change differences on $host_os" # Test on differences from the old library to the new library (echo "1"; echo "0"; echo "0"; echo yes; echo no; echo no; echo yes) \ | $script_path libexample/.libs/$libname.$libext new_libexample/.libs/$libname.$libext > actual tr -d '[[:space:]]' < actual > temp && mv temp actual # If the symbol list has changed and something has been added, roll the CURRENT and AGE version. # That is, the new version is 2.0.1 expected_version="This is the libtool version of the library for the new release: LTV_CURRENT=2 LTV_REVISION=0 LTV_AGE=1" expected_version=$(echo "$expected_version" | tr -d '[[:space:]]') AT_CHECK([$GREP -i $expected_version actual], [0], [ignore]) # Verify the symbol list has changed and is a new_function expected_1="The symbol list changed. Here are the differences:" expected_2=new_function expected_1=$(remove_whitespace "$expected_1") expected_2=$(remove_whitespace "$expected_2") echo "expected is $expected_1 && $expected_2" AT_CHECK([$GREP -i $expected_1 actual && $GREP -i $expected_2 actual], [0], [ignore]) esac AT_CLEANUP