mirror of
https://https.git.savannah.gnu.org/git/libtool.git
synced 2026-01-27 01:44:28 +00:00
298 lines
10 KiB
Bash
298 lines
10 KiB
Bash
#! /bin/sh
|
|
#
|
|
# Copyright (C) 2019-2026 Free Software Foundation, Inc.
|
|
#
|
|
# This program 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 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
|
#
|
|
|
|
# This program is a wizard that helps a maintainer update the libtool
|
|
# version of a shared library, according to the documentation section
|
|
# 'Updating version info'
|
|
# <https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html>.
|
|
#
|
|
# Let's call the three parts of the version
|
|
# LTV_CURRENT
|
|
# LTV_REVISION
|
|
# LTV_AGE
|
|
#
|
|
# The list of steps given in this documentation section
|
|
# - If the library source code has changed at all since the last update,
|
|
# then increment LTV_REVISION.
|
|
# - If any interfaces have been added, removed, or changed since the last
|
|
# update, increment LTV_CURRENT and set LTV_REVISION to 0.
|
|
# - If any interfaces have been added since the last public release, then
|
|
# increment LTV_AGE.
|
|
# - If any interfaces have been removed or changed since the last public
|
|
# release, then set LTV_AGE to 0.
|
|
# leads to mistakes, because
|
|
# - It does not say what "interfaces" are.
|
|
# - It does not enforce that applying the second, third, or fourth rule
|
|
# is only possible after applying the first rule.
|
|
# - It does not enforce that applying the third or fourth rule is only
|
|
# possible after applying the second rule.
|
|
|
|
# func_usage
|
|
# outputs to stdout the --help usage message.
|
|
func_usage ()
|
|
{
|
|
echo "\
|
|
Usage: libtool-next-version [OPTION]... PREVIOUS-LIBRARY CURRENT-LIBRARY
|
|
|
|
Determines the next version to use for a libtool library.
|
|
|
|
PREVIOUS-LIBRARY is the installed library (in .a or .so format) of the
|
|
previous release.
|
|
|
|
CURRENT-LIBRARY is the installed library (in .a or .so format) of the current
|
|
release candidate.
|
|
|
|
Options:
|
|
--help print this help and exit
|
|
--version print version information and exit
|
|
|
|
Send patches and bug reports to <@PACKAGE_BUGREPORT@>."
|
|
}
|
|
|
|
# func_version
|
|
# outputs to stdout the --version message.
|
|
func_version ()
|
|
{
|
|
sed_extract_copyright_year='/Copyright (C)/{
|
|
s/.*\([0-9][0-9][0-9][0-9]\).*/\1/p
|
|
q
|
|
}'
|
|
copyright_year=`sed -n -e "$sed_extract_copyright_year" < "$0"`
|
|
echo "libtool-next-version (GNU @PACKAGE@) @VERSION@"
|
|
echo "Copyright (C) $copyright_year Free Software Foundation, Inc.
|
|
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
|
|
This is free software: you are free to change and redistribute it.
|
|
There is NO WARRANTY, to the extent permitted by law."
|
|
echo
|
|
printf 'Written by %s.\n' "Bruno Haible"
|
|
}
|
|
|
|
# func_fatal_error message
|
|
# outputs to stderr a fatal error message, and terminates the program.
|
|
func_fatal_error ()
|
|
{
|
|
echo "libtool-next-version: *** $1" 1>&2
|
|
echo "libtool-next-version: *** Stop." 1>&2
|
|
exit 1
|
|
}
|
|
|
|
# func_tmpdir
|
|
# creates a temporary directory.
|
|
# Sets variable
|
|
# - tmp pathname of freshly created temporary directory
|
|
func_tmpdir ()
|
|
{
|
|
# Use the environment variable TMPDIR, falling back to /tmp. This allows
|
|
# users to specify a different temporary directory, for example, if their
|
|
# /tmp is filled up or too small.
|
|
: "${TMPDIR=/tmp}"
|
|
{
|
|
# Use the mktemp program if available. If not available, hide the error
|
|
# message.
|
|
tmp=`(umask 077 && mktemp -d -q "$TMPDIR/gtXXXXXX") 2>/dev/null` &&
|
|
test -n "$tmp" && test -d "$tmp"
|
|
} ||
|
|
{
|
|
# Use a simple mkdir command. It is guaranteed to fail if the directory
|
|
# already exists. $RANDOM is bash specific and expands to empty in shells
|
|
# other than bash, ksh and zsh. Its use does not increase security;
|
|
# rather, it minimizes the probability of failure in a very cluttered /tmp
|
|
# directory.
|
|
tmp=$TMPDIR/gt$$-$RANDOM
|
|
(umask 077 && mkdir "$tmp")
|
|
} ||
|
|
{
|
|
echo "$0: cannot create a temporary directory in $TMPDIR" >&2
|
|
{ (exit 1); exit 1; }
|
|
}
|
|
}
|
|
|
|
# func_read_yesno
|
|
# reads an answer (yes or no).
|
|
# Sets variable
|
|
# - ans yes or no
|
|
func_read_yesno ()
|
|
{
|
|
while true; do
|
|
read ans
|
|
if test yes = "$ans" || test no = "$ans"; then
|
|
break
|
|
fi
|
|
echo "Invalid answer. Please answer yes or no."
|
|
done
|
|
}
|
|
|
|
# Command-line option processing.
|
|
while test $# -gt 0; do
|
|
case $1 in
|
|
--help | --hel | --he | --h )
|
|
func_usage
|
|
exit 0 ;;
|
|
--version | --versio | --versi | --vers | --ver | --ve | --v )
|
|
func_version
|
|
exit 0 ;;
|
|
-- ) # Stop option processing
|
|
shift; break ;;
|
|
-* )
|
|
func_fatal_error "unrecognized option: $option"
|
|
;;
|
|
* )
|
|
break ;;
|
|
esac
|
|
done
|
|
|
|
test $# = 2 || {
|
|
if test $# -gt 2; then
|
|
func_fatal_error "too many arguments"
|
|
else
|
|
func_fatal_error "Usage: libtool-next-version [OPTION]... PREVIOUS-LIBRARY CURRENT-LIBRARY"
|
|
fi
|
|
}
|
|
|
|
test -f "$1" || func_fatal_error "file $1 not found"
|
|
test -f "$2" || func_fatal_error "file $2 not found"
|
|
|
|
(type nm) >/dev/null || func_fatal_error "program 'nm' not found"
|
|
# Determine how to extract a symbol list from the 'nm' output.
|
|
case `uname -s` in
|
|
Linux | FreeBSD | NetBSD | OpenBSD) nm_filter="sed -n -e 's/^.* [TWDRB] //p'" ;;
|
|
Darwin) nm_filter="sed -n -e 's/^.* [TWDRB] _//p'" ;;
|
|
Minix) nm_filter="sed -n -e 's/^.* [TDC] _//p'" ;;
|
|
AIX) nm_filter="sed -n -e 's/ *[UD] .*//p' | sed -e 's/^\\.//'" ;;
|
|
HP-UX) nm_filter="grep '|extern|\\(code\\|data\\) |' | sed -e 's/|.*//' | sed -e 's/ *$//'" ;;
|
|
IRIX) nm_filter="grep '|\\(GLOB\\|WEAK\\)' | sed -e 's/^.*|//'" ;;
|
|
SunOS)
|
|
case `uname -r` in
|
|
5.10) nm_filter="sed -n -e 's/^.* [ATWDRBV] //p'" ;;
|
|
*) nm_filter="grep '|\\(GLOB\\|WEAK\\)' | grep -v '|UNDEF' | grep -v '|SUNW' | sed -e 's/^.*|//'" ;;
|
|
esac
|
|
;;
|
|
CYGWIN*) nm_filter="sed -n -e 's/^.* T _//p'" ;;
|
|
*) func_fatal_error "unknown OS - don't know how to interpret the 'nm' output" ;;
|
|
esac
|
|
nm_filter="$nm_filter | LC_ALL=C sort -u"
|
|
|
|
func_tmpdir
|
|
eval "nm '$1' | $nm_filter > '$tmp/symlist1'"
|
|
eval "nm '$2' | $nm_filter > '$tmp/symlist2'"
|
|
|
|
echo "Please enter the libtool version of the library in the previous release."
|
|
|
|
printf "LTV_CURRENT="; read current
|
|
nondigits=`echo "$current" | tr -d '0123456789'`
|
|
{ test -n "$current" && test -z "$nondigits"; } \
|
|
|| func_fatal_error "LTV_CURRENT is invalid. It should be a nonnegative integer."
|
|
|
|
printf "LTV_REVISION="; read revision
|
|
nondigits=`echo "$revision" | tr -d '0123456789'`
|
|
{ test -n "$revision" && test -z "$nondigits"; } \
|
|
|| func_fatal_error "LTV_REVISION is invalid. It should be a nonnegative integer."
|
|
|
|
printf "LTV_AGE="; read age
|
|
nondigits=`echo "$age" | tr -d '0123456789'`
|
|
{ test -n "$age" && test -z "$nondigits"; } \
|
|
|| func_fatal_error "LTV_AGE is invalid. It should be a nonnegative integer."
|
|
|
|
echo
|
|
echo "-------------------------------------------------------------------------------"
|
|
echo "Did the library's code change at all since the previous version?"
|
|
echo "You can usually detect this by looking at the source code changes in git;"
|
|
echo "don't forget source code that is imported from other projects."
|
|
if cmp "$tmp/symlist1" "$tmp/symlist2" >/dev/null; then
|
|
echo "Please answer yes or no."
|
|
else
|
|
echo "The symbol list changed. Here are the differences:"
|
|
(cd "$tmp" && diff symlist1 symlist2 | grep '^[<>]' | sed -e 's/^/ /')
|
|
echo "Please answer yes or no (probably yes)."
|
|
fi
|
|
func_read_yesno
|
|
if test yes = "$ans"; then
|
|
|
|
revision=`expr $revision + 1`
|
|
|
|
echo
|
|
echo "-------------------------------------------------------------------------------"
|
|
echo "Have any interfaces (functions, variables, classes) been removed since the"
|
|
echo "previous release? What matters here are interfaces at the linker level;"
|
|
echo "whether macros have been removed from the include files does not matter."
|
|
if diff "$tmp/symlist1" "$tmp/symlist2" | grep '^< ' >/dev/null; then
|
|
echo "Some symbols have been removed:"
|
|
diff "$tmp/symlist1" "$tmp/symlist2" | grep '^< ' | sed -e 's/^< / /'
|
|
echo "Please answer yes or no (probably yes)."
|
|
else
|
|
echo "Please answer yes or no."
|
|
fi
|
|
func_read_yesno
|
|
|
|
if test yes = "$ans"; then
|
|
|
|
current=`expr $current + 1`
|
|
revision=0
|
|
age=0
|
|
|
|
else
|
|
|
|
echo
|
|
echo "-------------------------------------------------------------------------------"
|
|
echo "Have any interfaces (functions, variables, classes) been changed since the"
|
|
echo "previous release? This includes signature changes. It includes also details of"
|
|
echo "how functions produce their results and the values of variables, IF AND ONLY IF"
|
|
echo "users of the library are likely use these details in their test suite."
|
|
echo "Please answer yes or no."
|
|
func_read_yesno
|
|
|
|
if test yes = "$ans"; then
|
|
|
|
current=`expr $current + 1`
|
|
revision=0
|
|
age=0
|
|
|
|
else
|
|
|
|
echo
|
|
echo "-------------------------------------------------------------------------------"
|
|
echo "Have any interfaces (functions, variables, classes) been added since the"
|
|
echo "previous release? What matters here are interfaces at the linker level;"
|
|
echo "whether macros have been added to the include files does not matter."
|
|
if diff "$tmp/symlist1" "$tmp/symlist2" | grep '^> ' >/dev/null; then
|
|
echo "Some symbols have been added:"
|
|
diff "$tmp/symlist1" "$tmp/symlist2" | grep '^> ' | sed -e 's/^> / /'
|
|
echo "Please answer yes or no (probably yes)."
|
|
else
|
|
echo "Please answer yes or no."
|
|
fi
|
|
func_read_yesno
|
|
|
|
if test yes = "$ans"; then
|
|
|
|
current=`expr $current + 1`
|
|
revision=0
|
|
age=`expr $age + 1`
|
|
|
|
fi
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
echo
|
|
echo "-------------------------------------------------------------------------------"
|
|
echo "This is the libtool version of the library for the new release:"
|
|
echo "LTV_CURRENT=$current"
|
|
echo "LTV_REVISION=$revision"
|
|
echo "LTV_AGE=$age"
|