1 #!/usr/bin/env bash 2 # Copyright (C) 1990-2024 Free Software Foundation 3 # 4 # This file is free software; you can redistribute it and/or modify 5 # it under the terms of the GNU General Public License as published by 6 # the Free Software Foundation; either version 3 of the License, or 7 # (at your option) any later version. 8 # 9 # This program is distributed in the hope that it will be useful, 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 # GNU General Public License for more details. 13 # 14 # You should have received a copy of the GNU General Public License 15 # along with this program. If not, see <http://www.gnu.org/licenses/>. 16 # 17 18 # This script creates release packages for gdb, binutils, and other 19 # packages which live in src. It used to be implemented as the src-release 20 # Makefile and prior to that was part of the top level Makefile, but that 21 # turned out to be very messy and hard to maintain. 22 23 set -e 24 25 BZIPPROG=bzip2 26 GZIPPROG=gzip 27 LZIPPROG=lzip 28 XZPROG=xz 29 ZSTDPROG=zstd 30 SHA256PROG=sha256sum 31 MAKE=make 32 CC=gcc 33 CXX=g++ 34 release_date= 35 36 # Default to avoid splitting info files by setting the threshold high. 37 MAKEINFOFLAGS=--split-size=5000000 38 39 # 40 # Support for building net releases 41 42 # Files in root used in any net release. 43 DEVO_SUPPORT="ar-lib ChangeLog compile config config-ml.in config.guess \ 44 config.rpath config.sub configure configure.ac COPYING COPYING.LIB \ 45 COPYING3 COPYING3.LIB depcomp install-sh libtool.m4 ltgcc.m4 \ 46 ltmain.sh ltoptions.m4 ltsugar.m4 ltversion.m4 lt~obsolete.m4 \ 47 MAINTAINERS Makefile.def Makefile.in Makefile.tpl missing mkdep \ 48 mkinstalldirs move-if-change README README-maintainer-mode \ 49 SECURITY.txt src-release.sh symlink-tree test-driver ylwrap \ 50 multilib.am ChangeLog.git" 51 52 # Files in devo/etc used in any net release. 53 ETC_SUPPORT="ChangeLog Makefile.am Makefile.in aclocal.m4 add-log.el \ 54 add-log.vi configbuild.* configdev.* configure configure.ac \ 55 configure.in configure.info* configure.texi fdl.texi gnu-oids.texi \ 56 make-stds.texi standards.info* standards.texi texi2pod.pl \ 57 update-copyright.py" 58 59 # Get the version number of a given tool 60 getver() 61 { 62 tool=$1 63 if grep 'AC_INIT.*BFD_VERSION' $tool/configure.ac >/dev/null 2>&1; then 64 bfd/configure --version | sed -n -e '1s,.* ,,p' 65 elif test -f $tool/common/create-version.sh; then 66 $tool/common/create-version.sh $tool 'dummy-host' 'dummy-target' VER.tmp 67 cat VER.tmp | grep 'version\[\]' | sed 's/.*"\([^"]*\)".*/\1/' | sed 's/-git$//' 68 rm -f VER.tmp 69 elif test $tool = "gdb"; then 70 ./gdbsupport/create-version.sh $tool 'dummy-host' 'dummy-target' VER.tmp 71 cat VER.tmp | grep 'version\[\]' | sed 's/.*"\([^"]*\)".*/\1/' | sed 's/-git$//' 72 rm -f VER.tmp 73 elif test -f $tool/version.in; then 74 head -n 1 $tool/version.in 75 else 76 echo VERSION 77 fi 78 } 79 80 clean_sources() 81 { 82 # Check that neither staged nor unstaged changes of any tracked file remains. 83 if [ -n "$(git status --porcelain -uno)" ]; then 84 echo "There are uncommitted changes. Please commit or stash them." 85 exit 1 86 fi 87 88 echo "==> Cleaning sources." 89 90 # Remove all untracked files. 91 git clean -fdx 92 93 # Umask for any new file created by this script. 94 umask 0022 95 96 # Fix permissions of all tracked files and directories according to the previously set umask. 97 echo "==> Fixing permissions." 98 permreg=$(printf "%o" $((0666 & ~$(umask)))) 99 permexe=$(printf "%o" $((0777 & ~$(umask)))) 100 git ls-tree -rt --format "objectmode=%(objectmode) path=%(path)" HEAD | while read -r objectprop; do 101 eval $objectprop 102 case $objectmode in 103 100644) 104 # regular file 105 chmod $permreg $path 106 ;; 107 100755|040000) 108 # executable file or directory 109 chmod $permexe $path 110 ;; 111 120000) 112 # symlink, do nothing, always lrwxrwxrwx. 113 ;; 114 160000) 115 # submodule, currently do nothing 116 ;; 117 *) 118 # unlikely, might be a future version of Git 119 echo unsupported object at $path 120 exit 1 121 ;; 122 esac 123 done 124 } 125 126 # Setup build directory for building release tarball 127 do_proto_toplev() 128 { 129 package=$1 130 ver=$2 131 tool=$3 132 support_files=$4 133 134 clean_sources 135 136 echo "==> Making $package-$ver/" 137 # Take out texinfo from a few places. 138 sed -e '/^all\.normal: /s/\all-texinfo //' \ 139 -e '/^ install-texinfo /d' \ 140 <Makefile.in >tmp 141 mv -f tmp Makefile.in 142 # configure. --enable-gold is needed to ensure .c/.h from .y are 143 # built in the gold dir. The disables speed the build a little. 144 enables= 145 disables= 146 for dir in binutils gas gdb gold gprof gprofng libsframe ld libctf libdecnumber readline sim; do 147 case " $tool $support_files " in 148 *" $dir "*) enables="$enables --enable-$dir" ;; 149 *) disables="$disables --disable-$dir" ;; 150 esac 151 done 152 echo "==> configure --target=i386-pc-linux-gnu $disables $enables" 153 ./configure --target=i386-pc-linux-gnu $disables $enables 154 $MAKE configure-host configure-target \ 155 ALL_GCC="" ALL_GCC_C="" ALL_GCC_CXX="" \ 156 CC_FOR_TARGET="$CC" CXX_FOR_TARGET="$CXX" 157 # Make links, and run "make diststuff" or "make info" when needed. 158 rm -rf proto-toplev 159 mkdir proto-toplev 160 dirs="$DEVO_SUPPORT $support_files $tool" 161 for d in $dirs ; do 162 if [ -d $d ]; then 163 if [ ! -f $d/Makefile ] ; then 164 true 165 elif grep '^diststuff:' $d/Makefile >/dev/null ; then 166 (cd $d ; $MAKE MAKEINFOFLAGS="$MAKEINFOFLAGS" diststuff) \ 167 || exit 1 168 elif grep '^info:' $d/Makefile >/dev/null ; then 169 (cd $d ; $MAKE MAKEINFOFLAGS="$MAKEINFOFLAGS" info) \ 170 || exit 1 171 fi 172 if [ -d $d/proto-$d.dir ]; then 173 ln -s ../$d/proto-$d.dir proto-toplev/$d 174 else 175 ln -s ../$d proto-toplev/$d 176 fi 177 else 178 if (echo x$d | grep / >/dev/null); then 179 mkdir -p proto-toplev/`dirname $d` 180 x=`dirname $d` 181 ln -s ../`echo $x/ | sed -e 's,[^/]*/,../,g'`$d proto-toplev/$d 182 else 183 ln -s ../$d proto-toplev/$d 184 fi 185 fi 186 done 187 (cd etc; $MAKE MAKEINFOFLAGS="$MAKEINFOFLAGS" info) 188 $MAKE distclean 189 mkdir proto-toplev/etc 190 (cd proto-toplev/etc; 191 for i in $ETC_SUPPORT; do 192 ln -s ../../etc/$i . 193 done) 194 # 195 # Take out texinfo from configurable dirs 196 rm proto-toplev/configure.ac 197 sed -e '/^host_tools=/s/texinfo //' \ 198 <configure.ac >proto-toplev/configure.ac 199 # 200 mkdir proto-toplev/texinfo 201 ln -s ../../texinfo/texinfo.tex proto-toplev/texinfo/ 202 if test -r texinfo/util/tex3patch ; then 203 mkdir proto-toplev/texinfo/util && \ 204 ln -s ../../../texinfo/util/tex3patch proto-toplev/texinfo/util 205 fi 206 # 207 # Create .gmo files from .po files. 208 for f in `find . -name '*.po' -type f -print`; do 209 msgfmt -o `echo $f | sed -e 's/\.po$/.gmo/'` $f 210 done 211 # 212 rm -f $package-$ver 213 ln -s proto-toplev $package-$ver 214 } 215 216 CVS_NAMES='-name CVS -o -name .cvsignore' 217 218 # Add a sha256sum to the built tarball 219 do_sha256sum() 220 { 221 echo "==> Adding sha256 checksum to top-level directory" 222 (cd proto-toplev && find * -follow \( $CVS_NAMES \) -prune \ 223 -o -type f -print \ 224 | xargs $SHA256PROG > ../sha256.new) 225 rm -f proto-toplev/sha256.sum 226 mv sha256.new proto-toplev/sha256.sum 227 } 228 229 # Build the release tarball 230 do_tar() 231 { 232 package=$1 233 ver=$2 234 echo "==> Making $package-$ver.tar" 235 rm -f $package-$ver.tar 236 if test x$release_date == "x" ; then 237 find $package-$ver -follow \( $CVS_NAMES \) -prune -o -type f -print \ 238 | tar cTfh - $package-$ver.tar 239 else 240 # Attempt to create a consistent, reproducible tarball using the 241 # specified date. 242 find $package-$ver -follow \( $CVS_NAMES \) -prune -o -type f -print \ 243 | LC_ALL=C sort \ 244 | tar cTfh - $package-$ver.tar \ 245 --mtime=$release_date --group=0 --owner=0 246 fi 247 } 248 249 # Compress the output with bzip2 250 do_bz2() 251 { 252 package=$1 253 ver=$2 254 echo "==> Bzipping $package-$ver.tar.bz2" 255 rm -f $package-$ver.tar.bz2 256 $BZIPPROG -k -v -9 $package-$ver.tar 257 } 258 259 # Compress the output with gzip 260 do_gz() 261 { 262 package=$1 263 ver=$2 264 echo "==> Gzipping $package-$ver.tar.gz" 265 rm -f $package-$ver.tar.gz 266 $GZIPPROG -k -v -9 $package-$ver.tar 267 } 268 269 # Compress the output with lzip 270 do_lz() 271 { 272 package=$1 273 ver=$2 274 echo "==> Lzipping $package-$ver.tar.lz" 275 rm -f $package-$ver.tar.lz 276 $LZIPPROG -k -v -9 $package-$ver.tar 277 } 278 279 # Compress the output with xz 280 do_xz() 281 { 282 package=$1 283 ver=$2 284 echo "==> Xzipping $package-$ver.tar.xz" 285 rm -f $package-$ver.tar.xz 286 $XZPROG -k -v -9 -T0 $package-$ver.tar 287 } 288 289 # Compress the output with zstd 290 do_zstd() 291 { 292 package=$1 293 ver=$2 294 echo "==> Zzipping $package-$ver.tar.zst" 295 rm -f $package-$ver.tar.zst 296 $ZSTDPROG -k -v -19 -T0 $package-$ver.tar 297 } 298 299 # Compress the output with all selected compresion methods 300 do_compress() 301 { 302 package=$1 303 ver=$2 304 compressors=$3 305 for comp in $compressors; do 306 case $comp in 307 bz2) 308 do_bz2 $package $ver;; 309 gz) 310 do_gz $package $ver;; 311 lz) 312 do_lz $package $ver;; 313 xz) 314 do_xz $package $ver;; 315 zstd) 316 do_zstd $package $ver;; 317 *) 318 echo "Unknown compression method: $comp" && exit 1;; 319 esac 320 done 321 } 322 323 # Add djunpack.bat the tarball 324 do_djunpack() 325 { 326 package=$1 327 ver=$2 328 echo "==> Adding updated djunpack.bat to top-level directory" 329 echo - 's /gdb-[0-9\.]*/$package-'"$ver"'/' 330 sed < djunpack.bat > djunpack.new \ 331 -e 's/gdb-[0-9][0-9\.]*/$package-'"$ver"'/' 332 rm -f proto-toplev/djunpack.bat 333 mv djunpack.new proto-toplev/djunpack.bat 334 } 335 336 # Create a release package, tar it and compress it 337 tar_compress() 338 { 339 package=$1 340 tool=$2 341 support_files=$3 342 compressors=$4 343 verdir=${5:-$tool} 344 ver=$(getver $verdir) 345 do_proto_toplev $package $ver $tool "$support_files" 346 do_sha256sum 347 do_tar $package $ver 348 do_compress $package $ver "$compressors" 349 } 350 351 # Create a gdb release package, tar it and compress it 352 gdb_tar_compress() 353 { 354 package=$1 355 tool=$2 356 support_files=$3 357 compressors=$4 358 ver=$(getver $tool) 359 do_proto_toplev $package $ver $tool "$support_files" 360 do_sha256sum 361 do_djunpack $package $ver 362 do_tar $package $ver 363 do_compress $package $ver "$compressors" 364 } 365 366 GAS_DIRS="bfd gas include libiberty opcodes setup.com makefile.vms zlib" 367 gas_release() 368 { 369 compressors=$1 370 package=gas 371 tool=gas 372 tar_compress $package $tool "$GAS_DIRS" "$compressors" 373 } 374 375 BINUTILS_DIRS="$GAS_DIRS binutils cpu gprof gprofng ld libsframe libctf" 376 binutils_release() 377 { 378 compressors=$1 379 package=binutils 380 tool=binutils 381 tar_compress $package $tool "$BINUTILS_DIRS" "$compressors" 382 } 383 384 BINUTILS_GOLD_DIRS="$BINUTILS_DIRS elfcpp gold" 385 binutils_gold_release() 386 { 387 compressors=$1 388 package=binutils-with-gold 389 tool=binutils 390 tar_compress $package $tool "$BINUTILS_GOLD_DIRS" "$compressors" 391 } 392 393 GOLD_DIRS="gold elfcpp include" 394 # These extra directories whilst not directly related to 395 # gold are needed in order to be able to build and test it. 396 GOLD_DIRS="$GOLD_DIRS bfd libsframe libctf libiberty binutils opcodes gas" 397 gold_release() 398 { 399 compressors=$1 400 package=gold 401 tool=binutils 402 tar_compress $package $tool "$GOLD_DIRS" "$compressors" 403 } 404 405 GDB_SUPPORT_DIRS="libsframe bfd include libiberty libctf opcodes readline sim libdecnumber cpu zlib contrib gnulib gdbsupport gdbserver libbacktrace" 406 gdb_release() 407 { 408 compressors=$1 409 package=gdb 410 tool=gdb 411 gdb_tar_compress $package $tool "$GDB_SUPPORT_DIRS" "$compressors" 412 } 413 414 # Corresponding to the CVS "sim" module. 415 SIM_SUPPORT_DIRS="libsframe bfd opcodes libiberty libctf/swap.h include gdb/version.in gdb/common/create-version.sh makefile.vms zlib gnulib" 416 sim_release() 417 { 418 compressors=$1 419 package=sim 420 tool=sim 421 tar_compress $package $tool "$SIM_SUPPORT_DIRS" "$compressors" gdb 422 } 423 424 usage() 425 { 426 echo "src-release.sh <options> <release>" 427 echo "options:" 428 echo " -b: Compress with bzip2" 429 echo " -g: Compress with gzip" 430 echo " -l: Compress with lzip" 431 echo " -x: Compress with xz" 432 echo " -z: Compress with zstd" 433 echo " -r <date>: Create a reproducible tarball using <date> as the mtime" 434 echo "release:" 435 echo " binutils: All the binutils except gold" 436 echo " binutils_with_gold: All the binutils including gold" 437 echo " gas: Just the assembler" 438 echo " gdb: All of GDB" 439 echo " gold: Just the gold linker" 440 echo " sim: Just the simulator" 441 exit 1 442 } 443 444 build_release() 445 { 446 release=$1 447 compressors=$2 448 case $release in 449 binutils) 450 binutils_release "$compressors";; 451 binutils_with_gold) 452 binutils_gold_release "$compressors";; 453 gas) 454 gas_release "$compressors";; 455 gdb) 456 gdb_release "$compressors";; 457 gold) 458 gold_release "$compressors";; 459 sim) 460 sim_release "$compressors";; 461 *) 462 echo "Unknown release name: $release" && usage;; 463 esac 464 } 465 466 compressors="" 467 468 while getopts ":bglr:xz" opt; do 469 case $opt in 470 b) 471 compressors="$compressors bz2";; 472 g) 473 compressors="$compressors gz";; 474 l) 475 compressors="$compressors lz";; 476 r) 477 release_date=$OPTARG;; 478 x) 479 compressors="$compressors xz";; 480 z) 481 compressors="$compressors zstd";; 482 \?) 483 echo "Invalid option: -$OPTARG" && usage;; 484 esac 485 done 486 shift $((OPTIND -1)) 487 release=$1 488 489 build_release $release "$compressors" 490