1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2024-12-22 17:34:18 +03:00

autogen.sh: Improve and generalize

The goal is twofold: firstly, we want to extend the script so
that it can deal with more than a single git submodule, and
secondly we'd like to reduce the amount of duplicated code.
Moreover, since we're making heavy changes to the code anyway,
we might as well make sure it follows a somewhat consistent
coding style too.

To reduce code duplication, we introduce a new --dry-run
option, which can be used by third parties to figure out
whether calling autogen.sh is necessary or not: this allows
us to get rid of the reimplementation of part of the logic
in cfg.mk and guarantee they'll never get out of sync.

Other changes include: making dirty submodules checking and
cleaning entirely independent of other operations; removing
the use of 'set -e' and handling errors explicitly instead;
better parsing of command line arguments.
This commit is contained in:
Andrea Bolognani 2017-04-12 13:09:08 +02:00
parent 5efa7f2a4b
commit 6d53255377
2 changed files with 196 additions and 116 deletions

View File

@ -1,117 +1,196 @@
#!/bin/sh #!/bin/sh
# Run this to generate all the initial makefiles, etc. # Run this to generate all the initial makefiles, etc.
set -e die()
{
srcdir=`dirname "$0"` echo "error: $1" >&2
test -z "$srcdir" && srcdir=.
THEDIR=`pwd`
cd "$srcdir"
test -f src/libvirt.c || {
echo "You must run this script in the top-level libvirt directory"
exit 1 exit 1
} }
starting_point=$(pwd)
EXTRA_ARGS= srcdir=$(dirname "$0")
test "$srcdir" || srcdir=.
cd "$srcdir" || {
die "Failed to cd into $srcdir"
}
test -f src/libvirt.c || {
die "$0 must live in the top-level libvirt directory"
}
dry_run=
no_git= no_git=
if test "x$1" = "x--no-git"; then gnulib_srcdir=
extra_args=
while test "$#" -gt 0; do
case "$1" in
--dry-run)
# This variable will serve both as an indicator of the fact that
# a dry run has been requested, and to store the result of the
# dry run. It will be ultimately used as return code for the
# script: 0 means no action is necessary, 2 means that autogen.sh
# needs to be executed, and 1 is reserved for failures
dry_run=0
shift
;;
--no-git)
no_git=" $1" no_git=" $1"
shift shift
case "$1 $2" in ;;
--gnulib-srcdir=*) no_git="$no_git $1"; shift ;; --gnulib-srcdir=*)
--gnulib-srcdir\ *) no_git="$no_git $1=$2"; shift; shift;; gnulib_srcdir=" $1"
esac
fi
if test -z "$NOCONFIGURE" ; then
if test "x$1" = "x--system"; then
shift shift
;;
--gnulib-srcdir)
gnulib_srcdir=" $1=$2"
shift
shift
;;
--system)
prefix=/usr prefix=/usr
libdir=$prefix/lib
sysconfdir=/etc sysconfdir=/etc
localstatedir=/var localstatedir=/var
if [ -d /usr/lib64 ]; then if test -d $prefix/lib64; then
libdir=$prefix/lib64 libdir=$prefix/lib64
fi
EXTRA_ARGS="--prefix=$prefix --sysconfdir=$sysconfdir --localstatedir=$localstatedir --libdir=$libdir"
echo "Running ./configure with $EXTRA_ARGS $@"
else else
if test -z "$*" && test ! -f "$THEDIR/config.status"; then libdir=$prefix/lib
echo "I am going to run ./configure with no arguments - if you wish"
echo "to pass any to it, please specify them on the $0 command line."
fi fi
fi extra_args="--prefix=$prefix --localstatedir=$localstatedir"
fi extra_args="$extra_args --sysconfdir=$sysconfdir --libdir=$libdir"
shift
;;
*)
# All remaining arguments will be passed to configure verbatim
break
;;
esac
done
no_git="$no_git$gnulib_srcdir"
# Compute the hash we'll use to determine whether rerunning bootstrap gnulib_hash()
# is required. The first is just the SHA1 that selects a gnulib snapshot.
# The second ensures that whenever we change the set of gnulib modules used
# by this package, we rerun bootstrap to pull in the matching set of files.
# The third ensures that whenever we change the set of local gnulib diffs,
# we rerun bootstrap to pull in those diffs.
bootstrap_hash()
{ {
local no_git=$1
if test "$no_git"; then if test "$no_git"; then
echo no-git echo "no-git"
return return
fi fi
git submodule status | sed 's/^[ +-]//;s/ .*//'
# Compute the hash we'll use to determine whether rerunning bootstrap
# is required. The first is just the SHA1 that selects a gnulib snapshot.
# The second ensures that whenever we change the set of gnulib modules used
# by this package, we rerun bootstrap to pull in the matching set of files.
# The third ensures that whenever we change the set of local gnulib diffs,
# we rerun bootstrap to pull in those diffs.
git submodule status .gnulib | awk '{ print $1 }'
git hash-object bootstrap.conf git hash-object bootstrap.conf
git ls-tree -d HEAD gnulib/local | awk '{print $3}' git ls-tree -d HEAD gnulib/local | awk '{ print $3 }'
} }
# Ensure that whenever we pull in a gnulib update or otherwise change to a # Only look into git submodules if we're in a git checkout
# different version (i.e., when switching branches), we also rerun ./bootstrap.
# Also, running 'make rpm' tends to litter the po/ directory, and some people
# like to run 'git clean -x -f po' to fix it; but only ./bootstrap regenerates
# the required file po/Makevars.
# Only run bootstrap from a git checkout, never from a tarball.
if test -d .git || test -f .git; then if test -d .git || test -f .git; then
curr_status=.git-module-status t=
if test "$no_git"; then # Check for dirty submodules
t=no-git if test -z "$CLEAN_SUBMODULE"; then
elif test -d .gnulib; then for path in $(git submodule status | awk '{ print $2 }'); do
t=$(bootstrap_hash; git diff .gnulib) case "$(git diff "$path")" in
fi
case $t:${CLEAN_SUBMODULE+set} in
*:set) ;;
*-dirty*) *-dirty*)
echo "error: gnulib submodule is dirty, please investigate" 2>&1 echo "error: $path is dirty, please investigate" >&2
echo "set env-var CLEAN_SUBMODULE to discard gnulib changes" 2>&1 echo "set CLEAN_SUBMODULE to discard submodule changes" >&2
exit 1 ;; exit 1
;;
esac esac
# Keep this test in sync with cfg.mk:_update_required done
if test "$t" = "$(cat $curr_status 2>/dev/null)" \ fi
&& test -f "po/Makevars" && test -f AUTHORS; then if test "$CLEAN_SUBMODULE" && test -z "$no_git"; then
# good, it's up to date, all we need is autoreconf if test -z "$dry_run"; then
autoreconf -if echo "Cleaning up submodules..."
git submodule foreach 'git clean -dfqx && git reset --hard' || {
die "Cleaning up submodules failed"
}
fi
fi
# Update all submodules. If any of the submodules has not been
# initialized yet, it will be initialized now; moreover, any submodule
# with uncommitted changes will be returned to the expected state
echo "Updating submodules..."
git submodule update --init || {
die "Updating submodules failed"
}
# The expected hash, eg. the one computed after the last
# successful bootstrap run, is stored on disk
state_file=.git-module-status
expected_hash=$(cat "$state_file" 2>/dev/null)
actual_hash=$(gnulib_hash "$no_git")
if test "$actual_hash" = "$expected_hash" && \
test -f po/Makevars && test -f AUTHORS; then
# The gnulib hash matches our expectations, and all the files
# that can only be generated through bootstrap are present:
# we just need to run autoreconf. Unless we're performing a
# dry run, of course...
if test -z "$dry_run"; then
echo "Running autoreconf..."
autoreconf -if || {
die "autoreconf failed"
}
fi
else else
if test -z "$no_git" && test ${CLEAN_SUBMODULE+set}; then # Whenever the gnulib submodule or any of the related bits
echo cleaning up submodules... # has been changed in some way (see gnulib_hash) we need to
git submodule foreach 'git clean -dfqx && git reset --hard' # run bootstrap again. If we're performing a dry run, we
# change the return code instead to signal our caller
if test "$dry_run"; then
dry_run=2
else
echo "Running bootstrap..."
./bootstrap$no_git --bootstrap-sync || {
die "bootstrap failed"
}
gnulib_hash >"$state_file"
fi fi
echo running bootstrap$no_git...
./bootstrap$no_git --bootstrap-sync && bootstrap_hash > $curr_status \
|| { echo "Failed to bootstrap, please investigate."; exit 1; }
fi fi
fi fi
test -n "$NOCONFIGURE" && exit 0 # When performing a dry run, we can stop here
test "$dry_run" && exit "$dry_run"
cd "$THEDIR" # If asked not to run configure, we can stop here
test "$NOCONFIGURE" && exit 0
if test "x$OBJ_DIR" != x; then cd "$starting_point" || {
mkdir -p "$OBJ_DIR" die "Failed to cd into $starting_point"
cd "$OBJ_DIR"
fi
if test -z "$*" && test -z "$EXTRA_ARGS" && test -f config.status; then
./config.status --recheck
else
$srcdir/configure $EXTRA_ARGS "$@"
fi && {
echo
echo "Now type 'make' to compile libvirt."
} }
if test "$OBJ_DIR"; then
mkdir -p "$OBJ_DIR" || {
die "Failed to create $OBJ_DIR"
}
cd "$OBJ_DIR" || {
die "Failed to cd into $OBJ_DIR"
}
fi
if test -z "$*" && test -z "$extra_args" && test -f config.status; then
echo "Running config.status..."
./config.status --recheck || {
die "config.status failed"
}
else
if test -z "$*" && test -z "$extra_args"; then
echo "I am going to run configure with no arguments - if you wish"
echo "to pass any to it, please specify them on the $0 command line."
else
echo "Running configure with $extra_args $@"
fi
"$srcdir/configure" $extra_args "$@" || {
die "configure failed"
}
fi
echo
echo "Now type 'make' to compile libvirt."

51
cfg.mk
View File

@ -1026,33 +1026,30 @@ prev_version_file = /dev/null
ifneq ($(_gl-Makefile),) ifneq ($(_gl-Makefile),)
ifeq (0,$(MAKELEVEL)) ifeq (0,$(MAKELEVEL))
_curr_status = .git-module-status _dry_run_result := $(shell \
# The sed filter accommodates those who check out on a commit from which
# no tag is reachable. In that case, git submodule status prints a "-"
# in column 1 and does not print a "git describe"-style string after the
# submodule name. Contrast these:
# -b653eda3ac4864de205419d9f41eec267cb89eeb .gnulib
# b653eda3ac4864de205419d9f41eec267cb89eeb .gnulib (v0.0-2286-gb653eda)
# $ cat .git-module-status
# b653eda3ac4864de205419d9f41eec267cb89eeb
#
# Keep this logic in sync with autogen.sh.
_submodule_hash = $(SED) 's/^[ +-]//;s/ .*//'
_update_required := $(shell \
cd '$(srcdir)'; \ cd '$(srcdir)'; \
test -d .git || { echo 0; exit; }; \ test -d .git || test -f .git || { echo 0; exit; }; \
test -f po/Makevars || { echo 1; exit; }; \ $(srcdir)/autogen.sh --dry-run >/dev/null 2>&1; \
test -f AUTHORS || { echo 1; exit; }; \ echo $$?; \
test "no-git" = "$$(cat $(_curr_status))" && { echo 0; exit; }; \ )
actual=$$(git submodule status | $(_submodule_hash); \
git hash-object bootstrap.conf; \
git ls-tree -d HEAD gnulib/local | awk '{print $$3}'; \
git diff .gnulib); \
stamp="$$($(_submodule_hash) $(_curr_status) 2>/dev/null)"; \
test "$$stamp" = "$$actual"; echo $$?)
_clean_requested = $(filter %clean,$(MAKECMDGOALS)) _clean_requested = $(filter %clean,$(MAKECMDGOALS))
ifeq (1,$(_update_required)$(_clean_requested))
$(info INFO: gnulib update required; running ./autogen.sh first) # A return value of 0 means no action is required
# A return value of 1 means a genuine error has occurred while
# performing the dry run, and it should be reported so it can
# be investigated
ifeq (1,$(_dry_run_result))
$(info INFO: autogen.sh error, running again to show details)
maint.mk Makefile: _autogen_error
endif
# A return value of 2 means that autogen.sh needs to be executed
# in earnest before building, probably because of gnulib updates.
# We don't run autogen.sh if the clean target has been invoked,
# though, as it would be quite pointless
ifeq (2,$(_dry_run_result)$(_clean_requested))
$(info INFO: running autogen.sh is required, running it now...)
$(shell touch $(srcdir)/AUTHORS $(srcdir)/ChangeLog) $(shell touch $(srcdir)/AUTHORS $(srcdir)/ChangeLog)
maint.mk Makefile: _autogen maint.mk Makefile: _autogen
endif endif
@ -1066,6 +1063,10 @@ _autogen:
$(srcdir)/autogen.sh $(srcdir)/autogen.sh
./config.status ./config.status
.PHONY: _autogen_error
_autogen_error:
$(srcdir)/autogen.sh --dry-run
# regenerate HACKING as part of the syntax-check # regenerate HACKING as part of the syntax-check
ifneq ($(_gl-Makefile),) ifneq ($(_gl-Makefile),)
syntax-check: $(top_srcdir)/HACKING spacing-check test-wrap-argv \ syntax-check: $(top_srcdir)/HACKING spacing-check test-wrap-argv \