| # 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 <https://www.gnu.org/licenses/>. | |
| #### | |
| #### | |
| 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 <stdio.h> | |
| 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 <stdio.h> | |
| 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 |