#!/bin/sh set -e [ -n "$BASH_VERSION" ] && set -o posix export BUILD_ROOT="${BUILD_ROOT:-$HOME/vbam-build}" export TAR="${TAR:-tar --force-local}" export CURL="${CURL:-curl --insecure}" export PERL_MAKE="${PERL_MAKE:-make}" [ -n "$BUILD_ENV" ] && eval "$BUILD_ENV" BUILD_ENV=$BUILD_ENV$(cat </dev/null; then case "\$CMAKE_REQUIRED_ARGS" in *ccache*) : ;; *) CMAKE_REQUIRED_ARGS="\$CMAKE_REQUIRED_ARGS -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER=\$CC -DCMAKE_CXX_COMPILER=\$CXX" ;; esac fi ;; esac export CPPFLAGS="$CPPFLAGS${CPPFLAGS:+ }-I\$BUILD_ROOT/root/include -DCURL_STATICLIB -DGRAPHITE2_STATIC -DFLOAT_APPROX" export CFLAGS="$CFLAGS${CFLAGS:+ }-fPIC -I\$BUILD_ROOT/root/include -L\$BUILD_ROOT/root/lib -pthread -lm -DCURL_STATICLIB -DGRAPHITE2_STATIC -DFLOAT_APPROX -Ofast -march=core2 -mtune=generic -pipe -Wno-error=implicit-int" export CXXFLAGS="$CXXFLAGS${CXXFLAGS:+ }-fPIC -I\$BUILD_ROOT/root/include -L\$BUILD_ROOT/root/lib -std=gnu++17 -fpermissive -pthread -lm -DCURL_STATICLIB -DGRAPHITE2_STATIC -DFLOAT_APPROX -Ofast -march=core2 -mtune=generic -pipe" export OBJCXXFLAGS="$OBJCXXFLAGS${OBJCXXFLAGS:+ }-fPIC -I\$BUILD_ROOT/root/include -L\$BUILD_ROOT/root/lib -std=gnu++17 -fpermissive -pthread -lm -DCURL_STATICLIB -DGRAPHITE2_STATIC -DFLOAT_APPROX -Ofast -march=core2 -mtune=generic -pipe" export LDFLAGS="$LDFLAGS${LDFLAGS:+ }-fPIC -L\$BUILD_ROOT/root/lib -pthread -lm -Ofast -march=core2 -mtune=generic -pipe" export STRIP="\${STRIP:-strip}" if [ -z "\$OPENMP" ] && echo "\$CC" | grep -Eq gcc; then export CFLAGS="\$CFLAGS -fopenmp" export CXXFLAGS="\$CXXFLAGS -fopenmp" export OBJCXXFLAGS="\$OBJCXXFLAGS -fopenmp" export LDFLAGS="\$LDFLAGS -fopenmp" export OPENMP=1 fi export CMAKE_PREFIX_PATH="\${CMAKE_PREFIX_PATH:-\$BUILD_ROOT/root}" export PKG_CONFIG_PATH="\$BUILD_ROOT/root/lib/pkgconfig:\$BUILD_ROOT/root/share/pkgconfig" export LIBRARY_PATH="\$BUILD_ROOT/root/lib" export LD_LIBRARY_PATH="\$BUILD_ROOT/root/lib" export PERL_MM_USE_DEFAULT=1 export PERL_EXTUTILS_AUTOINSTALL="--defaultdeps" export OPENSSL_ROOT="\$BUILD_ROOT/root" export PERL_MB_OPT="--install_base \$BUILD_ROOT/root/perl5" export PERL_MM_OPT="INSTALL_BASE=\"\$BUILD_ROOT/root/perl5\" CCFLAGS=\"\$CFLAGS\" LDDFLAGS=\"\$LDFLAGS\"" export PERL5LIB="\$BUILD_ROOT/root/perl5/lib/perl5" export PERL_LOCAL_LIB_ROOT="\$BUILD_ROOT/root/perl5" case "\$PATH" in *"\$BUILD_ROOT"*) ;; *) export PATH="\$BUILD_ROOT/root/bin:\$BUILD_ROOT/root/perl5/bin:\$PATH" ;; esac export MANPATH="\$BUILD_ROOT/root/man:\$BUILD_ROOT/root/share/man:/usr/share/man:/usr/local/share/man" export XML_CATALOG_FILES="\$(cygpath -m "\$BUILD_ROOT/root/etc/xml/catalog.xml" 2>/dev/null)" export FORMAT_DIR="\$BUILD_ROOT/root/share/xmlto/format" export XDG_DATA_DIRS="\$BUILD_ROOT/root/share" export FONTCONFIG_PATH="\$BUILD_ROOT/root/etc/fonts" export BISON_PKGDATADIR="\$BUILD_ROOT/root/share/bison" export SWIG_LIB="\$(echo \$BUILD_ROOT/root/share/swig/* 2>/dev/null)" EOF ) export BUILD_ENV ORIG_PATH=$PATH PRE_BUILD_DISTS="$PRE_BUILD_DISTS bzip2 xz unzip" DISTS=$DISTS' bzip2 ftp://sourceware.org/pub/bzip2/bzip2-1.0.8.tar.gz lib/libbz2.a xz https://tukaani.org/xz/xz-5.2.6.tar.gz lib/liblzma.a unzip https://downloads.sourceforge.net/project/infozip/UnZip%206.x%20%28latest%29/UnZip%206.0/unzip60.tar.gz bin/unzip zlib-ng https://github.com/zlib-ng/zlib-ng/archive/ce01b1e41da298334f8214389cc9369540a7560f.tar.gz lib/libz.a zip https://downloads.sourceforge.net/project/infozip/Zip%203.x%20%28latest%29/3.0/zip30.tar.gz bin/zip openssl https://www.openssl.org/source/openssl-1.1.1w.tar.gz lib/libssl.a curl https://github.com/curl/curl/releases/download/curl-8_4_0/curl-8.4.0.tar.bz2 lib/libcurl.a cmake https://github.com/Kitware/CMake/releases/download/v3.24.1/cmake-3.24.1.tar.gz bin/cmake zstd https://github.com/facebook/zstd/releases/download/v1.5.2/zstd-1.5.2.tar.gz lib/libzstd.a hiredis https://github.com/redis/hiredis/archive/refs/tags/v1.0.2.tar.gz lib/libhiredis.a ccache https://github.com/ccache/ccache/releases/download/v4.6.3/ccache-4.6.3.tar.xz bin/ccache m4 http://ftp.gnu.org/gnu/m4/m4-1.4.19.tar.xz bin/m4 autoconf https://ftp.gnu.org/gnu/autoconf/autoconf-2.71.tar.xz bin/autoconf autoconf-archive http://gnu.askapache.com/autoconf-archive/autoconf-archive-2022.09.03.tar.xz share/aclocal/ax_check_gl.m4 automake https://ftp.gnu.org/gnu/automake/automake-1.16.5.tar.xz bin/automake libtool https://ftp.gnu.org/gnu/libtool/libtool-2.4.7.tar.xz bin/libtool xorg-macros https://www.x.org/archive//individual/util/util-macros-1.19.1.tar.bz2 share/pkgconfig/xorg-macros.pc help2man https://ftp.gnu.org/gnu/help2man/help2man-1.49.2.tar.xz bin/help2man libiconv https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.17.tar.gz lib/libiconv.a gettext http://ftp.gnu.org/pub/gnu/gettext/gettext-0.22.5.tar.xz lib/libintl.a getopt http://frodo.looijaard.name/system/files/software/getopt/getopt-1.1.6.tar.gz bin/getopt gsed http://ftp.gnu.org/gnu/sed/sed-4.9.tar.xz bin/sed bison https://ftp.gnu.org/gnu/bison/bison-3.8.2.tar.xz bin/bison texinfo http://ftp.gnu.org/gnu/texinfo/texinfo-6.8.tar.xz bin/makeinfo flex-2.6.3 https://github.com/westes/flex/releases/download/v2.6.3/flex-2.6.3.tar.gz bin/flex flex https://github.com/westes/flex/archive/ea6493d9b6f1915ba096160df666637a6e1b3f20.tar.gz bin/flex xmlto https://releases.pagure.org/xmlto/xmlto-0.0.28.tar.bz2 bin/xmlto gperf http://ftp.gnu.org/pub/gnu/gperf/gperf-3.1.tar.gz bin/gperf libicu https://github.com/unicode-org/icu/releases/download/release-71-1/icu4c-71_1-src.tgz lib/libicud*t*.a pkgconf https://github.com/pkgconf/pkgconf/archive/refs/tags/pkgconf-1.9.3.tar.gz bin/pkgconf nasm https://www.nasm.us/pub/nasm/releasebuilds/2.15.05/nasm-2.15.05.tar.xz bin/nasm yasm http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz bin/yasm pcre https://downloads.sourceforge.net/project/pcre/pcre/8.45/pcre-8.45.tar.bz2 lib/libpcre.a pcre2 https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.40/pcre2-10.40.tar.bz2 lib/libpcre2-posix.a libffi https://github.com/libffi/libffi/releases/download/v3.4.2/libffi-3.4.2.tar.gz lib/libffi.a c2man https://github.com/fribidi/c2man/archive/577ed4095383ef5284225d45709e6b5f0598a064.tar.gz bin/c2man libxml2 https://gitlab.gnome.org/GNOME/libxml2/-/archive/v2.10.2/libxml2-v2.10.2.tar.bz2 lib/libxml2.a libxslt https://gitlab.gnome.org/GNOME/libxslt/-/archive/v1.1.37/libxslt-v1.1.37.tar.bz2 lib/libxslt.a XML-NamespaceSupport https://cpan.metacpan.org/authors/id/P/PE/PERIGRIN/XML-NamespaceSupport-1.12.tar.gz perl5/lib/perl5/XML/NamespaceSupport.pm XML-SAX-Base https://cpan.metacpan.org/authors/id/G/GR/GRANTM/XML-SAX-Base-1.09.tar.gz perl5/lib/perl5/XML/SAX/Base.pm XML-SAX https://cpan.metacpan.org/authors/id/G/GR/GRANTM/XML-SAX-1.02.tar.gz perl5/lib/perl5/XML/SAX.pm docbook2x https://downloads.sourceforge.net/project/docbook2x/docbook2x/0.8.8/docbook2X-0.8.8.tar.gz bin/docbook2man expat https://github.com/libexpat/libexpat/releases/download/R_2_4_8/expat-2.4.8.tar.xz lib/libexpat.a libpng https://download.sourceforge.net/libpng/libpng-1.6.37.tar.xz lib/libpng.a libjpeg-turbo https://github.com/libjpeg-turbo/libjpeg-turbo/archive/2.1.4.tar.gz lib/libjpeg.a libtiff https://download.osgeo.org/libtiff/tiff-4.4.0.tar.xz lib/libtiff.a # libcroco http://ftp.gnome.org/pub/gnome/sources/libcroco/0.6/libcroco-0.6.13.tar.xz lib/libcroco-0.6.a libuuid https://downloads.sourceforge.net/project/libuuid/libuuid-1.0.3.tar.gz lib/libuuid.a freetype http://download.savannah.gnu.org/releases/freetype/freetype-2.12.1.tar.xz lib/libfreetype.a fontconfig https://freedesktop.org/software/fontconfig/release/fontconfig-2.13.1.tar.bz2 lib/libfontconfig.a libgd https://github.com/libgd/libgd/releases/download/gd-2.3.3/libgd-2.3.3.tar.xz lib/libgd.a dejavu http://sourceforge.net/projects/dejavu/files/dejavu/2.37/dejavu-fonts-ttf-2.37.tar.bz2 share/fonts/dejavu/DejaVuSansMono.ttf liberation https://github.com/liberationfonts/liberation-fonts/files/7261482/liberation-fonts-ttf-2.1.5.tar.gz share/fonts/liberation/LiberationMono-Regular.ttf urw https://github.com/ArtifexSoftware/urw-base35-fonts/archive/refs/tags/20200910.tar.gz share/fonts/urw/URWBookman-Light.ttf graphviz https://gitlab.com/api/v4/projects/4207231/packages/generic/graphviz-releases/5.0.1/graphviz-5.0.1.tar.xz bin/dot_static docbook4.2 http://www.docbook.org/xml/4.2/docbook-xml-4.2.zip share/xml/docbook/schema/dtd/4.2/catalog.xml docbook4.1.2 http://www.docbook.org/xml/4.1.2/docbkx412.zip share/xml/docbook/schema/dtd/4.1.2/catalog.xml docbook4.3 http://www.docbook.org/xml/4.3/docbook-xml-4.3.zip share/xml/docbook/schema/dtd/4.3/catalog.xml docbook4.4 http://www.docbook.org/xml/4.4/docbook-xml-4.4.zip share/xml/docbook/schema/dtd/4.4/catalog.xml docbook4.5 http://www.docbook.org/xml/4.5/docbook-xml-4.5.zip share/xml/docbook/schema/dtd/4.5/catalog.xml docbook5.0.1 http://www.docbook.org/xml/5.0.1/docbook-5.0.1.zip share/xml/docbook/schema/dtd/5.0.1/catalog.xml docbook5.1 https://docbook.org/xml/5.1/docbook-v5.1-os.zip share/xml/docbook/schema/dtd/5.0.1/catalog.xml docbook-xsl https://downloads.sourceforge.net/project/docbook/docbook-xsl/1.79.1/docbook-xsl-1.79.1.tar.bz2 share/xml/docbook/stylesheet/docbook-xsl/catalog.xml docbook-xsl-ns https://downloads.sourceforge.net/project/docbook/docbook-xsl-ns/1.79.1/docbook-xsl-ns-1.79.1.tar.bz2 share/xml/docbook/stylesheet/docbook-xsl-ns/catalog.xml python2 https://www.python.org/ftp/python/2.7.18/Python-2.7.18.tar.xz bin/python python3 https://www.python.org/ftp/python/3.10.6/Python-3.10.6.tar.xz bin/python3 swig https://sourceforge.net/projects/swig/files/swig/swig-4.0.2/swig-4.0.2.tar.gz/download bin/swig doxygen https://www.doxygen.nl/files/doxygen-1.9.5.src.tar.gz bin/doxygen bakefile https://github.com/vslavik/bakefile/archive/7a218d89d860f01d64b558b7e198bb0cbc538511.tar.gz bin/bakefile_gen XML-Parser https://cpan.metacpan.org/authors/id/T/TO/TODDR/XML-Parser-2.46.tar.gz perl5/man/man3/XML*Parser.3* intltool https://launchpad.net/intltool/trunk/0.51.0/+download/intltool-0.51.0.tar.gz bin/intltoolize ninja https://github.com/ninja-build/ninja/archive/v1.11.1.tar.gz bin/ninja glib https://gitlab.gnome.org/GNOME/glib/-/archive/046f70cc0ddd1db310d30b02c692ee1364c41e16/glib-046f70cc0ddd1db310d30b02c692ee1364c41e16.tar.bz2 lib/libglib-2.0.a libgpg-error https://gnupg.org/ftp/gcrypt/libgpg-error/libgpg-error-1.45.tar.bz2 lib/libgpg-error.a libgcrypt https://gnupg.org/ftp/gcrypt/libgcrypt/libgcrypt-1.10.1.tar.bz2 lib/libgcrypt.a libsecret https://gitlab.gnome.org/GNOME/libsecret/-/archive/0.20.5/libsecret-0.20.5.tar.bz2 lib/libsecret-1.a sdl2 https://github.com/libsdl-org/SDL/releases/download/release-2.30.7/SDL2-2.30.7.tar.gz lib/libSDL2.a faudio https://github.com/FNA-XNA/FAudio/archive/refs/tags/24.09.tar.gz lib/libFAudio.a flac https://ftp.osuosl.org/pub/xiph/releases/flac/flac-1.3.4.tar.xz lib/libFLAC.a harfbuzz https://github.com/harfbuzz/harfbuzz/releases/download/10.0.1/harfbuzz-10.0.1.tar.xz lib/libharfbuzz.a sfml https://github.com/SFML/SFML/archive/refs/tags/2.6.1.tar.gz lib/libsfml-system-s.a shared-mime-info https://gitlab.freedesktop.org/xdg/shared-mime-info/-/archive/2.2/shared-mime-info-2.2.tar.bz2 bin/update-mime-database wxwidgets https://github.com/wxWidgets/wxWidgets/releases/download/v3.2.6/wxWidgets-3.2.6.tar.bz2 lib/libwx_baseu-3.*.a ffmpeg http://ffmpeg.org/releases/ffmpeg-7.0.2.tar.xz lib/libavformat.a ' BUILD_FFMPEG=1 FFMPEG_DISTS=' graphite2 xvidcore fribidi libgsm libmodplug libopencore-amrnb opus snappy libsoxr speex libtheora vidstab libvo-amrwbenc mp3lame libass libbluray libvpx libx264 libx265 libxavs libzmq libzvbi ffmpeg ' PROJECT_ARGS="-DDISABLE_MACOS_PACKAGE_MANAGERS=TRUE -DENABLE_ONLINEUPDATES=OFF -DwxWidgets_CONFIG_EXECUTABLE='$BUILD_ROOT/root/bin/wx-config' -DwxWidgets_CONFIG_OPTIONS='--prefix=$BUILD_ROOT/root' -DBUILD_TESTING=NO" : ${PATH_SEP:=':'} export CMAKE_BASE_ARGS="$CMAKE_BASE_ARGS -DBUILD_SHARED_LIBS=NO -DENABLE_SHARED=NO -DCMAKE_PREFIX_PATH:FILEPATH=\"\$CMAKE_PREFIX_PATH\" -DCMAKE_BUILD_TYPE=Release" export CONFIGURE_INSTALL_ARGS="--prefix=/usr --sysconfdir=/etc" export CMAKE_INSTALL_ARGS="-DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_INSTALL_FULL_SYSCONFDIR=/etc" export MESON=meson export MAKE=make export MESON_INSTALL_ARGS="--prefix /usr --sysconfdir /etc" if [ -z "$target_os" ] && [ "$os" = linux ] && [ "$bits" = 64 ]; then export CONFIGURE_INSTALL_ARGS="$CONFIGURE_INSTALL_ARGS --libdir=/usr/lib64" export MESON_INSTALL_ARGS="$MESON_INSTALL_ARGS --libdir /usr/lib64" export CMAKE_INSTALL_ARGS="$CMAKE_INSTALL_ARGS -DCMAKE_INSTALL_RPATH=/usr/lib64 -DCMAKE_INSTALL_LIBDIR=/usr/lib64" fi export CONFIGURE_ARGS="$CONFIGURE_ARGS --disable-shared $CONFIGURE_INSTALL_ARGS" export CMAKE_ARGS="$CMAKE_BASE_ARGS $CMAKE_ARGS $CMAKE_INSTALL_ARGS" export MESON_ARGS="$MESON_BASE_ARGS --buildtype release --default-library static $MESON_INSTALL_ARGS" DIST_PATCHES=$DIST_PATCHES' docbook2x https://gist.githubusercontent.com/rkitover/0b5dcc95a0703a9b0e0e7eb6d325a98e/raw/e256d2fad8d19633ac8abe02a0d1e119063d1fd9/docbook2x.patch graphite2 https://gist.githubusercontent.com/rkitover/e753f41a7f6461ad412c2d076ec24e0f/raw/d0c2b8cccd556e407e15da8a2e739a902bd1a3b5/graphite2-static-cmake-opts.patch python2 https://gist.githubusercontent.com/rkitover/2d9e5baff1f1cc4f2618dee53083bd35/raw/7f33fcf5470a9f1013ac6ae7bb168368a98fe5a0/python-2.7.14-custom-static-openssl.patch https://gist.githubusercontent.com/rkitover/afab7ed3ac7ce1860c43a258571c8ae1/raw/6f5fc90a7acf5f5c3ffda2edf402b28f469a4b3b/python-2.7.14-static-libintl.patch intltool https://gist.githubusercontent.com/rkitover/d638882f52e5d5f8e392cbf6842cd6d0/raw/dcfbe358bbb8b89f88b40a9c3402494552fd33f8/intltool-0.51.0.patch ' DIST_TAR_ARGS="$DIST_TAR_ARGS " DIST_CONFIGURE_TYPES="$DIST_CONFIGURE_TYPES unzip make zip make pkgconf autoreconf_noargs fontconfig autoreconf libgd autoreconf python2 autoreconf python3 autoreconf graphviz autoreconf docbook2x autoreconf libvorbis autoreconf libgpg-error autoreconf wxwidgets autoreconf " DIST_RELOCATION_TYPES="$DIST_RELOCATION_TYPES texinfo aggressive " DIST_PRE_BUILD="$DIST_PRE_BUILD # xz mkdir -p build-aux; touch build-aux/config.rpath; mkdir -p po; touch po/Makefile.in.in; sed -i.bak 's/ po / /g' Makefile.am; getopt sed -i.bak 's/\\\$(LDFLAGS)\\(.*\\)\$/\\1 \$(LDFLAGS)/' Makefile; libicu cd source; # c2man sed -i.bak 's/exit(\\([^)]*\\));/return \\1;/g' Configure # flex-2.6.3 sed -i.bak '/^'\"\$TAB\"'tests \\\\\$/d' Makefile.am; flex mkdir -p build-aux; touch build-aux/config.rpath; mkdir -p po; touch po/Makefile.in.in; sed -i.bak '/po \\\\$/d' Makefile.am; fontconfig sed -i.bak 'd;q' test/Makefile.am; python3 sed -i.bak '/-Wl,-stack_size,/d' configure.ac; bakefile sed -i.bak '/SUBDIRS = doc/d' Makefile.am; unzip rm -f unix/Contents; ln -sf \$(find unix -mindepth 1 -maxdepth 1) .; zip rm -f unix/Contents; ln -sf \$(find unix -mindepth 1 -maxdepth 1) .; gettext sed -i.bak 's/-Wl,--disable-auto-import//' m4/woe32-dll.m4; glib cd subprojects/gvdb; \ curl -sLO 'https://gitlab.gnome.org/GNOME/gvdb/-/archive/89dbdb9ab45721189e195c7e70ed620143d840f7/gvdb-89dbdb9ab45721189e195c7e70ed620143d840f7.tar.bz2'; \ tar --strip-components=1 -jxf gvdb-89dbdb9ab45721189e195c7e70ed620143d840f7.tar.bz2; \ rm gvdb-89dbdb9ab45721189e195c7e70ed620143d840f7.tar.bz2; \ cd ../..; expat sed -i.bak '/doc\\/Makefile/d' configure.ac; \ sed -i.bak '/SUBDIRS/{; s/ doc//; }' Makefile.am; graphviz sed -i.bak 's/ -export-symbols/ -Wl,-export-symbols/g' \$(find . -name Makefile.am); \ putsln '#define __declspec(x)' > declspec.h; xvidcore cd build/generic; \ sed -i.bak '/^all:/{ s/ *\\\$(SHARED_LIB)//; }; \ /^install:/{ s, *\\\$(BUILD_DIR)/\\\$(SHARED_LIB),,; }; \ s/\\\$(INSTALL).*\\\$(SHARED_LIB).*/:/; \ s/\\\$(LN_S).*\\\$(SHARED_LIB).*/:/; \ s/@echo.*\\\$(SHARED_LIB).*/@:/; \ ' Makefile; libx265 cd source; libsoxr rm -rf tests; mkdir tests; touch tests/CMakeLists.txt; libvorbis rm -f autogen.sh; XML-SAX sed -i.bak 's/-MXML::SAX/-Mblib -MXML::SAX/' Makefile.PL; docbook2x sed -i.bak 's/^\\( *SUBDIRS *= *.*\\)doc\\(.*\\)\$/\1\2/' Makefile.am; \ sed -i.bak 's/^\\( *SUBDIRS *= *.*\\)documentation\\(.*\\)\$/\1\2/' xslt/Makefile.am; hiredis sed -i.bak 's/ SHARED / STATIC /' CMakeLists.txt; wxwidgets sed -i.bak 's/^WX_LDFLAGS=.*/WX_LDFLAGS=\$USER_LDFLAGS/' configure.in; " DIST_POST_BUILD="$DIST_POST_BUILD pkgconf ln -sf \"\$BUILD_ROOT/root/bin/pkgconf\" \"\$BUILD_ROOT/root/bin/pkg-config\"; ccache setup_ccache harfbuzz rebuild_dist freetype -Dharfbuzz=enabled; flex-2.6.3 build_dist flex || :; libtool ln -sf \"\$BUILD_ROOT/root/bin/libtoolize\" \"\$BUILD_ROOT/root/bin/glibtoolize\"; glib rebuild_dist gettext --without-included-glib --without-included-libxml; # graphviz (cd \"\$BUILD_ROOT/root/bin\"; path_exists dot_static && ! path_exists dot && ln -sf \"\$BUILD_ROOT/root/bin/dot_static\" ./dot || :); libxml2 mkdir -p \"\$BUILD_ROOT/root/etc/xml\"; \ xmlcatalog --noout --create \"\$(cygpath -m \"\$BUILD_ROOT/root/etc/xml/catalog.xml\")\" || :; python2 python2 -m pip install six; python3 python3 -m pip install six; \ rm \"\$BUILD_ROOT/root/bin/meson\"; \ python3 -m pip install meson; \ rebuild_dist libxml2 --with-python --with-python3; fontconfig mkdir -p \"\$BUILD_ROOT/root/etc/fonts\"; \ touch \"\$BUILD_ROOT/root/etc/fonts/fonts.conf\"; \ sed -i.bak \"s|/usr/share/fonts|\$BUILD_ROOT/root/share/fonts|g\" \"\$BUILD_ROOT/root/etc/fonts/fonts.conf\"; ffmpeg sed -i.bak 's/-lX11/ /g' \$BUILD_ROOT/root/lib/pkgconfig/libavutil.pc " DIST_CONFIGURE_OVERRIDES="$DIST_CONFIGURE_OVERRIDES zlib-ng ./configure --prefix=/usr --static --zlib-compat openssl ./config no-shared --prefix=/usr --openssldir=/etc/ssl cmake ./configure --prefix=/usr --no-qt-gui --parallel=\$NUM_CPUS XML-SAX echo no | PERL_MM_USE_DEFAULT=0 \"\$perl\" Makefile.PL libvpx ./configure --disable-shared --enable-static --prefix=/usr --disable-unit-tests --disable-tools --disable-docs --disable-examples ffmpeg ./configure --disable-shared --enable-static --prefix=/usr --pkg-config-flags=--static --disable-nonfree --enable-fontconfig --enable-gpl --enable-version3 --disable-libass --disable-libbluray --enable-libfreetype --disable-libgsm --disable-libmodplug --disable-libmp3lame --disable-libopencore-amrnb --disable-libopencore-amrwb --disable-libopus --disable-libsnappy --disable-libsoxr --disable-libspeex --disable-libtheora --disable-libvidstab --disable-libvo-amrwbenc --disable-libvorbis --disable-libvpx --disable-libx264 --disable-libx265 --disable-libxavs --disable-libxvid --disable-libzmq --disable-openssl --enable-lzma --extra-cflags='-DMODPLUG_STATIC -DZMQ_STATIC' --extra-cxxflags='-DMODPLUG_STATIC -DZMQ_STATIC' --extra-objcflags='-DMODPLUG_STATIC -DZMQ_STATIC' --extra-libs=-liconv --cc=\"\$CC\" --cxx=\"\$CXX\" " DIST_BUILD_OVERRIDES="$DIST_BUILD_OVERRIDES c2man ./Configure -de -Dprefix=/usr -Dmansrc=/usr/share/man/man1 -Dcc=\"\$CC\"; \ sed -i.bak \"s|/[^ ][^ ]*/libfl[.][^ ]*|-L\$BUILD_ROOT/root/lib -lfl|\" Makefile; \ \$MAKE -j\$NUM_CPUS; \ \$MAKE install bin=\"\$BUILD_ROOT/root/bin\" mansrc=\"\$BUILD_ROOT/root/share/man/man1\" privlib=\"\$BUILD_ROOT/root/lib/c2man\" zstd \$MAKE -j\$NUM_CPUS -C lib install-static DESTDIR=\"\$BUILD_ROOT/root\" LIBDIR=/lib setuptools python bootstrap.py; python easy_install.py . pip easy_install . ninja python configure.py --bootstrap && cp -af ./ninja \"\$BUILD_ROOT/root/bin\" docbook4.2 install_docbook_dist schema docbook4.1.2 cp \"\$BUILD_ROOT/dists/docbook4.2/catalog.xml\" . ; \ sed -i.bak 's/V4.2/V4.1.2/g; s/4.2/4.1.2/g;' catalog.xml; \ install_docbook_dist schema docbook4.3 install_docbook_dist schema docbook4.4 install_docbook_dist schema docbook4.5 install_docbook_dist schema docbook5.0.1 install_docbook_dist schema docbook5.1 install_docbook_dist schema docbook-xsl install_docbook_dist stylesheet docbook-xsl-ns install_docbook_dist stylesheet dejavu install_fonts liberation install_fonts urw install_fonts " DIST_ARGS="$DIST_ARGS pkgconf --disable-tests curl --with-openssl --without-nghttp2 --without-libidn2 --without-librtmp --without-brotli libffi --enable-static libicu --enable-static --disable-extras --disable-tools --disable-tests --disable-samples --with-library-bits=64 gettext --with-included-gettext --with-included-glib --with-included-libcroco --with-included-libunistring --with-included-libxml --disable-curses CPPFLAGS=\"\$CPPFLAGS -DLIBXML_STATIC\" pkgconfig --with-internal-glib --with-libiconv=gnu curl --with-ssl --without-brotli pcre --enable-utf --enable-unicode-properties --enable-pcre16 --enable-pcre32 --enable-jit pcre2 --enable-utf8 --enable-pcre2-8 --enable-pcre2-16 --enable-pcre2-32 --enable-unicode-properties --enable-pcregrep-libz --enable-pcregrep-libbz2 --enable-jit libxslt --without-python --without-crypto libgd --without-xpm fontconfig --with-baseconfigdir=/etc/fonts graphviz --disable-ltdl --without-x --disable-swig CFLAGS=\"-include \$PWD/declspec.h \$CFLAGS\" CC=\"\$CXX\" python2 --with-ensurepip=install --with-system-expat python3 --with-ensurepip=install --with-system-expat bakefile --enable-shared XML-Parser EXPATINCPATH=\"\$BUILD_ROOT/root/include\" EXPATLIBPATH=\"\$BUILD_ROOT/root/lib\" doxygen -DICONV_ACCEPTS_NONCONST_INPUT:BOOL=FALSE -DICONV_ACCEPTS_CONST_INPUT:BOOL=TRUE sfml -DSFML_USE_SYSTEM_DEPS=TRUE -DSFML_BUILD_AUDIO=FALSE libcroco --disable-Bsymbolic snappy -DSNAPPY_BUILD_TESTS=OFF -DSNAPPY_BUILD_BENCHMARKS=OFF libjpeg-turbo -DWITH_JPEG8=ON -DWITH_SIMD=OFF libtiff --disable-lzma --disable-webp freetype -Dharfbuzz=disabled harfbuzz -Dcairo=disabled -Dicu=disabled graphite2 -DGRAPHITE2_NFILEFACE=ON -DGRAPHITE2_TESTS=OFF -DGRAPHITE2_DOCS=OFF flac --disable-ogg libsoxr -DWITH_OPENMP=NO libxavs --disable-asm libzvbi --without-x libxml2 --without-python --without-python3 libbluray --disable-bdjava-jar --disable-examples libopencore-amrnb --disable-compile-c vidstab -DUSE_OMP=NO libx264 --enable-static --enable-pic libx265 -DHIGH_BIT_DEPTH=ON -DENABLE_ASSEMBLY=OFF -DENABLE_CLI=OFF wxwidgets --enable-stl --disable-precomp-headers --enable-cxx11 --enable-permissive --with-opengl --with-libpng " export DIST_BARE_MAKE_ARGS='CC="$CC" CXX="$CXX" LD="$CXX"' export ALL_MAKE_ARGS='V=1 VERBOSE=1' DIST_MAKE_ARGS="$DIST_MAKE_ARGS openssl CC=\"\$CC\" getopt LDFLAGS=\"\$LDFLAGS -lintl -liconv\" CFLAGS=\"\$CFLAGS\" bzip2 libbz2.a bzip2 bzip2recover CFLAGS=\"\$CFLAGS\" LDFLAGS=\"\$LDFLAGS\" unzip generic2 zip generic expat DOCBOOK_TO_MAN=docbook2man shared-mime-info -j1 xvidcore -j1 fontconfig LIBS=\"-lintl -liconv\" libgsm CC=\"\$CC \$CFLAGS\" " DIST_INSTALL_TARGETS="$DIST_INSTALL_OVERRIDES openssl install_sw " DIST_EXTRA_LDFLAGS="$DIST_EXTRA_LDFLAGS python2 -lffi glib -liconv graphviz -lpcreposix doxygen -lintl -liconv ffmpeg -lm -llzma -lpthread " DIST_EXTRA_CXXFLAGS="$DIST_EXTRA_CXXFLAGS gperf -std=gnu++11 doxygen -std=gnu++11 sfml -std=gnu++11 wxwidgets -std=gnu++11 libmodplug -std=gnu++11 libopencore-amrnb -std=gnu++11 " DIST_EXTRA_LIBS="$DIST_EXTRA_LIBS gettext -liconv shared-mime-info \$LD_START_GROUP -lxml2 -lgio-2.0 -lgmodule-2.0 -lgobject-2.0 -lglib-2.0 -lpcre -llzma -lz -lm -lffi -lpthread -liconv -lresolv -ldl \$LD_END_GROUP python3 -liconv -lintl harfbuzz -lz wxwidgets -ljpeg -ltiff -liconv " OIFS=$IFS NL=' ' TAB=' ' builder() { eval "$BUILD_ENV" setup read_command_line "$@" install_core_deps setup_perl setup_meson setup_ccache setup_ninja delete_outdated_dists pre_build_all build_prerequisites DOWNLOADED_DISTS= UNPACKED_DISTS= download_needed_dists unpack_needed_dists $DOWNLOADED_DISTS build_needed_dists $UNPACKED_DISTS build_project "$@" } read_command_line() { case "$1" in --env|--target-env) puts "$BUILD_ENV" exit 0 ;; --host-env) puts "$BUILD_ENV" host_env 2>/dev/null || : exit 0 ;; --clean) rm -rf "$BUILD_ROOT/dists/*" unpack_dists exit 0 ;; esac } # overridable hook for other scripts pre_build_all() { return 0 } # NOTE: this is called on source at the end of the file setup() { detect_os target_os=${CROSS_OS:-$os} target_bits=${target_bits:-$bits} mkdir -p "$BUILD_ROOT/tmp" rm -rf "$BUILD_ROOT/tmp/"* mkdir -p "$BUILD_ROOT/root/include" [ -L "$BUILD_ROOT/root/inc" ] || ln -s "$BUILD_ROOT/root/include" "$BUILD_ROOT/root/inc" mkdir -p "$BUILD_ROOT/root/lib" for libarch in lib64 lib32; do [ -L "$BUILD_ROOT/root/$libarch" ] || ln -s "$BUILD_ROOT/root/lib" "$BUILD_ROOT/root/$libarch" done [ -n "$target_platform" ] && { [ -L "$BUILD_ROOT/root/lib/$target_platform" ] || ln -s "$BUILD_ROOT/root/lib" "$BUILD_ROOT/root/lib/$target_platform"; } OPWD=$PWD cd "$BUILD_ROOT/root" for d in bin perl5 share etc man doc; do mkdir -p "$d" done # things like strawberry perl very rudely put this in the PATH if [ "$os" != mac ]; then [ -L bin/gmake ] || ln -s "$(command -v make)" bin/gmake fi cd "$OPWD" # Don't use ffmpeg for 32 bit windows builds for XP compat and to make the # binary smaller. if [ "$target_os" = windows ] && [ "$target_bits" -eq 32 ]; then BUILD_FFMPEG= PROJECT_ARGS="$PROJECT_ARGS" fi if [ -z "$BUILD_FFMPEG" ]; then for dist in $FFMPEG_DISTS; do table_line_remove DISTS $dist done PROJECT_ARGS="$PROJECT_ARGS -DENABLE_FFMPEG=NO" fi DIST_NAMES=$( table_column DISTS 0 3) DIST_URLS=$( table_column DISTS 1 3) DIST_TARGETS=$(table_column DISTS 2 3) DISTS_NUM=$(table_rows DISTS) NUM_CPUS=$(num_cpus) BUILD_ENV="$BUILD_ENV export MAKEFLAGS=-j$NUM_CPUS " eval "$BUILD_ENV" : ${CHECKOUT:=$(find_checkout)} TMP_DIR=${TMP_DIR:-/tmp/builder-$$} setup_tmp_dir UNPACK_DIR="$TMP_DIR/unpack" mkdir "$UNPACK_DIR" DISTS_DIR="$BUILD_ROOT/dists" mkdir -p "$DISTS_DIR" } num_cpus() { if command -v nproc >/dev/null; then nproc return $? fi if path_exists /proc/cpuinfo; then set -- $(grep '^processor *:' /proc/cpuinfo | wc -l) puts $1 return 0 fi if command -v sysctl >/dev/null; then sysctl -n hw.ncpu return 0 fi warn 'cannot determine number of CPU threads, using a default of 2' puts 2 } setup_perl() { if [ -x /usr/bin/perl ]; then perl=/usr/bin/perl elif [ -x /usr/local/bin/perl ]; then perl=/usr/local/bin/perl else perl=$(command -v perl || :) fi if [ -n "$perl" ]; then if [ -n "$msys2" ] || [ -n "$cygwin" ]; then ln -sf "$perl" "$BUILD_ROOT/root/bin/perl.exe" perl="$BUILD_ROOT/root/bin/perl.exe" else ln -sf "$perl" "$BUILD_ROOT/root/bin/perl" fi "$perl" -MCPAN -e 'CPAN::Shell->notest("install", "App::cpanminus")' fi } setup_meson() { if ! [ -x "$BUILD_ROOT/root/bin/meson" ]; then if [ -x /usr/local/bin/meson ]; then meson=/usr/local/bin/meson else meson=$(command -v meson || :) fi if [ -n "$meson" ]; then if [ -n "$msys2" ] || [ -n "$cygwin" ]; then ln -sf "$meson" "$BUILD_ROOT/root/bin/meson.exe" meson="$BUILD_ROOT/root/bin/meson.exe" else ln -sf "$meson" "$BUILD_ROOT/root/bin/meson" fi fi fi } setup_ccache() { if command -v ccache >/dev/null; then ln -sf "$(command -v ccache)" "$BUILD_ROOT/root/bin/${CC##*/}" ln -sf "$(command -v ccache)" "$BUILD_ROOT/root/bin/${CXX##*/}" fi } setup_ninja() { if [ -x /usr/local/bin/ninja ]; then ninja=/usr/local/bin/ninja else ninja=$(command -v ninja || :) fi if [ -n "$ninja" ]; then if [ -n "$msys2" ] || [ -n "$cygwin" ]; then ln -sf "$ninja" "$BUILD_ROOT/root/bin/ninja.exe" ninja="$BUILD_ROOT/root/bin/ninja.exe" else ln -sf "$ninja" "$BUILD_ROOT/root/bin/ninja" fi fi } clear_build_env() { for var in CC CXX CFLAGS CPPFLAGS CXXFLAGS OBJCXXFLAGS LDFLAGS CMAKE_PREFIX_PATH PKG_CONFIG_PATH PERL_MM_USE_DEFAULT PERL_EXTUTILS_AUTOINSTALL OPENSSL_ROOT PERL_MB_OPT PERL_MM_OPT PERL5LIB PERL_LOCAL_LIB_ROOT; do unset $var done export PATH="$ORIG_PATH" } set_build_env() { eval "$BUILD_ENV" } install_core_deps() { ${os}_install_core_deps # get platform now that we have gcc detect_os # things like ccache may have been installed, re-eval build env eval "$BUILD_ENV" } installing_core_deps() { puts "${NL}Installing core dependencies for your OS...${NL}${NL}" } done_msg() { puts "${NL}Done!!!${NL}${NL}" } unknown_install_core_deps() { : } linux_install_core_deps() { # detect host architecture case "$(uname -a)" in *x86_64*) amd64=1 ;; *i686*) i686=1 ;; esac eval "${linux_distribution}_install_core_deps" } debian_install_core_deps() { installing_core_deps sudo apt-get -qq update || : sudo apt-get -qy install build-essential g++ curl ccache perl meson done_msg } fedora_install_core_deps() { installing_core_deps sudo dnf install -y --nogpgcheck --best --allowerasing gcc gcc-c++ make redhat-rpm-config curl perl ccache file patch findutils meson } suse_install_core_deps() { installing_core_deps sudo zypper in -y gcc gcc-c++ binutils glibc-devel-static make curl perl ccache file patch meson } arch_install_core_deps() { installing_core_deps # check for gcc-multilib gcc_pkg=gcc if sudo pacman -Q gcc-multilib >/dev/null 2>&1; then gcc_pkg=gcc-multilib fi # update catalogs sudo pacman -Sy # not using the base-devel group because it can break gcc-multilib sudo pacman --noconfirm --needed -S $gcc_pkg binutils file grep gawk gzip make patch sed util-linux curl ccache perl meson done_msg } solus_install_core_deps() { installing_core_deps sudo eopkg -y update-repo sudo eopkg -y install -c system.devel curl perl meson done_msg } windows_install_core_deps() { if [ -n "$msys2" ]; then msys2_install_core_deps elif [ -n "$cygwin" ]; then cygwin_install_core_deps fi } msys2_install_core_deps() { case "$MSYSTEM" in MINGW32) target='mingw-w64-i686' ;; *) target='mingw-w64-x86_64' ;; esac installing_core_deps # update catalogs pacman -Sy set -- for p in binutils curl crt-git gcc gcc-libs headers-git tools-git windows-default-manifest libmangle-git meson; do set -- "$@" "${target}-${p}" done # install pacman --noconfirm --needed -S make tar patch diffutils ccache perl msys2-w32api-headers msys2-runtime-devel gcc gcc-libs mpfr windows-default-manifest python python2 pass ninja "$@" # make sure msys perl takes precedence over mingw perl if the latter is installed mkdir -p "$BUILD_ROOT/root/bin" # alias python2 to python ln -sf /usr/bin/python2.exe "$BUILD_ROOT/root/bin/python.exe" # activate ccache eval "$BUILD_ENV" done_msg } cygwin_install_core_deps() { installing_core_deps target="mingw64-${target_cpu}" curl -L rawgit.com/transcode-open/apt-cyg/master/apt-cyg > "$BUILD_ROOT/root/bin/apt-cyg" chmod +x "$BUILD_ROOT/root/bin/apt-cyg" hash -r apt-cyg update set -- for p in binutils gcc-core gcc-g++ headers windows-default-manifest; do set -- "$@" "${target}-${p}" done apt-cyg install make tar patch diffutils ccache perl m4 cygwin32-w32api-headers gcc-core gcc-g++ mpfr windows-default-manifest python2 libncurses-devel meson "$@" # alias python2 to python ln -sf /usr/bin/python2.exe "$BUILD_ROOT/root/bin/python.exe" # activate ccache eval "$BUILD_ENV" done_msg } mac_install_core_deps() { if ! xcode-select -p >/dev/null 2>&1 && \ ! pkgutil --pkg-info=com.apple.pkg.CLTools_Executables >/dev/null 2>&1 && \ ! pkgutil --pkg-info=com.apple.pkg.DeveloperToolsCLI >/dev/null 2>&1; then error 'Please install XCode and the XCode Command Line Tools, then run this script again. On newer systems this can be done with: ;xcode-select --install' fi if ! [ -x /usr/local/bin/brew ]; then error 'Please install Mac Homebrew: ;https://brew.sh/' fi /usr/local/bin/brew install -q perl meson ninja # This is necessary because someone broke my compiler. /usr/local/bin/brew unlink openssl@3 >/dev/null 2>&1 || : } setup_tmp_dir() { # mkdir -m doesn't work on some versions of msys and similar rm -rf "$TMP_DIR" if ! ( mkdir -m 700 "$TMP_DIR" 2>/dev/null || mkdir "$TMP_DIR" 2>/dev/null || [ -d "$TMP_DIR" ] ); then die "Failed to create temporary directory: '$TMP_DIR" fi chmod 700 "$TMP_DIR" 2>/dev/null || : trap 'quit $?' EXIT PIPE HUP INT QUIT ILL TRAP KILL BUS TERM } quit() { cd "$HOME" || : rm -rf "$TMP_DIR" || : exit "${1:-0}" } detect_os() { case "$(uname -s)" in Linux) os=linux ;; Darwin) os=mac ;; MINGW*|MSYS*) os=windows msys2=1 ;; CYGWIN*) os=windows cygwin=1 ;; *) os=unknown ;; esac case "$(uname -a)" in *x86_64*) bits=64 ;; *i686*) bits=32 ;; esac target_platform=$($CC -dumpmachine 2>/dev/null) || : LD_START_GROUP= LD_END_GROUP= if ld -v 2>/dev/null | grep -Eq GNU; then LD_START_GROUP='-Wl,--start-group' LD_END_GROUP='-Wl,--end-group' fi # detect linux distribution linux_distribution=unknown if [ $os = linux ]; then if [ -f /etc/debian_version ]; then linux_distribution=debian elif [ -f /etc/fedora-release ]; then linux_distribution=fedora elif [ -f /etc/arch-release ]; then linux_distribution=arch elif [ -f /etc/solus-release ]; then linux_distribution=solus elif path_exists /etc/os-release && (. /etc/os-release; puts "$ID_LIKE") | grep -q suse; then linux_distribution=suse fi fi } delete_outdated_dists() { [ ! -d "$BUILD_ROOT/downloads" ] && return 0 files= for current_dist in $DIST_NAMES; do files="$files $(dist_file "$current_dist")" done IFS=$NL find "$BUILD_ROOT/downloads" -maxdepth 1 -type f -not -name '.*' | \ while read -r file; do IFS=$OIFS if ! list_contains "$file" $files; then puts "${NL}Deleting outdated dist archive: $file${NL}${NL}" rm -f "$file" dist_dir="$BUILD_ROOT/dists/${file##*/}" while [ ! -d "$dist_dir" ]; do case "$file_dist" in *-*) dist_dir=${dist_dir%-*} ;; *) dist_dir= break ;; esac done if [ -n "$dist_dir" ] && [ -d "$dist_dir" ]; then puts "${NL}Deleting outdated dist unpack dir: $dist_dir${NL}${NL}" rm -rf "$dist_dir" fi fi done IFS=$OIFS ( cd "$BUILD_ROOT/dists" IFS=$NL find . -maxdepth 1 -type d -not -name '.*' | \ while read -r dir; do IFS=$OIFS dir=${dir#./} if ! list_contains "$dir" $DIST_NAMES; then puts "${NL}Deleting outdated dist unpack dir: $dir${NL}${NL}" rm -rf "$dir" fi done IFS=$OIFS ) } build_prerequisites() { dists_are_installed $PRE_BUILD_DISTS && return 0 puts "${NL}Fetching and building prerequisites...${NL}${NL}" for current_dist in $PRE_BUILD_DISTS; do get_dist $current_dist build_dist_if_needed $current_dist done puts "${NL}Done with prerequisites.${NL}${NL}" } dists_are_installed() { for current_dist; do if ! path_exists "$(install_artifact -f $current_dist)"; then return 1 fi done } download_needed_dists() { running_jobs= max_jobs=25 setup_jobs job_failed_hook download_failed for current_dist in $DIST_NAMES; do if ! path_exists "$(dist_file "$current_dist")"; then ( start_job write_job_info dist_name $current_dist { download_dist $current_dist write_job_exit_status } 2>&1 | write_job_output ) & running_jobs="$running_jobs $!" wait_jobs running_jobs $max_jobs # FIXME: this should only run on a job_success hook, hooks need to be fixed DOWNLOADED_DISTS="$DOWNLOADED_DISTS $current_dist" fi done wait_all_jobs running_jobs cleanup_jobs } unpack_needed_dists() { running_jobs= max_jobs=$NUM_CPUS setup_jobs job_failed_hook unpack_failed for current_dist in $DIST_NAMES; do if list_contains "$current_dist" "$@" || ! path_exists "$(dist_dir "$current_dist")"; then ( start_job write_job_info dist_name $current_dist { unpack_dist $current_dist write_job_exit_status } 2>&1 | write_job_output ) & running_jobs="$running_jobs $!" wait_jobs running_jobs $max_jobs # FIXME: this should only run on a job_success hook, hooks need to be fixed UNPACKED_DISTS="$UNPACKED_DISTS $current_dist" fi done wait_all_jobs running_jobs cleanup_jobs } dist_url() { current_dist=$1 [ -n "$current_dist" ] || die 'dist_url: dist name required' dist_idx=$(list_index $current_dist $DIST_NAMES) putsln "$(list_get $dist_idx $DIST_URLS)" } dist_file() { current_dist=$1 [ -n "$current_dist" ] || die 'dist_file: dist name required' dist_url=$(dist_url "$current_dist") dist_file=${dist_url##*/} # remove query string stuff dist_file=${dist_file%\?*} # set full path dist_file="$BUILD_ROOT/downloads/$current_dist-$dist_file" puts "$(resolve_link "$dist_file")" } dist_dir() { current_dist=$1 [ -n "$current_dist" ] || die 'dist_dir: dist name required' putsln "$BUILD_ROOT/dists/$current_dist" } get_dist() { current_dist=$1 [ -n "$current_dist" ] || die 'get_dist: dist name required' download_dist "$current_dist" unpack_dist "$current_dist" } download_dist() { current_dist=$1 [ -n "$current_dist" ] || die 'download_dist: dist name required' dist_url=$(dist_url "$current_dist") dist_file=$(dist_file "$current_dist") dist_dir="$DISTS_DIR/$current_dist" mkdir -p "$BUILD_ROOT/downloads" cd "$BUILD_ROOT/downloads" if [ ! -f "$dist_file" ]; then puts "${NL}Fetching $current_dist: $dist_url${NL}${NL}" $CURL -SsL "$dist_url" -o "$dist_file" case "$dist_file" in *.*) ;; *) # no extension, try to figure out if zip or .tar.gz new_dist_file=$(echo "$dist_file" | sed 's/-* *$//') # remove trailing dash and spaces case "$(file "$dist_file")" in *gzip*) mv "$dist_file" "$new_dist_file.tar.gz" ln -sf "$new_dist_file.tar.gz" "$dist_file" ;; *Zip\ archive*) mv "$dist_file" "$new_dist_file.zip" ln -sf "$new_dist_file.zip" "$dist_file" ;; esac ;; esac fi } rtrim() { str=$1 while [ "$str" != "${str% }" ]; do str="${str% }" done puts "$str" } download_failed() { job_pid=$1 error "Fetching $current_dist failed, check the URL:${NL}${NL}$(cat "$TMP_DIR/job_output/$job_pid")" rm -f "$(dist_file "$current_dist")" exit 1 } unpack_dist() { current_dist=$1 [ -n "$current_dist" ] || die 'unpack_dist: dist name required' dist_file=$(dist_file "$current_dist") dist_dir="$DISTS_DIR/$current_dist" if [ ! -f "$dist_file" ]; then error "unpack_dist: missing dist file for dist '$current_dist': '$dist_file'" fi puts "${NL}Unpacking $current_dist${NL}${NL}" rm -rf "$dist_dir" mkdir "$dist_dir" OPWD=$PWD unpack_dir="$UNPACK_DIR/$current_dist-$$" mkdir "$unpack_dir" cd "$unpack_dir" eval "set -- $(dist_tar_args "$current_dist")" case "$dist_file" in *.tar) $TAR $@ -xf "$dist_file" ;; *.tar.gz|*.tgz) $TAR $@ -zxf "$dist_file" ;; *.tar.xz) xz -dc "$dist_file" | $TAR $@ -xf - ;; *.tar.bz2) bzip2 -dc "$dist_file" | $TAR $@ -xf - ;; *.zip) unzip -q "$dist_file" ;; esac if [ $(list_length *) -eq 1 ] && [ -d * ]; then # one archive dir cd * fi $TAR -cf - . | (cd "$dist_dir"; $TAR -xf -) cd "$TMP_DIR" rm -rf "$unpack_dir" ( cd "$dist_dir" dist_post_unpack "$current_dist" ) cd "$OPWD" } unpack_failed() { job_pid=$1 error "Unpacking $current_dist failed:${NL}${NL}$(cat "$TMP_DIR/job_output/$job_pid")" rm -rf "$DISTS_DIR/$current_dist" exit 1 } setup_jobs() { rm -rf "$TMP_DIR/job_status" "$TMP_DIR/job_output" mkdir -p "$TMP_DIR/job_status" "$TMP_DIR/job_output" _job_failed_hook= } cleanup_jobs() { rm -rf "$TMP_DIR/job_status" "$TMP_DIR/job_output" _job_failed_hook= } start_job() { current_job_pid=$(exec sh -c 'printf "%s" $PPID') } write_job_exit_status() { _exit_status=$? putsln "job_exited='$_exit_status'" >> "$TMP_DIR/job_status/$current_job_pid" 2>/dev/null } write_job_info() { [ -n "$1" ] || die 'write_job_info: key name required' putsln "${1}='${2}'" >> "$TMP_DIR/job_status/$current_job_pid" 2>/dev/null } write_job_output() { tee -a "$TMP_DIR/job_output/$current_job_pid" } wait_all_jobs() { [ -n "$1" ] || die 'wait_all_jobs: jobs list var name required' while [ "$(eval list_length "\$$1")" -gt 0 ]; do sleep 0.2 check_jobs $1 done } wait_jobs() { [ -n "$1" ] || die 'limit_jobs: jobs list var name required' [ -n "$2" ] && [ $2 -ge 0 ] || die 'limit_jobs: max jobs number required' while [ "$(eval list_length "\$$1")" -ge $2 ]; do sleep 0.05 check_jobs $1 done } running_jobs() { alive_list_var=$1 [ -n "$alive_list_var" ] || die 'running_jobs: alive list variable name required' reaped_list_var=$2 [ -n "$reaped_list_var" ] || die 'running_jobs: reaped list variable name required' jobs_file="$TMP_DIR/jobs_list.txt" jobs -l > "$jobs_file" eval "$alive_list_var=" eval "$reaped_list_var=" IFS=$NL # will get pair: for job in $(sed <"$jobs_file" -n 's/^\[[0-9]\{1,\}\] *[-+]\{0,1\} *\([0-9][0-9]*\) *\([A-Za-z]\{1,\}\).*/\1 \2/p'); do IFS=$OIFS set -- $job pid=$1 state=$2 case "$state" in Stopped) kill $pid 2>/dev/null || : eval "$reaped_list_var=\"\$$reaped_list_var $pid\"" ;; Running) eval "$alive_list_var=\"\$$alive_list_var $pid\"" ;; esac done IFS=$OIFS rm -f "$jobs_file" } check_jobs() { jobs_list_var=$1 [ -n "$jobs_list_var" ] || die 'check_jobs: jobs list variable name required' running_jobs alive reaped new_jobs= for job in $(eval puts \$$jobs_list_var); do if list_contains $job $alive; then new_jobs="$new_jobs $job" else job_status_file="$TMP_DIR/job_status/$job" job_output_file="$TMP_DIR/job_output/$job" if [ -f "$job_status_file" ]; then job_exited= eval "$(cat "$job_status_file")" if [ -n "$job_exited" ] && [ "$job_exited" -eq 0 ]; then rm "$job_status_file" "$job_output_file" else current_dist=$dist_name error "A job has failed, winding down pending jobs..." while [ "$(list_length $alive)" -ne 0 ]; do for pid in $alive; do if ! list_contains $pid $last_alive; then kill $pid 2>/dev/null || : else kill -9 $pid 2>/dev/null || : fi done last_alive=$alive sleep 0.2 running_jobs alive reaped done # don't want signals to interrupt sleep trap - PIPE HUP ALRM if [ "$os" != windows ]; then sleep 30 || : else # this is painfully slow on msys2/cygwin warn 'Please wait, this will take a while...' sleep 330 || : fi call_job_failed_hook $job fi fi fi done eval "$jobs_list_var=\$new_jobs" } job_failed_hook() { [ -n "$1" ] || die 'job_failed_hoook: sh function name required' _job_failed_hook=$1 } call_job_failed_hook() { [ -n "$1" ] && [ $1 -gt 0 ] || die 'call_job_failed_hook: job pid required' if [ -n "$_job_failed_hook" ]; then eval $_job_failed_hook '"$@"' fi } # fall back to 1 second sleeps if fractional sleep is not supported sleep() { if ! command sleep "$@" 2>/dev/null; then sleep_secs=${1%%.*} [ $# -gt 0 ] && shift if [ -z "$sleep_secs" ] || [ "$sleep_secs" -lt 1 ]; then sleep_secs=1 fi command sleep $sleep_secs "$@" fi } build_dists() { for current_dist; do build_dist "$current_dist" BUILT_DISTS="$BUILT_DISTS $current_dist" done } build_needed_dists() { for current_dist in $DIST_NAMES; do if list_contains "$current_dist" "$@"; then build_dist $current_dist else build_dist_if_needed $current_dist fi done } build_dist_if_needed() { current_dist=$1 [ -n "$current_dist" ] || die 'build_dist_if_needed: dist name required' shift if ! path_exists "$(install_artifact -f $current_dist)"; then build_dist $current_dist "$@" BUILT_DISTS="$BUILT_DISTS $current_dist" fi } rebuild_dist() { current_dist=$1 [ -n "$current_dist" ] || die 'rebuild_dist: dist name required' shift rm -rf "$BUILD_ROOT/dists/$current_dist" unpack_dist "$current_dist" build_dist "$current_dist" "$@" } build_dist() { current_dist=$1 [ -n "$current_dist" ] || die 'build_dist: dist name required' shift extra_dist_args=$@ if ! [ -n "$(table_line DISTS $current_dist)" ]; then warn "no such dist: $current_dist" return fi cd "$DISTS_DIR/$current_dist" puts "${NL}Building $current_dist${NL}${NL}" dist_patch "$current_dist" dist_pre_build "$current_dist" ORIG_CPPFLAGS=$CPPFLAGS ORIG_CFLAGS=$CFLAGS ORIG_CXXFLAGS=$CXXFLAGS ORIG_OBJCXXFLAGS=$OBJCXXFLAGS ORIG_LDFLAGS=$LDFLAGS ORIG_LIBS=$LIBS # have to make sure C++ flags are passed when linking, but only for C++ and **NOT** C # this fails if there are any .c files in the project if [ "$(find . -name '*.cpp' -o -name '*.cc' | wc -l)" -ne 0 -a "$(find . -name '*.c' | wc -l)" -eq 0 ]; then export LDFLAGS="$CXXFLAGS $LDFLAGS" fi export CPPFLAGS="$CPPFLAGS $(eval puts "$(dist_extra_cppflags "$current_dist")")" export CFLAGS="$CFLAGS $(eval puts "$(dist_extra_cflags "$current_dist")")" export CXXFLAGS="$CXXFLAGS $(eval puts "$(dist_extra_cxxflags "$current_dist")")" export OBJCXXFLAGS="$OBJCXXFLAGS $(eval puts "$(dist_extra_objcxxflags "$current_dist")")" export LDFLAGS="$LDFLAGS $(eval puts "$(dist_extra_ldflags "$current_dist")")" export LIBS="$LIBS $(eval puts "$(dist_extra_libs "$current_dist")")" configure_override=$(dist_configure_override "$current_dist") install_override=$(dist_install_override "$current_dist") build_override=$(dist_build_override "$current_dist") config_type=$(dist_configure_type "$current_dist") if [ -n "$build_override" ]; then eval "set -- $extra_dist_args" echo_eval_run "$build_override $@" check_install_artifact "$current_dist" else if [ "$config_type" = meson ] || [ -z "$config_type" -a -f meson.build ]; then mkdir -p build cd build if [ -n "$configure_override" ]; then eval "set -- $extra_dist_args" echo_eval_run "$configure_override $@" else eval "set -- $(dist_args "$current_dist" meson) $extra_dist_args" echo_run $MESON .. "$@" fi dist_post_configure "$current_dist" eval "set -- $(dist_ninja_args "$current_dist")" echo_run ninja "$@" if [ -z "$install_override" ]; then rm -rf destdir mkdir destdir echo_eval_run 'DESTDIR="$PWD/destdir" ninja '"$(dist_make_install_args "$current_dist")"' install || :' install_dist "$current_dist" else echo_eval_run "$install_override $(dist_make_install_args "$current_dist")" fi check_install_artifact "$current_dist" elif [ "$config_type" = autoconf -o "$config_type" = autoreconf -o "$config_type" = autoreconf_noargs ] || [ -z "$config_type" -a \( -f configure -o -f Configure -o -f configure.ac -o -f configure.in -o -f Makefile.am \) ]; then # workaround a sometimes autoconf bug touch config.rpath if [ -n "$configure_override" ]; then eval "set -- $extra_dist_args" echo_eval_run "$configure_override $@" else autogen= if [ "$config_type" = autoreconf -o "$config_type" = autoreconf_noargs ] || [ ! -f configure ]; then autogen=1 if [ "$config_type" != autoreconf_noargs ]; then eval "set -- $CONFIGURE_REQUIRED_ARGS $(dist_args "$current_dist" autoconf) $extra_dist_args" else set -- fi if [ -f autogen.sh ]; then chmod +x autogen.sh echo_run ./autogen.sh "$@" elif [ -f buildconf.sh ]; then chmod +x buildconf.sh echo_run ./buildconf.sh "$@" elif [ -f bootstrap ]; then chmod +x bootstrap echo_run ./bootstrap "$@" else if [ -d m4 ]; then echo_run aclocal --force -I m4 else echo_run aclocal --force fi if command -v glibtoolize >/dev/null; then echo_run glibtoolize --force elif command -v libtoolize >/dev/null; then echo_run libtoolize --force fi echo_run autoheader || : echo_run autoconf --force if command -v gtkdocize >/dev/null; then echo_run gtkdocize 2>/dev/null || : fi [ -f Makefile.am ] && echo_run automake --foreign --add-missing --copy fi fi if [ -z "$autogen" ] || ! path_exists config.status; then if path_exists Configure; then chmod +x ./Configure eval "set -- $CONFIGURE_REQUIRED_ARGS $(dist_args "$current_dist" autoconf) $extra_dist_args" echo_run ./Configure "$@" else chmod +x ./configure eval "set -- $CONFIGURE_REQUIRED_ARGS $(dist_args "$current_dist" autoconf) $extra_dist_args" echo_run ./configure "$@" fi fi fi dist_post_configure "$current_dist" eval "set -- $(dist_make_args "$current_dist")" echo_run $MAKE -j$NUM_CPUS "$@" if [ -z "$install_override" ]; then rm -rf destdir mkdir destdir eval "set -- $(dist_make_install_args "$current_dist")" make_install "$@" install_dist "$current_dist" else echo_eval_run "$install_override $(dist_make_install_args "$current_dist")" fi check_install_artifact "$current_dist" elif [ "$config_type" = cmakeninja ]; then if ! command -v ninja >/dev/null; then error "configure type 'cmakeninja' requested but ninja is not available yet"; fi mkdir -p build cd build if [ -n "$configure_override" ]; then eval "set -- $extra_dist_args" echo_eval_run "$configure_override $@" else eval "set -- $CMAKE_REQUIRED_ARGS $(dist_args "$current_dist" cmake) $extra_dist_args -G Ninja" echo_run cmake .. "$@" fi dist_post_configure "$current_dist" eval "set -- $(dist_ninja_args "$current_dist")" echo_run ninja "$@" if [ -z "$install_override" ]; then rm -rf destdir mkdir destdir eval "set -- $(dist_make_install_args "$current_dist")" echo_run $MAKE "$@" install DESTDIR="$PWD/destdir" || : install_dist "$current_dist" else echo_eval_run "$install_override $(dist_make_install_args "$current_dist")" fi check_install_artifact "$current_dist" elif [ "$config_type" = cmake ] || [ -z "$config_type" -a -f CMakeLists.txt ]; then mkdir -p build cd build if [ -n "$configure_override" ]; then eval "set -- $extra_dist_args" echo_eval_run "$configure_override $@" else eval "set -- $CMAKE_REQUIRED_ARGS $(dist_args "$current_dist" cmake) $extra_dist_args" echo_run cmake .. "$@" fi dist_post_configure "$current_dist" eval "set -- $(dist_make_args "$current_dist")" echo_run $MAKE -j$NUM_CPUS "$@" if [ -z "$install_override" ]; then rm -rf destdir mkdir destdir eval "set -- $(dist_make_install_args "$current_dist")" echo_run $MAKE "$@" install DESTDIR="$PWD/destdir" || : install_dist "$current_dist" else echo_eval_run "$install_override $(dist_make_install_args "$current_dist")" fi check_install_artifact "$current_dist" elif [ "$config_type" = python ] || [ -z "$config_type" -a -f setup.py ]; then if [ -z "$install_override" ]; then set -- if grep -Eq 'Python :: 3' PKG-INFO 2>/dev/null; then set -- 'python3 -m pip' fi if grep -Eq 'Python :: 2' PKG-INFO 2>/dev/null; then set -- "$@" 'python2 -m pip' fi # default to python2 if no package info [ "$#" = 0 ] && set -- 'python2 -m pip' for pip in "$@"; do if [ -n "$configure_override" ]; then eval "set -- $extra_dist_args" echo_eval_run "$configure_override $@" else eval "set -- $(dist_args "$current_dist" python) $extra_dist_args" echo_run $pip install . "$@" fi done else echo_eval_run "$install_override $(dist_make_install_args "$current_dist")" fi check_install_artifact "$current_dist" elif [ "$config_type" = perl ] || [ -z "$config_type" -a -f Makefile.PL ]; then echo_run cpanm --notest --installdeps . if [ -n "$configure_override" ]; then eval "set -- $extra_dist_args" echo_eval_run "$configure_override $@" else eval "set -- $(dist_args "$current_dist" perl) $extra_dist_args" echo_run "$perl" Makefile.PL "$@" fi dist_post_configure "$current_dist" eval "set -- $(dist_make_args "$current_dist")" echo_run $PERL_MAKE "$@" # dmake doesn't understand -j if [ -z "$install_override" ]; then eval "set -- $(dist_make_install_args "$current_dist")" echo_run $PERL_MAKE "$@" install || : else echo_eval_run "$install_override $(dist_make_install_args "$current_dist")" fi check_install_artifact "$current_dist" elif [ "$config_type" = make ] || [ -z "$config_type" -a \( -f Makefile -o -f makefile \) ]; then makefile=makefile if [ -f Makefile ]; then makefile=Makefile fi eval "set -- $DIST_BARE_MAKE_ARGS $(dist_make_args "$current_dist")" echo_run $MAKE -j$NUM_CPUS "$@" if [ -z "$install_override" ]; then eval "set -- $(dist_make_install_args "$current_dist")" make_install "$@" # some bare makefiles just have no DESTDIR mechanism of any sort if [ -d destdir ]; then install_dist "$current_dist" fi else echo_eval_run "$install_override $(dist_make_install_args "$current_dist")" fi check_install_artifact "$current_dist" else die "don't know how to build $current_dist, please define a BUILD_OVERRIDE" fi fi export CPPFLAGS="$ORIG_CPPFLAGS" export CFLAGS="$ORIG_CFLAGS" export CXXFLAGS="$ORIG_CXXFLAGS" export OBJCXXFLAGS="$ORIG_OBJCXXFLAGS" export LDFLAGS="$ORIG_LDFLAGS" export LIBS="$ORIG_LIBS" dist_post_build "$current_dist" done_msg } make_install() { rm -rf destdir mkdir -p destdir cd destdir prefix=$(dist_prefix $current_dist) # sometimes make install doesn't try to pre-create the dest dirs mkdir -p ./${prefix}/man/man1 ./${prefix}/man/man3 ./${prefix}/share/man/man1 ./${prefix}/share/man/man3 ./${prefix}/inc ./${prefix}/include ./${prefix}/bin ./${prefix}/lib # some dists understand DESTDIR but not combined with prefix for p in man share inc include bin lib; do ln -s ./${prefix}/$p $p done cd .. ORIG_LIBRARY_PATH="$LIBRARY_PATH" unset LIBRARY_PATH if grep -Eq 'DESTDIR|cmake_install\.cmake' $(find . -name Makefile -o -name makefile -o -name '*.mk' -o -name '*.mak') 2>/dev/null; then echo_eval_run $MAKE $(dist_install_target $current_dist) $(dist_make_args $current_dist) prefix="${prefix}" PREFIX="${prefix}" DESTDIR="$PWD/destdir" "$@" || : else echo_eval_run $MAKE $(dist_install_target $current_dist) $(dist_make_args $current_dist) prefix="$PWD/destdir${prefix}" PREFIX="$PWD/destdir${prefix}" INSTALL_PREFIX="$PWD/destdir${prefix}" INSTALL_ROOT="$PWD/destdir${prefix}" INSTALLTOP="/..${prefix}/" "$@" || : fi export LIBRARY_PATH="$ORIG_LIBRARY_PATH" } # assumes make install has run into ./destdir install_dist() { current_dist=$1 [ -n "$current_dist" ] || die 'install_dist: dist name required' [ -d destdir ] || die 'install_dist: ./destdir does not exist' prefix=$(dist_prefix $current_dist) rel_prefix=${prefix#/} # if there is an extra prefix, like e.g. 'msys64' on msys2 before 'usr/', # remove it if ([ "$(list_length destdir/*)" -eq 1 ] && [ ! -d "destdir${prefix}" ]) || \ ([ "$(list_length destdir/*)" -eq 2 ] && [ "$(find destdir${prefix} -type f 2>/dev/null | wc -l)" -eq 0 ]); then mv "destdir/${prefix}"/* tmp-usr rm -rf destdir/* mkdir -p "destdir${prefix%/*}" mv tmp-usr "destdir${prefix}" fi # if there is no prefix in the destdir, create it if [ ! -d "destdir${prefix}" ]; then find destdir -maxdepth 1 -mindepth 1 | \ while read -r installed; do mkdir -p "destdir${prefix}" mv "$installed" "destdir${prefix}" done fi # move libs out of platforms dirs like lib/x86_64-linux-gnu/ and lib64/ # and adjust pkgconfig files dest_lib_dir="destdir${prefix}/lib" [ -n "$target_platform" ] && dest_platform_lib_dir="$dest_lib_dir/$target_platform" [ -n "$bits" ] && dest_bits_lib_dir="destdir${prefix}/lib$bits" for platf_dir in "$dest_platform_lib_dir" "$dest_bits_lib_dir"; do if [ -n "$platf_dir" ] && [ -d "$platf_dir" ]; then if [ -d "$platf_dir/pkgconfig" ]; then sed -i.bak "s,lib/$target_platform,lib,g" "$platf_dir/pkgconfig"/*.pc rm -f "$platf_dir/pkgconfig"/*.pc.bak fi mkdir -p "$dest_lib_dir" (cd "$platf_dir"; $TAR -cf - .) | (cd "$dest_lib_dir"; $TAR -xf -) rm -rf "$platf_dir" fi done # copy platform includes to the regular include dirs IFS=$NL for platform_inc_dir in $(find "destdir${prefix}/lib/" -mindepth 2 -maxdepth 2 -type d -name include 2>/dev/null || :); do IFS=$OIFS ( inc_dir=${platform_inc_dir%/*} inc_dir="destdir${prefix}/include/${inc_dir##*/}" mkdir -p "$inc_dir" (cd "$platform_inc_dir"; $TAR -cf - .) | (cd "$inc_dir"; $TAR -xf -) ) done IFS=$OIFS # check that key file was built check_install_artifact_relative "$current_dist" "destdir${prefix}" # when cross compiling, resolve build root to host or target inst_root=$(resolve_link "$BUILD_ROOT/root") inst_root="$inst_root/${rel_prefix#usr}" # build file list and sed script to replace file paths in text files and # scripts file_list="$TMP_DIR/file_list_$$.txt" rm -f "$file_list" (cd "destdir"; IFS=$NL; find "./$prefix" etc 2>/dev/null | while read -r f; do IFS=$OIFS f=$(normalize_relative_path "$f") [ -n "$f" ] || continue putsln "$f" >> "$file_list" done) IFS=$OIFS [ -f "$file_list" ] sed_scr="$TMP_DIR/sed_scr_$$.sed" sed_scr_usr="$TMP_DIR/sed_scr_usr_$$.sed" sed_scr_etc="$TMP_DIR/sed_scr_etc_$$.sed" rm -f "$sed_scr" "$sed_scr_usr "$sed_scr_etc"" # build sed script using shortest possible common paths, # ignoring docs, man and info pages and top level dirs IFS=$NL escaped_prefix=$(puts "$rel_prefix" | sed 's,/,\\/,g') sed " /^[^/]*\$/d /^${escaped_prefix}\\/man\$/d /^${escaped_prefix}\\/man\\//d /^${escaped_prefix}\\/share\\/doc\$/d /^${escaped_prefix}\\/share\\/doc\\//d /^${escaped_prefix}\\/share\\/man\$/d /^${escaped_prefix}\\/share\\/man\\//d /^${escaped_prefix}\\/share\\/info\$/d /^${escaped_prefix}\\/share\\/info\\//d /^${escaped_prefix}\\/[^/][^/]*\$/d s|^\\(${escaped_prefix}/[^/][^/]*/[^/][^/]*\\)/[^/].*|\\1| s|^\\(etc/[^/][^/]*\\)/[^/].*|\\1| " "$file_list" | sort -u | \ while read -r f; do IFS=$OIFS variants=$f [ "$f" != "${f%.exe}" ] && variants="$variants ${f%.exe}" for f in $variants; do case "$f" in ${rel_prefix}/*) f=${f#${rel_prefix}/} cat >>"$sed_scr_usr" <>"$sed_scr_usr" <"${sed_scr}.work" <<'EOF' /\/usr/{ EOF # also add special rules to rewrite 'prefix' variables in scripts cat >>"${sed_scr}.work" <>"${sed_scr}.work" <>"${sed_scr}.work" <>"${sed_scr}.work" </dev/null || : # rewrite symlinks pointing to /usr/* if [ -h "$tmp_prefix/$f" ]; then link_dest=$(expr "$(ls -l "$tmp_prefix/$f")" : '.* -> \(.*\)$' | sed 's|^/usr/|'"$inst_root/|") # rewrite relative links to absolute ones case "$link_dest" in /*) ;; *) link_dest="$PWD/${dest_f%/*}/$link_dest" ;; esac link_dest=$(fully_resolve_link "$link_dest") if [ -e "$link_dest" ]; then echo_run ln -sf "$link_dest" "$dest_f" || : else # this is for windows as well, where symlinks can't point to a # file that doesn't (yet) exist defer_cmds="$defer_cmds ln -sf \"$link_dest\" \"$dest_f\" || : " fi continue fi # don''t relocate headers, man and info pages and docs case "$dest_f" in share/doc/*|share/man/*|share/info/*|include/*) echo_run cp -af "$tmp_prefix/$f" "$dest_f" || echo_run cp -rf "$tmp_prefix/$f" "$dest_f" continue ;; esac if file "$tmp_prefix/$f" | grep -Eiq ':.*text'; then ( start_job write_job_info dist_name "$current_dist" write_job_info file_name "$tmp_prefix/$f" if [ -x "$tmp_prefix/$f" ]; then putsln "Relocating executable script: $dest_f" else putsln "Relocating text file: $dest_f" fi { LANG=C sed -f "$sed_scr" "$tmp_prefix/$f" >"$dest_f" # rewrite prefix in pkgconfig and libtool files case "$dest_f" in lib/*.l[ao]|lib/pkgconfig/*.pc|share/pkgconfig/*.pc) cp "$dest_f" "${dest_f}.work" LANG=C sed ' /\/usr/{ s|/usr/local$|/USRLOCAL| s|/usr/local/|/USRLOCAL/|g s|\([^a-zA-Z0-9]\)/usr$|\1'"$inst_root"'| s|\([^a-zA-Z0-9]\)/usr/|\1'"$inst_root/"'|g s|\(-[IL]\)/usr/|\1'"$inst_root/"'|g s|/USRLOCAL/|/usr/local/|g s|/USRLOCAL$|/usr/local| } ' "${dest_f}.work" > "$dest_f" rm -f "${dest_f}.work" ;; esac } 2>&1 | write_job_output write_job_exit_status if [ -x "$tmp_prefix/$f" ]; then chmod +x "$dest_f" ; fi ) & running_jobs="$running_jobs $!" wait_jobs running_jobs $max_jobs continue fi echo_run cp -af "$tmp_prefix/$f" "$dest_f" || echo_run cp -rf "$tmp_prefix/$f" "$dest_f" # when cross-compiling, link arch-suffixed libs to their normal names if [ -n "$target_arch" ]; then case "$f" in */lib/*-${target_arch}.a) echo_run ln -sf "$PWD/$dest_f" "${dest_f%%-${target_arch}.a}.a" ;; esac fi done IFS=$OIFS wait_all_jobs running_jobs cleanup_jobs if [ -n "$defer_cmds" ]; then message "making deferred links..." IFS=$NL for cmd in $defer_cmds; do IFS=$OIFS eval echo_run "$cmd" done IFS=$OIFS fi cd "$OLDPWD" rm -f "$file_list" "$sed_scr" # things in build env may depend on what was just installed eval "$BUILD_ENV" # find new things in PATH hash -r } relocation_failed() { error "Relocating file '$file_name' from '$current_dist' failed:${NL}${NL}$(cat "$TMP_DIR/job_output/$1")" exit 1 } normalize_relative_path() { p=$1 [ -n "$p" ] || die 'normalize_relative_path: path required' p=${p#.} while :; do case "$p" in /*) p=${p#/} ;; */) p=${p%/} ;; *) break ;; esac done putsln "$p" } echo_run() { putsln "Executing: $(cmd_with_quoted_args "$@")" "$@" } echo_eval_run() { putsln "Executing: $@" eval "$@" } cmd_with_quoted_args() { [ -n "$1" ] || error 'cmd_with_quoted_args: command required' res="$1 " shift for arg; do res="$res '$arg'" done puts "$res" } remove_drive_prefix() { path=$1 [ -n "$path" ] || die 'remove_drive_prefix: path required' if [ -n "$msys2" ]; then path=${path#/[a-zA-Z]/} elif [ -n "$cygwin" ]; then path=${path#/cygdrive/[a-zA-Z]/} fi # remove windows drive prefixes such as c: path=${path#[a-zA-Z]:} # remove all but one slash at the beginning (double slashes have special meaning on windows) while :; do case "$path" in /*) path=${path#/} ;; *) break ;; esac done puts "/$path" } list_get() { pos=$1 [ -n "$pos" ] || die 'list_get: position to retrieve required' shift i=0 for item; do if [ $i -eq $pos ]; then puts "$item" return 0 fi i=$((i + 1)) done } list_index() { item=$1 [ -n "$item" ] || die 'list_index: item to find required' shift i=0 for element; do if [ "$element" = "$item" ]; then puts $i return 0 fi i=$((i + 1)) done return 1 } dist_args() { current_dist=$1 [ -n "$current_dist" ] || die 'dist_args: dist name required' buildsys=$2 case "$buildsys" in autoconf) puts "$CONFIGURE_ARGS $(table_line DIST_ARGS $current_dist)" || : ;; cmake) puts "$CMAKE_ARGS $(table_line DIST_ARGS $current_dist)" || : ;; meson) puts "$MESON_ARGS $(table_line DIST_ARGS $current_dist)" || : ;; perl) puts "$(table_line DIST_ARGS $current_dist)" || : ;; python) puts "$(table_line DIST_ARGS $current_dist)" || : ;; *) die "dist_args: buildsystem type required, must be 'autoconf', 'cmake' or 'perl'" ;; esac } dist_prefix() { current_dist=$1 [ -n "$current_dist" ] || die 'dist_prefix: dist name required' prefix=$(table_line DIST_PREFIX $current_dist) || : [ -n "$prefix" ] || prefix=/usr while :; do case "$prefix" in */) prefix=${prefix%/} ;; *) break ;; esac done puts "$prefix" } dist_tar_args() { current_dist=$1 [ -n "$current_dist" ] || die 'dist_tar_args: dist name required' puts "$(table_line DIST_TAR_ARGS $current_dist)" || : } dist_configure_override() { current_dist=$1 [ -n "$current_dist" ] || die 'dist_configure_override: dist name required' puts "$(table_line DIST_CONFIGURE_OVERRIDES $current_dist)" || : } dist_install_target() { current_dist=$1 [ -n "$current_dist" ] || die 'dist_install_override: dist name required' target="$(table_line DIST_INSTALL_TARGETS $current_dist)" || : [ -z "$target" ] && target=install puts "$target" } dist_install_override() { current_dist=$1 [ -n "$current_dist" ] || die 'dist_install_override: dist name required' puts "$(table_line DIST_INSTALL_OVERRIDES $current_dist)" || : } dist_build_override() { current_dist=$1 [ -n "$current_dist" ] || die 'dist_build_override: dist name required' puts "$(table_line DIST_BUILD_OVERRIDES $current_dist)" || : } dist_configure_type() { current_dist=$1 [ -n "$current_dist" ] || die 'dist_configure_type: dist name required' puts "$(table_line DIST_CONFIGURE_TYPES $current_dist)" || : } dist_relocation_type() { current_dist=$1 [ -n "$current_dist" ] || die 'dist_relocation_type: dist name required' puts "$(table_line DIST_RELOCATION_TYPES $current_dist)" || : } dist_make_args() { current_dist=$1 [ -n "$current_dist" ] || die 'dist_make_args: dist name required' puts "$ALL_MAKE_ARGS $(table_line DIST_MAKE_ARGS $current_dist)" || : } dist_ninja_args() { current_dist=$1 [ -n "$current_dist" ] || die 'dist_ninja_args: dist name required' _num_cpus=$NUM_CPUS # ninja hits the open file limit on windows [ "$os" = windows ] && [ $_num_cpus -gt 32 ] && _num_cpus=32 puts "-v $(table_line DIST_MAKE_ARGS $current_dist) -j $_num_cpus" || : } dist_make_install_args() { current_dist=$1 [ -n "$current_dist" ] || die 'dist_make_install_args: dist name required' puts "$(table_line DIST_MAKE_INSTALL_ARGS $current_dist)" || : } dist_extra_cppflags() { current_dist=$1 [ -n "$current_dist" ] || die 'dist_extra_cppflags: dist name required' puts "$(table_line DIST_EXTRA_CPPFLAGS $current_dist)" || : } dist_extra_cflags() { current_dist=$1 [ -n "$current_dist" ] || die 'dist_extra_cflags: dist name required' puts "$(table_line DIST_EXTRA_CFLAGS $current_dist)" || : } dist_extra_cxxflags() { current_dist=$1 [ -n "$current_dist" ] || die 'dist_extra_cxxflags: dist name required' puts "$(table_line DIST_EXTRA_CXXFLAGS $current_dist)" || : } dist_extra_objcxxflags() { current_dist=$1 [ -n "$current_dist" ] || die 'dist_extra_objcxxflags: dist name required' puts "$(table_line DIST_EXTRA_OBJCXXFLAGS $current_dist)" || : } dist_extra_ldflags() { current_dist=$1 [ -n "$current_dist" ] || die 'dist_extra_ldflags: dist name required' puts "$(table_line DIST_EXTRA_LDFLAGS $current_dist)" || : } dist_extra_libs() { current_dist=$1 [ -n "$current_dist" ] || die 'dist_extra_libs: dist name required' puts "$(table_line DIST_EXTRA_LIBS $current_dist)" || : } dist_patch() { current_dist=$1 [ -n "$current_dist" ] || die 'dist_patch: dist name required' _patch_level=-p1 for _patch_url in $(table_line DIST_PATCHES $current_dist); do case "$_patch_url" in -p*) _patch_level=$_patch_url continue ;; esac _patch_file=${_patch_url##*/} _patch_file=${_patch_file%%\?*} if [ ! -f "$_patch_file" ]; then puts "${NL}Applying patch $_patch_url to $current_dist${NL}${NL}" $CURL -SsL "$_patch_url" -o "$_patch_file" patch -l $_patch_level < "$_patch_file" # reset patch level to 1 which is default _patch_level=-p1 done_msg else puts "${NL}Patch $_patch_url to $current_dist is already appplied...${NL}${NL}" fi done } dist_pre_build() { current_dist=$1 [ -n "$current_dist" ] || die 'dist_pre_build: dist name required' if _cmd=$(table_line DIST_PRE_BUILD $current_dist); then puts "${NL}Running pre-build for: $current_dist:${NL}$_cmd${NL}${NL}" eval "$_cmd" fi } dist_post_unpack() { current_dist=$1 [ -n "$current_dist" ] || die 'dist_post_unpack: dist name required' if _cmd=$(table_line DIST_POST_UNPACK $current_dist); then puts "${NL}Running post-unpack for: $current_dist:${NL}$_cmd${NL}${NL}" eval "$_cmd" fi } dist_post_configure() { current_dist=$1 [ -n "$current_dist" ] || die 'dist_post_configure: dist name required' if _cmd=$(table_line DIST_POST_CONFIGURE $current_dist); then puts "${NL}Running post-configure for: $current_dist:${NL}$_cmd${NL}${NL}" eval "$_cmd" fi # sometimes PREFIX/include gets added to header search # definitely don't want this # also definitely don't want any kind of -Werror find . -name Makefile | while IFS=$NL read -r make_file; do sed -i.bak ' s,-I/usr/include , ,g s,-I/usr/include$,,g s,-Werror[^ ]* , ,g s,-Werror[^ ]*$,,g ' "$make_file" done } dist_post_build() { current_dist=$1 [ -n "$current_dist" ] || die 'dist_post_build: dist name required' if _cmd=$(table_line DIST_POST_BUILD $current_dist); then puts "${NL}Running post-build for: $current_dist:${NL}$_cmd${NL}${NL}" eval "$_cmd" fi } install_docbook_dist() { _type=$1 _dist_ver=$(echo "$PWD" | sed 's/.*[^0-9.]\([0-9.]*\)$/\1/') case "$_type" in stylesheet) _dir="stylesheet/${PWD##*/}" ;; schema) _dir="schema/dtd/$_dist_ver" ;; *) die "install_docbook_dist: type of dist required, must be 'stylesheet' or 'schema'" ;; esac _dir="$BUILD_ROOT/root/share/xml/docbook/$_dir" echo_run mkdir -p "$_dir" echo_run cp -af * "$_dir" || echo_run cp -rf * "$_dir" # on cygwin/msys write native POSIX paths to catalog _dir=$(cygpath -m "$_dir") if [ -f "$_dir/catalog.xml" ]; then echo_run xmlcatalog --noout --del "file://$_dir/catalog.xml" "$(cygpath -m "$BUILD_ROOT/root/etc/xml/catalog.xml")" || : echo_run xmlcatalog --noout --add nextCatalog '' "file://$_dir/catalog.xml" "$(cygpath -m "$BUILD_ROOT/root/etc/xml/catalog.xml")" fi } install_fonts() { if [ -d fontconfig ]; then install -v -m644 fontconfig/*.conf "$BUILD_ROOT/root/etc/fonts/conf.d" fi font_found= IFS=$NL for ttf in $(find . -name '*.ttf' -o -name '*.TTF' -o -name '*.pfm' -o -name '*.PFM' -o -name '*.pfb' -o -name '*.PFB' -o -name '*.afb' -o -name '*.AFB'); do IFS=$OIFS font_found=1 if [ ! -d "$BUILD_ROOT/root/share/fonts/${PWD##*/}" ]; then install -v -d -m755 "$BUILD_ROOT/root/share/fonts/${PWD##*/}" fi install -v -m644 "$ttf" "$BUILD_ROOT/root/share/fonts/${PWD##*/}" done IFS=$OIFS [ -n "$font_found" ] && echo_run fc-cache -fv "$BUILD_ROOT/root/share/fonts/${PWD##*/}" } table_line() { table=$1 [ -n "$table" ] || die 'table_line: table name required' name=$2 [ -n "$name" ] || die 'table_line: item name required' table=$(table_contents $table) IFS=$NL for line in $table; do IFS=$OIFS set -- $line if [ "$1" = "$name" ]; then shift puts "$@" return 0 fi done IFS=$OIFS return 1 } table_line_append() { table=$1 [ -n "$table" ] || die 'table_line_append: table name required' name=$2 [ -n "$name" ] || die 'table_line_append: item name required' append_str=$3 [ -n "$append_str" ] || die 'table_line_append: string to append required' table_name=$table table=$(table_contents $table) new_table= line_appended= IFS=$NL for line in $table; do IFS=$OIFS set -- $line if [ "$1" = "$name" ]; then new_table="${new_table}$@ ${append_str}${NL}" line_appended=1 else new_table="${new_table}${@}${NL}" fi done IFS=$OIFS if [ -z "$line_appended" ]; then # make new entry new_table="${new_table}${name} ${append_str}${NL}" fi eval "$table_name=\$new_table" } table_line_replace() { table=$1 [ -n "$table" ] || die 'table_line_replace: table name required' name=$2 [ -n "$name" ] || die 'table_line_replace: item name required' set_str=$3 [ -n "$set_str" ] || die 'table_line_replace: string to set required' table_name=$table table=$(table_contents $table) new_table= line_found= IFS=$NL for line in $table; do IFS=$OIFS set -- $line if [ "$1" = "$name" ]; then new_table="${new_table}$1 ${set_str}${NL}" line_found=1 else new_table="${new_table}${@}${NL}" fi done IFS=$OIFS if [ -z "$line_found" ]; then # make new entry new_table="${new_table}${name} ${set_str}${NL}" fi eval "$table_name=\$new_table" } table_insert_after() { table=$1 [ -n "$table" ] || die 'table_insert_after: table name required' name=$2 [ -n "$name" ] || die 'table_insert_after: item name to insert after required' new_line=$3 [ -n "$new_line" ] || die 'table_insert_after: new line required' table_name=$table table=$(table_contents $table) new_table= line_found= IFS=$NL for line in $table; do IFS=$OIFS set -- $line new_table="${new_table}${@}${NL}" if [ "$1" = "$name" ]; then new_table="${new_table}${new_line}${NL}" line_found=1 fi done IFS=$OIFS [ -n "$line_found" ] || error 'table_insert_after: item to insert after not found' eval "$table_name=\$new_table" } table_insert_before() { table=$1 [ -n "$table" ] || die 'table_insert_before: table name required' name=$2 [ -n "$name" ] || die 'table_insert_before: item name to insert before required' new_line=$3 [ -n "$new_line" ] || die 'table_insert_before: new line required' table_name=$table table=$(table_contents $table) new_table= line_found= IFS=$NL for line in $table; do IFS=$OIFS set -- $line if [ "$1" = "$name" ]; then new_table="${new_table}${new_line}${NL}" line_found=1 fi new_table="${new_table}${@}${NL}" done IFS=$OIFS [ -n "$line_found" ] || die 'table_insert_before: item to insert before not found' eval "$table_name=\$new_table" } table_line_remove() { table=$1 [ -n "$table" ] || die 'table_line_remove: table name required' name=$2 [ -n "$name" ] || die 'table_line_remove: item name required' table_name=$table table=$(table_contents $table) new_table= IFS=$NL for line in $table; do IFS=$OIFS set -- $line if [ "$1" != "$name" ]; then new_table="${new_table}${@}${NL}" fi done IFS=$OIFS eval "$table_name=\$new_table" } find_checkout() { ( cd "$(dirname "$0")" while [ "$PWD" != / ]; do if [ -f src/wx/wxvbam.h ]; then puts "$PWD" exit 0 fi cd .. done exit 1 ) || die 'cannot find project checkout' } error() { puts >&2 "${NL}ERROR: $@${NL}${NL}" } warn() { puts >&2 "${NL}WARNING: $@${NL}${NL}" } message() { puts >&2 "${NL}INFO: $@${NL}${NL}" } die() { error "$@" exit 1 } build_project() { puts "${NL}Building project: $CHECKOUT${NL}${NL}" dist_pre_build project mkdir -p "$BUILD_ROOT/project" cd "$BUILD_ROOT/project" rm -rf visualboyadvance-m.exe visualboyadvance-m.app lto=ON # FIXME: LTO still broken on 64 bit mingw, and now 32 bit mingw too if [ "$target_os" = windows ]; then lto=OFF fi rm -rf release debug mkdir -p release debug # Release build. puts "${NL}Building Release...${NL}${NL}" cd release echo_eval_run cmake "'$CHECKOUT'" $CMAKE_REQUIRED_ARGS -DVBAM_STATIC=ON -DENABLE_LTO=${lto} -DUPSTREAM_RELEASE=TRUE $CMAKE_ARGS $PROJECT_ARGS -G Ninja $@ echo_run ninja -j$NUM_CPUS -v dist_post_build project cd .. # Debug build. puts "${NL}Building Debug...${NL}${NL}" cd debug echo_eval_run cmake "'$CHECKOUT'" $CMAKE_REQUIRED_ARGS -DVBAM_STATIC=ON -DENABLE_LTO=${lto} -DUPSTREAM_RELEASE=TRUE $CMAKE_ARGS $PROJECT_ARGS -DCMAKE_BUILD_TYPE=Debug -G Ninja $@ echo_run ninja -j$NUM_CPUS -v dist_post_build project cd .. puts "${NL}Build Successful!!!${NL}${NL}Build results can be found in: $BUILD_ROOT/project${NL}${NL}" } duplicate_dist() { src_dist=$1 [ -n "$src_dist" ] || die 'duplicate_dist: source dist required' dest_dist=$2 [ -n "$dest_dist" ] || die 'duplicate_dist: destination dist required' IFS=$NL for table in DISTS $(set | sed -n 's/^\(DIST_[A-Z_]*\)=.*/\1/p'); do IFS=$OIFS if line=$(table_line $table $src_dist); then table_insert_after $table $src_dist "$dest_dist $line" fi done IFS=$OIFS } table_column() { table=$1 [ -n "$table" ] || die 'table_column: table name required' col=$2 [ -n "$col" ] || die 'table_column: column required' row_size=$3 [ -n "$row_size" ] || die 'table_column: row_size required' table=$(table_contents $table) i=0 res= for item in $table; do if [ $((i % row_size)) -eq "$col" ]; then res="$res $item" fi i=$((i + 1)) done puts "$res" } table_rows() { table=$1 [ -n "$table" ] || die 'table_rows: table name required' table=$(table_contents $table) i=0 IFS=$NL for line in $table; do i=$((i + 1)) done IFS=$OIFS puts $i } table_contents() { table=$1 [ -n "$table" ] || die 'table_contents: table name required' # filter comments and blank lines eval puts "\"\$$table\"" | grep -Ev '^ *(#|$)' || : } list_contains() { _item=$1 [ -n "$_item" ] || die 'list_contains: item required' shift for _pos; do [ "$_item" = "$_pos" ] && return 0 done return 1 } list_length() { puts $# } list_remove_duplicates() { _seen= for _item; do if ! list_contains $_item $_seen; then _seen="$_seen $_item" fi done echo $_seen } install_artifact() { full= if [ "$1" = "-f" ]; then full=1 shift fi current_dist=$1 [ -n "$current_dist" ] || die 'install_artifact: dist name required' prefix=$(dist_prefix $current_dist) prefix=${prefix#/usr} set -- $(table_line DISTS $current_dist) eval "path=\"\$$#\"" # for cross builds, the files are absolute paths into the host and target # trees case "$path" in /*) if [ -n "$full" ]; then puts "$path" else puts "$(install_artifact_relative "$current_dist")" fi return 0 ;; esac if [ -n "$full" ]; then puts "$BUILD_ROOT/root${prefix}/${path}" else puts "$path" fi } check_install_artifact() { current_dist=$1 [ -n "$current_dist" ] || die 'check_install_artifact: dist name required' if ! path_exists "$(install_artifact -f $current_dist)"; then die "$current_dist: target file not found after install" fi } check_install_artifact_relative() { current_dist=$1 [ -n "$current_dist" ] || die 'check_install_artifact_relative: dist name required' root=$2 [ -n "$root" ] || die 'check_install_artifact_relative: directory root relative to required' if ! path_exists "${root}/$(install_artifact_relative $current_dist)"; then die "$current_dist: target file not found in unpack directory" fi } install_artifact_relative() { current_dist=$1 [ -n "$current_dist" ] || die 'install_artifact_relative: dist name required' set -- $(table_line DISTS $current_dist) eval "path=\"\$$#\"" # for cross builds, the files are absolute paths into the host and target # trees puts "$path" | sed 's, *'"$BUILD_ROOT"'/[^/]*/,,' } echo() { if [ -n "$BASH_VERSION" -a "$os" != mac ]; then builtin echo -e "$@" else command echo "$@" fi } puts() { [ $# -gt 0 ] || return 0 printf '%s' "$1" shift for _str; do printf ' %s' "$_str" done } putsln() { puts "$@" printf '\n' } path_exists() { [ -z "$1" ] && return 1 if [ -e "$1" ] || [ -L "$1" ] || [ -d "$1" ]; then return 0 fi # check unquoted versions in case of globs # but must escape spaces first escaped=$(gsub ' ' '\ ' "$1") [ -e $escaped ] || [ -L $escaped ] || [ -d $escaped ] } gsub() { match=$1 repl=$2 shift; shift; res= str="$@" while [ -n "$str" ]; do case "$str" in *$match*) res="$res${str%%$match*}$repl" str="${str#*$match}" ;; *) res="$res$str" break ;; esac done printf '%s' "$res" } # on msys2 `ln -sf` to an existing link silently fails # so delete it first ln() { if [ $# -eq 3 ] && [ "$1" = "-sf" ] && [ -h "$3" ]; then rm -f "$3" fi command ln "$@" } cygpath() { if command -v cygpath >/dev/null; then command cygpath "$@" else case "$1" in -*) shift ;; esac echo "$@" fi } gpg() { if command -v gpg >/dev/null; then command gpg "$@" elif command -v gpg2 >/dev/null; then command gpg2 "$@" else warn 'GPG not available' fi } command() { if [ -x /bin/command ]; then /bin/command "$@" elif [ -x /usr/bin/command ]; then /usr/bin/command "$@" else /bin/sh -c 'command "$@"' -- "$@" fi } fully_resolve_link() { file=$1 # get initial part for non-absolute path, or blank for absolute path=${file%%/*} # and set $file to the rest file=${file#*/} OLDIFS=$IFS IFS='/' for part in $file; do [ ! -z "$part" ] && path=$(resolve_link "$path/$part") done IFS=$OLDIFS # remove 'foo/..' path parts while :; do case "$path" in */../*|*/..) path=$(echo "$path" | sed 's,//*[^/][^/]*//*\.\./*,/,g') ;; *) break ;; esac done # remove trailing /s while [ "$path" != "${path%/}" ]; do path=${path%/} done echo "$path" } resolve_link() { file=$1 while [ -h "$file" ]; do ls0=$(ls -ld "$file") new_link=$(expr "$ls0" : '.* -> \(.*\)$') if expr "$new_link" : '/.*' > /dev/null; then file="$new_link" else file="${file%/*}"/"$new_link" fi done echo "$file" } #cpanm() { # if command -v cpanm >/dev/null; then # cpanm "$@" # else # # why the fuck does this segfault? # perl -MApp::cpanminus::fatscript -le 'my $c = App::cpanminus::script->new; $c->parse_options(@ARGV); $c->doit;' -- "$@" # fi #} # this needs to run on source, not just after entry setup