#!/bin/sh if [ -z "$1" -o x$1 == x-h -o x$1 == x--help ]; then echo "" echo " build " echo "" echo " sources are expected in " echo " special value for arch: 'native' doesn't use r_arch at all." echo "" echo " Optional env. settings:" echo " BASE - abs. path to build system base" echo " PKGTYPE - install.packages() default type (defaults to mac.binary)" echo " XTRAMAKEF - make flags to append" echo " FORCE_OS_VERSION - force cross-build for particular Darwin verison" echo " skip_build - if set to something existing tar ball is used" echo "" exit 0; fi : ${BASE=/Volumes/Builds/R4} if [ ! -e "$BASE" ]; then echo "*** WARNING: BASE ($BASE) does not exist, falling back to current directory" BASE="`pwd`" fi # set -x : ${TAR=tar} RBUILDS=$BASE ## for oscode, ARCH, TNAME . $BASE/common RD="$1" if [ -z "$RD" ]; then echo "ERROR missing R directory to build" >&2 exit 1 fi tarch=$ARCH ## TARCH is used for R_ARCH mutli-arch builds unless "native" TARCH=native TNAMEWOA=`echo $TNAME|sed 's:-.*::'` ## big-sur has a separate package tree if [ "$oscode" = big-sur ]; then PKGSUFFIX=".$TNAME" fi : ${PKGTYPE=mac.binary$PKGSUFFIX} if [ -z "$JOBID" ]; then JOBID=build-$TNAME-$RD-$$-`date +%s` export JOBID fi LOCKJOB=`cat "$BASE/LOCK" 2>/dev/null` if [ -n "$LOCKJOB" ]; then if [ "$LOCKJOB" != "$JOBID" ]; then echo "ERROR: build locked by $LOCKJOB (I am $JOBID)" >&2 exit 1 fi locked=no else locked=yes echo $JOBID > "$BASE/LOCK" fi ## arm build uses /opt/R if [ -e /opt/R/$ARCH ]; then PREFIX=/opt/R/$ARCH else PREFIX=/usr/local fi PATH=$PREFIX/bin:$PATH if [ -z $(which gfortran 2>/dev/null) ]; then if [ -e /opt/gfortran/bin/gfortran ]; then PATH=/opt/gfortran/bin:$PATH else echo "** ERROR: cannot find GNU Fortran **" >&2 exit 1 fi fi ## it is better to ship with Apple stubs than a particular version #JH=`/usr/libexec/java_home` #if [ -n "$JH" ]; then # PATH=$JH/bin:$PATH #fi for texpath in /opt/TinyTex/bin /opt/texinfo/bin /Library/TeX/texbin; do if [ -e "$texpath" ]; then PATH="$texpath:$PATH" break fi done RBASE="$BASE/$RD" ## NOTE: the precedence has changed, we prefer our libraries to Xquartz, ## because it is no longer updated PKG_CONFIG_PATH=/usr/lib/pkgconfig:$PREFIX/lib/pkgconfig:$PREFIX/share/pkgconfig:/opt/X11/lib/pkgconfig:/opt/X11/share/pkgconfig export PKG_CONFIG_PATH CONSH=$BASE/consh host=`hostname -s` ncpu=`/usr/sbin/sysctl hw.ncpu|sed -n 's/hw.ncpu: //p'` if [ -n "${ncpu}" ]; then : ${MAKEF=-j$ncpu} fi if [ -n "${XTRAMAKEF}" ]; then MAKEF="${MAKEF} ${XTRAMAKEF}" fi export PATH mkdir -p $BASE/$TNAME cd $BASE TS=`date +%s:%Y%m%d:%H%M%S` if [ $TARCH = native ]; then RARCH='' else RARCH="r_arch=$TARCH" fi echo "Building $RD for $TNAME (arch $TARCH, pkgType=\"${PKGTYPE}\", PREFIX=$PREFIX)" clang --version ## check available disk space before proceeding - we require at least 1GB to make sure DSKF=`df -g "$BASE/$TNAME" | awk '{print $4}' | tail -n 1` if [ "$DSFK" = 0 ]; then echo "***FATAL ERROR: out of disk space!" echo "FATAL ERROR: out of disk space" > $BASE/$TNAME/$RD.FAILED if [ $locked = yes ]; then rm -f "$BASE/LOCK" fi exit 1 fi ## check flags for tar - we want --no-xattrs on tars that support it if $TAR c --no-xattrs build > /dev/null; then TARFLAGS=--no-xattrs fi if [ -z "${skip_build}" ]; then build_ok=no now=`date +%s` BUILDSUBDIR="builds/$RD-$now-$$" BUILDDIR="$BASE/$TNAME/$BUILDSUBDIR" if [ -e "$BUILDDIR" ]; then echo "ERROR: $BUILDDIR already exists!" >&2 if [ $locked = yes ]; then rm -f "$BASE/LOCK" fi exit 1 fi mkdir -p $BUILDDIR mkdir -p "$BASE/$TNAME/$RD" 2>/dev/null ## for results echo "$TS:$RD:configure" >> $BUILDDIR/build.log mkdir -p $BUILDDIR/$RD cd $BUILDDIR/$RD use_build=no HOST=`$BASE/$RD/tools/config.guess` if [ -n "${FORCE_OS_VERSION}" ]; then HOST=`echo ${HOST}|sed "s/-darwin.*/-darwin${FORCE_OS_VERSION}/"` use_build=yes fi if [ $TARCH = ppc -a $ARCH = i386 ]; then HOST=`echo ${HOST}|sed s/^i386/powerpc/` use_build=yes fi if [ $TARCH = x86_64 -a $ARCH = i386 ]; then HOST=`echo ${HOST}|sed s/^i386/x86_64/` use_build=yes fi if [ ${use_build} = yes ]; then echo " (forcing build name $HOST)" RARCH="--build=$HOST $RARCH" fi CONFF=`cat $BASE/conf.$TNAME 2>/dev/null` GCONFF=`cat $BASE/conf.$TNAMEWOA 2>/dev/null` ## for big-sur builds we append "-" to FW_VERSION if [ $oscode = big-sur ]; then grep '^PACKAGE_VERSION=' $BASE/$RD/configure | head -n1 > $BUILDDIR/R-version.sh echo 'echo $PACKAGE_VERSION' >> $BUILDDIR/R-version.sh PACKAGE_VERSION=`sh $BUILDDIR/R-version.sh` FW_VERSION=`echo "${PACKAGE_VERSION}" | sed 's/[\.][0-9]$//'` FWOVERRIDE="FW_VERSION=${FW_VERSION}-$ARCH" fi echo "Using configure $RARCH $FWOVERRIDE $GCONFF $CONFF" TS=`date +%s:%Y%m%d:%H%M%S` set > "$BUILDDIR/env" echo "$TS:$RD:confcall $RARCH $FWOVERRIDE $GCONFF $CONFF" >> $BUILDDIR/build.log ${CONSH} "$BASE/$RD/configure $RARCH $FWOVERRIDE $GCONFF $CONFF" $BUILDDIR/$RD.conf CRES=$? TS=`date +%s:%Y%m%d:%H%M%S` echo "$TS:$RD:configure:$CRES" >> $BUILDDIR/build.log if [ $CRES = 0 ]; then cd $BUILDDIR/$RD echo "#define PLATFORM_PKGTYPE \"${PKGTYPE}\"" >> src/include/config.h echo "make $MAKEF" echo "$TS:$RD:make" >> $BUILDDIR/build.log ${CONSH} "make $MAKEF" $BUILDDIR/$RD.build MRES=$? TS=`date +%s:%Y%m%d:%H%M%S` echo "$TS:$RD:make:$MRES" >> $BUILDDIR/build.log if [ $MRES = 0 ]; then cd $BUILDDIR # create a build tar-ball, e.g. for check on another machine echo "$BUILDDIR" > $RD/build-base $TAR fcz $RD-$TNAME-bld.tar.gz $RD cd $BUILDDIR/$RD TS=`date +%s:%Y%m%d:%H%M%S` set > $BUILDDIR/build-check-env echo "make check" echo "$TS:$RD:check" >> $BUILDDIR/build.log ${CONSH} "make check" $BUILDDIR/$RD.check CR=$? TS=`date +%s:%Y%m%d:%H%M%S` echo "$TS:$RD:check:$CR" >> $BUILDDIR/build.log if [ $CR = 0 ]; then echo "SUCCESS" touch $BUILDDIR/$RD.SUCCESS echo $BUILDSUBDIR > $BUILDDIR/build-path ## on success replace "last-success" with the current build ln -sfn $BUILDDIR $BASE/$TNAME/$RD/last-success TS=`date +%s:%Y%m%d:%H%M%S` echo "$TS:$RD:build-success:$BUILDSUBDIR:$BASE/$TNAME/$RD/last-success" >> $BASE/$TNAME/build.log ln -sfn last-success $BASE/$TNAME/$RD/current build_ok=yes else echo "make check FAILED" > $BUILDDIR/$RD.FAILED ## add tails of failed test output to the log file (if any) FT=`ls tests/*/*.fail tests/*.fail 2>/dev/null` if [ -n "$FT" ]; then for ft in $FT; do echo '#@2@#====== FAILED TEST: ' "$ft" '@#2#@' >> $BUILDDIR/$RD.check tail -n 20 $ft >> $BUILDDIR/$RD.check done fi fi else echo "make FAILED" > $BUILDDIR/$RD.FAILED fi else echo "Configure FAILED" echo "configure FAILED" > $BUILDDIR/$RD.FAILED fi if [ "$build_ok" != yes ]; then ## on failure keep the build dir and symlink it TS=`date +%s:%Y%m%d:%H%M%S` echo "$TS:$RD:build-failed:$BUILDSUBDIR" >> $BASE/$TNAME/build.log ln -sfn $BUILDDIR $BASE/$TNAME/$RD/last-failed ln -sfn last-failed $BASE/$TNAME/$RD/current fi fi ## skip_build TS=`date +%s:%Y%m%d:%H%M%S` ####==== install -> framework if [ -e $BASE/$TNAME/$RD/current/$RD.SUCCESS ]; then LOGDIR=$BASE/$TNAME/$RD/current miss=yes failed=yes if [ -e "$BASE/$TNAME/$RD/current/$RD-$TNAME-bld.tar.gz" -a -e "$BASE/$TNAME/$RD/current/$RD.SUCCESS" ]; then echo "$TS:$RD:common:collect:0:$TNAME" >> $LOGDIR/build.log miss=no else echo "Missing build result for $RD-$TNAME $BASE/$TNAME/$RD/current/$RD-$TNAME-bld.tar.gz" >&2 echo "Missing build result for $RD-$TNAME" >> $LOGDIR/$RD.ERROR echo "$TS:$RD:common:collect:1:$TNAME" >> $LOGDIR/build.log fi if [ $miss = no ]; then failed=no echo "NOTE: logs in $LOGDIR" echo "Remove previous framework ..." $BASE/rmfw ## this is the setuid version to make sure ... RFWH=/Library/Frameworks/R.framework/Resources echo "$RD:$TNAME" cd $BASE/$TNAME/$RD/current/$RD TS=`date +%s:%Y%m%d:%H%M%S` echo "$RD:$TNAME:install" echo "$TS:$RD:$tarch:install" >> $LOGDIR/build.log make install > $LOGDIR/$RD.$tarch.inst 2> $LOGDIR/$RD.$tarch.inst.err echo "$TS:$RD:$tarch:install:$?" >> $LOGDIR/build.log ## additional parts echo "$RD:$TNAME:install-tests" make install-tests >> $LOGDIR/$RD.$tarch.inst 2>&1 echo "$RD:$TNAME:install-tests:$?" echo "$RD:$TNAME:install-pdf" make install-pdf >> $LOGDIR/$RD.$tarch.inst 2>&1 echo "$RD:$TNAME:install-pdf:$?" if [ $failed = yes ]; then echo "make install failed for $tarch" echo "make install failed for $tarch" >> $LOGDIR/$RD.FAILED fi TS=`date +%s:%Y%m%d:%H%M%S` echo "$TS:$RD:$tarch:install:$CR" >> $LOGDIR/build.log fi if [ $failed = no ]; then echo "$RD:$TNAME:fixup" ## fixup permissions (first run to make sure it's writable) $BASE/fixup ## determine full path to lib (via id entry in libR) LIBDIR=`otool -L /Library/Frameworks/R.framework/R | sed -n '/\/libR/s/.*\(\/Library.*\)\/libR.dylib.*/\1/p'` if [ -z "$LIBDIR" ]; then echo "ERROR: cannot determine R.framework paths!" if [ $locked = yes ]; then rm -f "$BASE/LOCK" fi exit 1 fi ## copy vecLib BLAS stub if present if [ -f "$BASE/libRblas.vecLib.dylib" ]; then cp -p "$BASE/libRblas.vecLib.dylib" "$LIBDIR/" install_name_tool -id "$LIBDIR/libRblas.dylib" "$LIBDIR/libRblas.vecLib.dylib" fi ## symlink BLAS to .0 if present if [ -e "$LIBDIR/libRblas.dylib" ]; then mv "$LIBDIR/libRblas.dylib" "$LIBDIR/libRblas.0.dylib" ln -s libRblas.0.dylib "$LIBDIR/libRblas.dylib" fi ## copy omp if present if [ -f "$BASE/libomp.dylib" ]; then cp -p "$BASE/libomp.dylib" "$LIBDIR/" install_name_tool -id "$LIBDIR/libomp.dylib" "$LIBDIR/libomp.dylib" fi ## /usr/local libraries ULL=`otool -L /Library/Frameworks/R.framework/Resources/lib/*.dylib | grep -E '^\t(/usr/local|/opt)' | grep -v X11 | sed -e 's:^.::' -e 's: (.*::' | sort | uniq` ## check in those as well ULL2=`otool -L $ULL | grep -E '^\t(/usr/local|/opt)' | grep -v X11 | sed -e 's:^.::' -e 's: (.*::' | sort | uniq` ULL="$ULL $ULL2" ## pass 1 : copy external libs for lib in $ULL; do echo " - copy $lib" libn=`basename $lib` cp -p $lib "$LIBDIR/" install_name_tool -id "$LIBDIR/$libn" "$LIBDIR/$libn" done ## pass 2 : adjust paths for lib in $ULL; do echo " - fix linked to $lib" libn=`basename $lib` chmod +w "$LIBDIR/"* 2> /dev/null for dst in `ls $LIBDIR/*.dylib`; do install_name_tool -change "${lib}" "$LIBDIR/$libn" $dst done done ## generate dSYMs for l in "$LIBDIR/"libR*.dylib; do echo " - generating dsym for $l" dsymutil "$l" done ## copy qpdf (if present) and set R_QPDF accordingly if [ -e "$BASE/qpdf" ]; then echo " - copy qpdf" cp "$BASE/qpdf" /Library/Frameworks/R.framework/Resources/bin/qpdf renv="/Library/Frameworks/R.framework/Resources/etc/Renviron" if [ -e "$renv" ]; then echo '## CRAN R ships with qpdf inside so use it unless directed otherwise' >> "$renv" echo 'R_QPDF=${R_QPDF-'"'/Library/Frameworks/R.framework/Resources/bin/qpdf'"'}' >> "$renv" fi fi # unpack fontconfig config files and include fc-cache if [ -e $BASE/fontconfig-add.tar.gz ]; then echo " - extract fontconfig-add.tar.gz" $TAR fxz $BASE/fontconfig-add.tar.gz -C "$RFWH" fi if [ -e $PREFIX/bin/fc-cache ]; then echo " - copy fc-cache" cp -p $PREFIX/bin/fc-cache $RFWH/bin/fc-cache fi # remove any existing cache rm -rf $RFWH/fontconfig/cache/* ARHOME=`dirname "$LIBDIR"` $BASE/fixpathR "$ARHOME" $BASE/fixup if [ -e $BASE/unlock-sign ]; then . $BASE/unlock-sign fi ## see if full siging works rm -f /tmp/sign-test touch /tmp/sign-test if codesign -s dev /tmp/sign-test; then $BASE/sign-dev /Library/Frameworks/R.framework else echo falling back to empty sig $BASE/sign-dev /Library/Frameworks/R.framework - fi rm /tmp/sign-test $TAR fcz $BASE/$TNAME/$RD/current/$RD.tar.gz $TARFLAGS -C / /Library/Frameworks/R.framework #mkdir -p "$BASE/deploy/$oscode/$RD" 2>/dev/null #cp $BASE/$RD-$TNAME.tar.gz "$BASE/deploy/$oscode/$RD/" cd $BASE echo "SUCCESS" touch $BASE/$TNAME/$RD/current/$RD.FW.SUCCESS fi # failed=no fi if [ $locked = yes ]; then rm -f "$BASE/LOCK" fi ## copy results to deployment repo rm -rf "$BASE/deploy/$oscode/$RD/$tarch" mkdir -p "$BASE/deploy/$oscode/$RD/$tarch" 2>/dev/null for f in "$RD.SUCCESS" "$RD.FAILED" "$RD.ERROR" "$RD.FW.SUCCESS" "$RD.tar.gz" "$RD.check" "$RD.conf" "$RD.build" check.err conf.err build.err check conf build build.log; do if [ -e "$BASE/$TNAME/$RD/current/$f" ]; then cp -p "$BASE/$TNAME/$RD/current/$f" "$BASE/deploy/$oscode/$RD/$tarch/$f"; fi done