#!/bin/bash # # This script prepares a Windows binary distribution of wimlib. set -e -u SCRIPTNAME="$0" TOPDIR=$(dirname "$(dirname "$(realpath "$0")")") cd "$TOPDIR" # Top-level directory of the git repo MSYSTEM=${MSYSTEM:-} if [ -z "$MSYSTEM" ]; then ARCH=x86_64 else case "$MSYSTEM" in MINGW32) ARCH=i686 CC_PKG=mingw-w64-i686-gcc ;; MINGW64) ARCH=x86_64 CC_PKG=mingw-w64-x86_64-gcc ;; CLANG32) ARCH=i686 CC_PKG=mingw-w64-clang-i686-clang ;; CLANG64) ARCH=x86_64 CC_PKG=mingw-w64-clang-x86_64-clang ;; CLANGARM64) ARCH=aarch64 CC_PKG=mingw-w64-clang-aarch64-clang ;; *) echo 1>&2 "Unsupported MSYS2 environment: $MSYSTEM. This script supports" echo 1>&2 "MINGW32, MINGW64, CLANG32, CLANG64, and CLANGARM64." echo 1>&2 "See https://www.msys2.org/docs/environments/" exit 1 esac fi INCLUDE_DOCS=false INSTALL_MSYS2_PACKAGES=false SKIP_CONFIGURE=false ZIP=false longopts="help" longopts+=",arch:" longopts+=",include-docs" longopts+=",install-msys2-packages" longopts+=",skip-configure" longopts+=",zip" usage() { cat << EOF Usage: $SCRIPTNAME [OPTION]... [EXTRA_CONFIGURE_ARG]... Options: --arch=ARCH Specify the CPU architecture. This is unnecessary when using MSYS2. --include-docs Build and install the PDF manual pages. --install-msys2-packages Install the MSYS2 packages needed to build wimlib. You can omit this if you have already done this for the same MSYS2 environment. --skip-configure Skip running the configure script again. You can use this to save time in incremental builds if you are sure you didn't change any options. --zip Zip the output files up into a zip file. EOF } if ! options=$(getopt -o "" -l "$longopts" -- "$@"); then usage 1>&2 exit 1 fi eval set -- "$options" while true; do case "$1" in --help) usage exit 0 ;; --arch) ARCH=$2 shift ;; --include-docs) INCLUDE_DOCS=true ;; --install-msys2-packages) if [ -z "$MSYSTEM" ]; then echo 1>&2 "--install-msys2-packages is not allowed outside MSYS2." exit 1 fi INSTALL_MSYS2_PACKAGES=true ;; --skip-configure) SKIP_CONFIGURE=true ;; --zip) ZIP=true ;; --) shift break ;; *) echo 1>&2 "Invalid option '$1'" usage 1>&2 exit 1 ;; esac shift done EXTRA_CONFIGURE_ARGS=("$@") case "$ARCH" in i686|x86_64|aarch64) ;; *) echo 1>&2 "Unknown ARCH: $ARCH. Please specify a supported architecture with --arch" exit 1 ;; esac VERSION=$(tools/get-version-number) DESTDIR=wimlib-${VERSION}-windows-${ARCH}-bin ZIPFILE=$DESTDIR.zip MAKE="make -j$(getconf _NPROCESSORS_ONLN)" rm -rf "$DESTDIR" "$ZIPFILE" mkdir "$DESTDIR" # Install the required MSYS2 packages if requested. if $INSTALL_MSYS2_PACKAGES; then echo "Installing the MSYS2 $MSYSTEM packages needed to build wimlib..." pacman -Syu --noconfirm --needed \ autoconf \ automake \ git \ libtool \ make \ "$CC_PKG" \ pkgconf echo "Done installing the MSYS2 $MSYSTEM packages needed to build wimlib." fi # Bootstrap the repository if not already done. if [ ! -e configure ]; then echo "Bootstrapping the wimlib repository..." ./bootstrap fi # Configure wimlib. if ! [ -e config.log ] || ! $SKIP_CONFIGURE; then echo "Configuring wimlib..." configure_args=("--host=${ARCH}-w64-mingw32") configure_args+=("--disable-static") # -static-libgcc is needed with gcc. It should go in the CFLAGS, but # libtool strips it, so it must go directly in CC instead. See # http://www.gnu.org/software/libtool/manual/libtool.html#Stripped-link-flags if "${ARCH}-w64-mingw32-cc" --version | grep -q '(GCC)'; then configure_args+=("CC=${ARCH}-w64-mingw32-cc -static-libgcc") fi configure_args+=("${EXTRA_CONFIGURE_ARGS[@]}") ./configure "${configure_args[@]}" $MAKE clean fi echo "Building wimlib..." $MAKE echo "Installing binaries..." cp .libs/*.{dll,exe} "$DESTDIR" strip "$DESTDIR"/*.{dll,exe} echo "Installing NEWS, README, and licenses..." cp NEWS README* COPYING* "$DESTDIR" sed -n '/^#/q; s/^[\/\* ]*//; p' src/divsufsort.c > "$DESTDIR"/COPYING.libdivsufsort-lite if ! grep -q 'Copyright' "$DESTDIR"/COPYING.libdivsufsort-lite; then echo 1>&2 "ERROR: failed to extract libdivsufsort-lite license text" exit 1 fi cd "$DESTDIR" for fil in NEWS README* COPYING*; do sed < "$fil" > "${fil}".txt -e 's/$/\r/g' rm "$fil" done cd .. IMAGEX_CMDS=() for cmd in ./doc/man1/wim*.1; do cmd=${cmd##*/} cmd=${cmd%.1} case "$cmd" in wimlib-imagex|wimmount|wimmountrw|wimunmount) ;; *) IMAGEX_CMDS+=("$cmd") ;; esac done function gen_pdf_from_man_page() { local cmd=$1 local pdf=${DESTDIR}/doc/${cmd}.pdf echo "Generating $pdf" MANPATH="./doc" man -t "$cmd" | ps2pdf - "$pdf" } if $INCLUDE_DOCS; then echo "Installing manual pages..." mkdir "$DESTDIR"/doc for cmd in "${IMAGEX_CMDS[@]}"; do gen_pdf_from_man_page "$cmd" done gen_pdf_from_man_page wimlib-imagex fi echo "Installing wim*.cmd files..." for cmd in "${IMAGEX_CMDS[@]}"; do sed 's/$/\r/g' > "${DESTDIR}/${cmd}.cmd" <<- EOF @echo off "%~dp0\\wimlib-imagex" ${cmd#wim} %* EOF chmod +x "${DESTDIR}/${cmd}.cmd" done echo "Installing development files..." mkdir "$DESTDIR"/devel cp .libs/libwim.dll.a "$DESTDIR"/devel/libwim.lib cp include/wimlib.h "$DESTDIR"/devel/ if $ZIP; then echo "Creating zip file..." cd "$DESTDIR" 7z -mx9 a ../"$ZIPFILE" . > /dev/null cd .. echo "Success! Output is in $ZIPFILE" else echo "Success! Output is in $DESTDIR" fi