#! /bin/sh
error() {
echo "gcc_release: error: $1"
exit 1
}
inform() {
echo "gcc_release: $1"
}
usage() {
cat <<EOF
gcc_release -r release [-f] [further options]
gcc_release -s name:cvsbranch [further options]
Options:
-r release Version of the form X.Y or X.Y.Z.
-s name:cvsbranch Create a snapshot, not a real release.
-d destination Local working directory where we will build the release
(default=${HOME}).
-f Create a final release (and update ChangeLogs,...).
-l Indicate that we are running on gcc.gnu.org.
-p previous-tarball Location of a previous tarball (to generate diff files).
-t tag Tag to mark the release in CVS.
-u username Username for upload operations.
EOF
exit 1
}
changedir() {
cd $1 || \
error "Could not change directory to $1"
}
adjust_dirs() {
for x in $@; do
echo `basename ${SOURCE_DIRECTORY}`/$x
done
}
build_sources() {
if [ -r ${WORKING_DIRECTORY} ]; then
error "\`${WORKING_DIRECTORY}' already exists"
fi
mkdir "${WORKING_DIRECTORY}" \
|| error "Could not create \`${WORKING_DIRECTORY}'"
changedir "${WORKING_DIRECTORY}"
if [ ${FINAL} -ne 0 ]; then
inform "Updating ChangeLogs and version files"
${CVS} co -d "`basename ${SOURCE_DIRECTORY}`" \
-r ${CVSBRANCH} gcc || \
error "Could not check out release sources"
for x in `find ${SOURCE_DIRECTORY} -name ChangeLog`; do
if ! grep "GCC ${RELEASE} released." ${x} > /dev/null ; then
cat - ${x} > ${x}.new <<EOF
${LONG_DATE} Release Manager
* GCC ${RELEASE} released.
EOF
mv ${x}.new ${x} || \
error "Could not update ${x}"
(changedir `dirname ${x}` && \
${CVS} ci -m 'Mark ChangeLog' `basename ${x}`) || \
error "Could not commit ${x}"
fi
done
for x in gcc/version.c; do
y=`basename ${x}`
(changedir `dirname ${SOURCE_DIRECTORY}/${x}` && \
sed -e 's|version_string\[\] = \".*\"|version_string\[\] = \"'${RELEASE}'\"|g' < ${y} > ${y}.new && \
mv ${y}.new ${y} && \
${CVS} ci -m 'Update version' ${y}) || \
error "Could not update ${x}"
done
# Make sure we tag the sources for a final release.
TAG="gcc_`echo ${RELEASE} | tr . _`_release"
rm -rf ${SOURCE_DIRECTORY}
fi
# Tag the sources.
EXPORTDATE=""
if [ -n "${TAG}" ]; then
inform "Tagging sources as ${TAG}"
# The -F option to CVS is intentionally not used below. If you
# need to retry a release, you will have to manually remove any
# existing tag.
${CVS} rtag -r ${CVSBRANCH} ${TAG} gcc || \
error "Could not tag sources"
EXPORTTAG="-r${TAG}"
else
if [ ${CVSBRANCH} != "HEAD" ]; then
EXPORTTAG="-r${CVSBRANCH}"
# It does not work to use both "-r" and "-D" with
# "cvs export" so EXPORTDATE is not set here.
else
# HEAD is the default branch, no need to specify it.
EXPORTTAG=""
EXPORTDATE="-D`date -u +"%Y-%m-%d %H:%M"` UTC"
fi
fi
# Export the current sources.
inform "Retrieving sources (cvs export ${EXPORTTAG} ${EXPORTDATE} gcc)"
if [ -z "${EXPORTTAG}" ]; then
${CVS} export -d "`basename ${SOURCE_DIRECTORY}`" \
"${EXPORTDATE}" gcc || \
error "Could not retrieve sources"
elif [ -z "${EXPORTDATE}" ]; then
${CVS} export -d "`basename ${SOURCE_DIRECTORY}`" \
"${EXPORTTAG}" gcc || \
error "Could not retrieve sources"
else
error "Cannot specify -r and -D at the same time"
fi
# Run gcc_update on them to set up the timestamps nicely, and (re)write
# the LAST_UPDATED file containing the CVS tag/date used.
changedir "gcc-${RELEASE}"
contrib/gcc_update --touch
echo "Obtained from CVS: ${EXPORTTAG} ${EXPORTDATE}" > LAST_UPDATED
# Obtain some documentation files from the wwwdocs module.
inform "Retrieving HTML documentation"
changedir "${WORKING_DIRECTORY}"
for x in bugs faq; do
(${CVS} export -r HEAD wwwdocs/htdocs/${x}.html && \
cp ${WORKING_DIRECTORY}/wwwdocs/htdocs/${x}.html \
${SOURCE_DIRECTORY}) || \
error "Could not retrieve ${x}.html"
done
inform "Generating plain-text documentation from HTML"
changedir "${SOURCE_DIRECTORY}"
for file in *.html; do
newfile=`echo $file | sed -e 's/.html//' | tr "[:lower:]" "[:upper:]"`
(${ENV} TERM=vt100 lynx -dump $file \
| sed -e "s > $newfile) || \
error "Could not generate text-only version of ${file}"
done
changedir "${SOURCE_DIRECTORY}"
if [ $SNAPSHOT -ne 1 ]; then
inform "Building install docs"
SOURCEDIR=${SOURCE_DIRECTORY}/gcc/doc
DESTDIR=${SOURCE_DIRECTORY}/INSTALL
export SOURCEDIR
export DESTDIR
${SOURCE_DIRECTORY}/gcc/doc/install.texi2html
contrib/gennews > NEWS || \
error "Could not regenerate NEWS files"
inform "Building compiler"
OBJECT_DIRECTORY=../objdir
contrib/gcc_build -d ${SOURCE_DIRECTORY} -o ${OBJECT_DIRECTORY} \
-c "--enable-generated-files-in-srcdir" build || \
error "Could not rebuild GCC"
fi
mv ../objdir/gcc/po/*.gmo gcc/po/
[ -f libcpp/po/cpplib.pot ] && mv ../objdir/libcpp/po/*.gmo libcpp/po/
echo \
"# This file contains the MD5 checksums of the files in the
# gcc-"${RELEASE}".tar.bz2 tarball.
#
# Besides verifying that all files in the tarball were correctly expanded,
# it also can be used to determine if any files have changed since the
# tarball was expanded or to verify that a patchfile was correctly applied.
#
# Suggested usage:
# md5sum -c MD5SUMS | grep -v \"OK$\"
" > MD5SUMS
find . -type f |
sed -e 's:^\./::' -e '/MD5SUMS/d' |
sort |
xargs md5sum >>MD5SUMS
}
build_tarfile() {
TARFILE="$1.tar.bz2"
shift
(${TAR} cf - "$@" | ${BZIP2} > ${TARFILE}) || \
error "Could not build tarfile"
FILE_LIST="${FILE_LIST} ${TARFILE}"
}
maybe_build_tarfile() {
dest=$1
shift
dir_exists=0
for maybe_dir in "$@"; do
if [ -d "$maybe_dir" ]; then
dir_exists=1
fi
done
if [ $dir_exists = 1 ]; then
build_tarfile "$dest" "$@"
else
echo "Not building $dest tarfile"
fi
}
build_tarfiles() {
inform "Building tarfiles"
changedir "${WORKING_DIRECTORY}"
chmod -R a+r ${SOURCE_DIRECTORY}
find ${SOURCE_DIRECTORY} -type d -exec chmod 777 {} \;
build_tarfile gcc-${RELEASE} `basename ${SOURCE_DIRECTORY}`
maybe_build_tarfile gcc-ada-${RELEASE} ${ADA_DIRS}
maybe_build_tarfile gcc-g++-${RELEASE} ${CPLUSPLUS_DIRS}
maybe_build_tarfile gcc-g77-${RELEASE} ${FORTRAN_DIRS}
maybe_build_tarfile gcc-fortran-${RELEASE} ${FORTRAN95_DIRS}
maybe_build_tarfile gcc-java-${RELEASE} ${JAVA_DIRS}
maybe_build_tarfile gcc-objc-${RELEASE} ${OBJECTIVEC_DIRS}
maybe_build_tarfile gcc-testsuite-${RELEASE} ${TESTSUITE_DIRS}
EXCLUDES=""
for x in ${ADA_DIRS} ${CPLUSPLUS_DIRS} ${FORTRAN_DIRS} ${FORTRAN95_DIRS}\
${JAVA_DIRS} ${OBJECTIVEC_DIRS} ${TESTSUITE_DIRS}; do
EXCLUDES="${EXCLUDES} --exclude $x"
done
build_tarfile gcc-core-${RELEASE} ${EXCLUDES} \
`basename ${SOURCE_DIRECTORY}`
}
build_gzip() {
for f in ${FILE_LIST}; do
target=${f%.bz2}.gz
(${BZIP2} -d -c $f | ${GZIP} > ${target}) || error "Could not create ${target}"
done
}
build_diffs() {
old_dir=${1%/*}
old_file=${1 old_vers=${old_file%.tar.bz2}
old_vers=${old_vers inform "Building diffs against version $old_vers"
for f in gcc gcc-ada gcc-g++ gcc-g77 gcc-fortran gcc-java gcc-objc gcc-testsuite gcc-core; do
old_tar=${old_dir}/${f}-${old_vers}.tar.bz2
new_tar=${WORKING_DIRECTORY}/${f}-${RELEASE}.tar.bz2
if [ ! -e $old_tar ]; then
inform "$old_tar not found; not generating diff file"
elif [ ! -e $new_tar ]; then
inform "$new_tar not found; not generating diff file"
else
build_diff $old_tar gcc-${old_vers} $new_tar gcc-${RELEASE} \
${f}-${old_vers}-${RELEASE}.diff.bz2
fi
done
}
build_diff() {
changedir "${WORKING_DIRECTORY}"
tmpdir=gccdiff.$$
mkdir $tmpdir || error "Could not create directory $tmpdir"
changedir $tmpdir
(${BZIP2} -d -c $1 | ${TAR} xf - ) || error "Could not unpack $1 for diffs"
(${BZIP2} -d -c $3 | ${TAR} xf - ) || error "Could not unpack $3 for diffs"
${DIFF} $2 $4 > ../${5%.bz2}
if [ $? -eq 2 ]; then
error "Trouble making diffs from $1 to $3"
fi
${BZIP2} ../${5%.bz2} || error "Could not generate ../$5"
changedir ..
rm -rf $tmpdir
FILE_LIST="${FILE_LIST} $5"
}
upload_files() {
inform "Uploading files"
changedir "${WORKING_DIRECTORY}"
if [ $LOCAL -eq 0 ]; then
${SSH} -l ${GCC_USERNAME} ${GCC_HOSTNAME} \
mkdir -p "${FTP_PATH}/diffs"
UPLOAD_PATH="${GCC_USERNAME}@${GCC_HOSTNAME}:${FTP_PATH}"
else
mkdir -p "${FTP_PATH}/diffs" \
|| error "Could not create \`${FTP_PATH}'"
UPLOAD_PATH=${FTP_PATH}
fi
for x in gcc*.gz gcc*.bz2; do
if [ -e ${x} ]; then
chmod a+r ${x}
case ${x} in
*.diff.*)
SUBDIR="diffs/";
;;
*)
SUBDIR="";
esac
${SCP} ${x} ${UPLOAD_PATH}/${SUBDIR} \
|| error "Could not upload ${x}"
fi
done
}
snapshot_print() {
if [ -e ${RELEASE}/$1 ]; then
printf "%-38s%s\n\n" "$1" "$2" >> ${SNAPSHOT_README}
echo " <tr><td><a href=\"$1\">$1</a></td>" >> ${SNAPSHOT_INDEX}
echo " <td>$2</td></tr>" >> ${SNAPSHOT_INDEX}
fi
}
announce_snapshot() {
inform "Updating links and READMEs on the FTP server"
TEXT_DATE=`date --date=$DATE +%B\ %d,\ %Y`
SNAPSHOT_README=${RELEASE}/README
SNAPSHOT_INDEX=${RELEASE}/index.html
changedir "${SNAPSHOTS_DIR}"
echo \
"Snapshot gcc-"${RELEASE}" is now available on
ftp://gcc.gnu.org/pub/gcc/snapshots/"${RELEASE}"/
and on various mirrors, see http://gcc.gnu.org/mirrors.html for details.
This snapshot has been generated from the GCC "${BRANCH}" CVS branch
with the following options: "${EXPORTTAG} ${EXPORTDATE}"
You'll find:
" > ${SNAPSHOT_README}
echo \
"<html>
<head>
<title>GCC "${RELEASE}" Snapshot</title>
</head>
<body>
<h1>GCC "${RELEASE}" Snapshot</h1>
<p>The <a href =\"http://gcc.gnu.org/\">GCC Project</a> makes
periodic snapshots of the GCC source tree available to the public
for testing purposes.</p>
<p>If you are planning to download and use one of our snapshots, then
we highly recommend you join the GCC developers list. Details for
how to sign up can be found on the GCC project home page.</p>
<p>This snapshot has been generated from the GCC "${BRANCH}" CVS branch
with the following options: <code>"${EXPORTTAG} ${EXPORTDATE}"</code></p>
<table>" > ${SNAPSHOT_INDEX}
snapshot_print gcc-${RELEASE}.tar.bz2 "Complete GCC (includes all of below)"
snapshot_print gcc-core-${RELEASE}.tar.bz2 "C front end and core compiler"
snapshot_print gcc-ada-${RELEASE}.tar.bz2 "Ada front end and runtime"
snapshot_print gcc-fortran-${RELEASE}.tar.bz2 "Fortran front end and runtime"
snapshot_print gcc-g++-${RELEASE}.tar.bz2 "C++ front end and runtime"
snapshot_print gcc-g77-${RELEASE}.tar.bz2 "Fortran 77 front end and runtime"
snapshot_print gcc-java-${RELEASE}.tar.bz2 "Java front end and runtime"
snapshot_print gcc-objc-${RELEASE}.tar.bz2 "Objective-C front end and runtime"
snapshot_print gcc-testsuite-${RELEASE}.tar.bz2 "The GCC testsuite"
echo \
"Diffs from "${BRANCH}"-"${LAST_DATE}" are available in the diffs/ subdirectory.
When a particular snapshot is ready for public consumption the LATEST-"${BRANCH}"
link is updated and a message is sent to the gcc list. Please do not use
a snapshot before it has been announced that way." >> ${SNAPSHOT_README}
echo \
"</table>
<p>Diffs from "${BRANCH}"-"${LAST_DATE}" are available in the
<a href=\"diffs/\">diffs/ subdirectory</a>.</p>
<p>When a particular snapshot is ready for public consumption the LATEST-"${BRANCH}"
link is updated and a message is sent to the gcc list. Please do not use
a snapshot before it has been announced that way.</p>
<hr />
<address>
<a href=\"mailto:gcc@gcc.gnu.org\">gcc@gcc.gnu.org</a>
<br />
Last modified "${TEXT_DATE}"
</address>
</body>
</html>" >> ${SNAPSHOT_INDEX}
rm -f LATEST-${BRANCH}
ln -s ${RELEASE} LATEST-${BRANCH}
inform "Sending mail"
export QMAILHOST=gcc.gnu.org
mail -s "gcc-${RELEASE} is now available" gcc@gcc.gnu.org < ${SNAPSHOT_README}
}
DATE=`date "+%Y%m%d"`
LONG_DATE=`date "+%Y-%m-%d"`
CVS_SERVER="gcc.gnu.org"
CVS_REPOSITORY="/cvs/gcc"
CVS_PROTOCOL="ext"
CVS_USERNAME="${USER}"
GCC_HOSTNAME="gcc.gnu.org"
GCC_USERNAME="gccadmin"
FTP_PATH=/var/ftp/pub/gcc
SNAPSHOTS_DIR=${FTP_PATH}/snapshots
RELEASE_MAJOR=""
RELEASE_MINOR=""
RELEASE_REVISION=""
RELEASE=""
BRANCH=""
CVSBRANCH=""
TAG=""
OLD_TARS=""
DESTINATION=${HOME}
WORKING_DIRECTORY=""
SOURCE_DIRECTORY=""
ADA_DIRS="gcc/ada libada"
CPLUSPLUS_DIRS="gcc/cp libstdc++-v3"
FORTRAN_DIRS="gcc/f libf2c"
FORTRAN95_DIRS="gcc/fortran libgfortran"
JAVA_DIRS="gcc/java libjava libffi fastjar zlib boehm-gc"
OBJECTIVEC_DIRS="gcc/objc libobjc"
TESTSUITE_DIRS="gcc/testsuite"
FINAL=0
SNAPSHOT=0
LOCAL=0
MODE_GZIP=0
MODE_DIFFS=0
MODE_SOURCES=0
MODE_TARFILES=0
MODE_UPLOAD=0
FILE_LIST=""
BZIP2="${BZIP2:-bzip2}"
CVS="${CVS:-cvs -f -Q -z9}"
DIFF="${DIFF:-diff -Nrcpad}"
ENV="${ENV:-env}"
GZIP="${GZIP:-gzip --best}"
SCP="${SCP:-scp -p}"
SSH="${SSH:-ssh}"
TAR="${TAR:-tar}"
while getopts "d:fr:u:t:p:s:l" ARG; do
case $ARG in
d) DESTINATION="${OPTARG}";;
r) RELEASE="${OPTARG}";;
t) TAG="${OPTARG}";;
u) CVS_USERNAME="${OPTARG}";;
f) FINAL=1;;
s) SNAPSHOT=1
BRANCH=${OPTARG%:*}
CVSBRANCH=${OPTARG ;;
l) LOCAL=1
SCP=cp
PATH=~:/usr/local/bin:$PATH;;
p) OLD_TARS="${OLD_TARS} ${OPTARG}"
if [ ! -f ${OPTARG} ]; then
error "-p argument must name a tarball"
fi;;
\?) usage;;
esac
done
shift `expr ${OPTIND} - 1`
while [ $ case $1 in
diffs) MODE_DIFFS=1;;
gzip) MODE_GZIP=1;;
sources) MODE_SOURCES=1;;
tarfiles) MODE_TARFILES=1;;
upload) MODE_UPLOAD=1;;
all) MODE_SOURCES=1; MODE_TARFILES=1; MODE_DIFFS=1; MODE_UPLOAD=1;
if [ $SNAPSHOT -ne 1 ]; then
MODE_GZIP=1;
fi
;;
*) error "Unknown mode $1";;
esac
shift
done
if [ ${LOCAL} -eq 0 ] && [ -z ${CVS_USERNAME} ]; then
error "No username specified"
fi
if [ ! -d ${DESTINATION} ]; then
error "\`${DESTINATION}' is not a directory"
fi
if [ $SNAPSHOT -eq 0 ]; then
if [ -z ${RELEASE} ]; then
error "No release number specified"
fi
RELEASE_MAJOR=`echo $RELEASE | awk --assign FS=. '{ print $1; }'`
RELEASE_MINOR=`echo $RELEASE | awk --assign FS=. '{ print $2; }'`
RELEASE_REVISION=`echo $RELEASE | awk --assign FS=. '{ print $3; }'`
if [ -z "${RELEASE_MAJOR}" ] || [ -z "${RELEASE_MINOR}" ]; then
error "Release number \`${RELEASE}' is invalid"
fi
if [ -z "${RELEASE_REVISION}" ]; then
RELEASE="${RELEASE_MAJOR}.${RELEASE_MINOR}"
else
RELEASE="${RELEASE_MAJOR}.${RELEASE_MINOR}.${RELEASE_REVISION}"
fi
CVSBRANCH="gcc-${RELEASE_MAJOR}_${RELEASE_MINOR}-branch"
if [ ${FINAL} -ne 1 ]; then
RELEASE="${RELEASE}-${DATE}"
FTP_PATH="${FTP_PATH}/prerelease-${RELEASE}/"
else
FTP_PATH="${FTP_PATH}/releases/gcc-${RELEASE}/"
fi
else
RELEASE=${BRANCH}-${DATE}
FTP_PATH="${FTP_PATH}/snapshots/${RELEASE}"
if [ ${CVSBRANCH} != "HEAD" ]; then
TAG=gcc-ss-`echo ${RELEASE} | tr '.' '_'`
fi
if [ $MODE_DIFFS -ne 0 ] && [ $LOCAL -ne 0 ] && [ -z "${OLD_TARS}" ]; then
LAST_DATE=`cat ~/.snapshot_date-${BRANCH}`
OLD_TARS=${SNAPSHOTS_DIR}/${BRANCH}-${LAST_DATE}/gcc-${BRANCH}-${LAST_DATE}.tar.bz2
fi
fi
WORKING_DIRECTORY="${DESTINATION}/gcc-${RELEASE}"
SOURCE_DIRECTORY="${WORKING_DIRECTORY}/gcc-${RELEASE}"
ADA_DIRS=`adjust_dirs ${ADA_DIRS}`
CPLUSPLUS_DIRS=`adjust_dirs ${CPLUSPLUS_DIRS}`
FORTRAN_DIRS=`adjust_dirs ${FORTRAN_DIRS}`
FORTRAN95_DIRS=`adjust_dirs ${FORTRAN95_DIRS}`
JAVA_DIRS=`adjust_dirs ${JAVA_DIRS}`
OBJECTIVEC_DIRS=`adjust_dirs ${OBJECTIVEC_DIRS}`
TESTSUITE_DIRS=`adjust_dirs ${TESTSUITE_DIRS}`
if [ $LOCAL -eq 0 ]; then
CVSROOT=":${CVS_PROTOCOL}:${CVS_USERNAME}@"
CVSROOT="${CVSROOT}${CVS_SERVER}:${CVS_REPOSITORY}"
else
CVSROOT="${CVS_REPOSITORY}"
fi
export CVSROOT
TZ="UTC0"
export TZ
if [ $MODE_SOURCES -ne 0 ]; then
build_sources
fi
if [ $MODE_TARFILES -ne 0 ]; then
build_tarfiles
fi
if [ $MODE_DIFFS -ne 0 ]; then
if [ -n "$OLD_TARS" ]; then
for old_tar in $OLD_TARS; do
build_diffs $old_tar
done
fi
fi
if [ $MODE_GZIP -ne 0 ]; then
build_gzip
fi
if [ $MODE_UPLOAD -ne 0 ]; then
upload_files
if [ $SNAPSHOT -ne 0 ] && [ $LOCAL -ne 0 ]; then
announce_snapshot
changedir ~
echo $DATE > .snapshot_date-${BRANCH}
rm -rf ${WORKING_DIRECTORY}
fi
fi