#!/bin/bash # # This script creates a binary release of OpenSCAD. This should work # under Mac OS X, Linux 32bit, Linux 64bit, and Linux->Win32 MXE cross-build. # Windows under msys has not been tested recently. # # The script will create a file called openscad-. in # the current directory (or under ./mingw32 or ./mingw64) # # Usage: release-common.sh [-v ] [-c] [-mingw[32|64]] [-tests] # -v Version string (e.g. -v 2010.01) # -d Version date (e.g. -d 2010.01.23) # -mingw32 Cross-compile for win32 using MXE # -mingw64 Cross-compile for win64 using MXE # -snapshot Build a snapshot binary (make e.g. experimental features available, build with commit info) # -tests Build additional package containing the regression tests # # If no version string or version date is given, todays date will be used (YYYY-MM-DD) # If only version date is given, it will be used also as version string. # If no make target is given, release will be used on Windows, none one Mac OS X # # The mingw cross compile depends on the MXE cross-build tools. Please # see the README.md file on how to install these dependencies. To debug # the mingw-cross build process, set env var FAKEMAKE=1 to fake-make the # .exe files # # convert end-of-line in given file from unix \n to dos/windows(TM) \r\n # see https://kb.iu.edu/data/acux.html lf2crlf() { fname=$1 if [ "`command -v unix2dos`" ]; then unix2dos $fname return fi if [ "`command -v awk`" ]; then echo using awk to convert end of line markers in $fname awk 'sub("$", "\r")' $fname > $fname".temp" mv $fname".temp" $fname return fi echo 'warning- cant change eol to cr eol' } printUsage() { echo "Usage: $0 -v -d -c -mingw32 echo echo " Example: $0 -v 2010.01 } OPENSCADDIR=$PWD if [ ! -f $OPENSCADDIR/openscad.pro ]; then echo "Must be run from the OpenSCAD source root directory" exit 1 fi CONFIG=deploy if [[ "$OSTYPE" =~ "darwin" ]]; then OS=MACOSX elif [[ $OSTYPE == "msys" ]]; then OS=WIN elif [[ $OSTYPE == "linux-gnu" ]]; then OS=LINUX if [[ `uname -m` == "x86_64" ]]; then ARCH=64 else ARCH=32 fi echo "Detected build-machine ARCH: $ARCH" fi if [ "`echo $* | grep mingw32`" ]; then OS=UNIX_CROSS_WIN ARCH=32 echo Mingw-cross build using ARCH=32 fi if [ "`echo $* | grep mingw64`" ]; then OS=UNIX_CROSS_WIN ARCH=64 echo Mingw-cross build using ARCH=64 fi if [ "`echo $* | grep snapshot`" ]; then CONFIG="$CONFIG snapshot experimental" OPENSCAD_COMMIT=`git log -1 --pretty=format:"%h"` fi BUILD_TESTS= if [ "`echo $* | grep tests`" ]; then BUILD_TESTS=1 fi if [ $OS ]; then echo "Detected OS: $OS" else echo "Error: Couldn't detect OSTYPE" exit fi while getopts 'v:d:c' c do case $c in v) VERSION=$OPTARG;; d) VERSIONDATE=$OPTARG;; esac done if test -z "$VERSIONDATE"; then VERSIONDATE=`date "+%Y.%m.%d"` fi if test -z "$VERSION"; then VERSION=$VERSIONDATE fi export VERSIONDATE export VERSION if [ $FAKEMAKE ]; then echo 'fake make on:' $FAKEMAKE else FAKEMAKE= fi echo "Checking pre-requisites..." case $OS in UNIX_CROSS_WIN) MAKENSIS= if [ "`command -v makensis`" ]; then MAKENSIS=makensis elif [ "`command -v i686-pc-mingw32-makensis`" ]; then # we cant find systems nsis so look for the MXE's version. # MXE has its own makensis, but its only available under # 32-bit MXE. note that the cross-version in theory works # the same as the linux version so we can use them, in # theory, interchangeably. its not really a 'cross' nsis # todo - when doing 64 bit mingw build, see if we can call # 32bit nsis here. MAKENSIS=i686-pc-mingw32-makensis else echo "makensis not found. please install nsis on your system." echo "(for example, on debian linux, try apt-get install nsis)" exit 1 fi echo NSIS makensis found: $MAKENSIS ;; esac if [ ! -e $OPENSCADDIR/libraries/MCAD/__init__.py ]; then echo "Downloading MCAD" git submodule init git submodule update else echo "MCAD found:" $OPENSCADDIR/libraries/MCAD fi if [ -d .git ]; then git submodule update fi echo "Building openscad-$VERSION ($VERSIONDATE) $CONFIG..." if [ ! $NUMCPU ]; then echo "note: you can 'export NUMCPU=x' for multi-core compiles (x=number)"; NUMCPU=1 fi echo "NUMCPU: " $NUMCPU case $OS in LINUX|MACOSX) TARGET= # for QT4 set QT_SELECT=4 QT_SELECT=5 export QT_SELECT ;; WIN) export QTDIR=/c/devmingw/qt2009.03 export QTMAKESPEC=win32-g++ export PATH=$PATH:/c/devmingw/qt2009.03/bin:/c/devmingw/qt2009.03/qt/bin ZIP="/c/Program Files/7-Zip/7z.exe" ZIPARGS="a -tzip" TARGET=release ;; UNIX_CROSS_WIN) . ./scripts/setenv-mingw-xbuild.sh $ARCH TARGET=release ZIP="zip" ZIPARGS="-r -q" ;; esac case $OS in UNIX_CROSS_WIN) cd $DEPLOYDIR && qmake VERSION=$VERSION OPENSCAD_COMMIT=$OPENSCAD_COMMIT CONFIG+="$CONFIG" CONFIG+=mingw-cross-env CONFIG-=debug ../openscad.pro cd $OPENSCADDIR ;; *) QMAKE="`command -v qmake-qt5`" if [ ! -x "$QMAKE" ] then QMAKE=qmake fi "$QMAKE" VERSION=$VERSION OPENSCAD_COMMIT=$OPENSCAD_COMMIT CONFIG+="$CONFIG" CONFIG-=debug openscad.pro ;; esac case $OS in UNIX_CROSS_WIN) cd $DEPLOYDIR make clean ## comment out for test-run cd $OPENSCADDIR ;; *) make -s clean ;; esac case $OS in MACOSX) rm -rf OpenSCAD.app ;; WIN) #if the following files are missing their tried removal stops the build process on msys touch -t 200012121010 parser_yacc.h parser_yacc.cpp lexer_lex.cpp ;; UNIX_CROSS_WIN) # kludge to enable paralell make touch -t 200012121010 $OPENSCADDIR/src/parser_yacc.h touch -t 200012121010 $OPENSCADDIR/src/parser_yacc.cpp touch -t 200012121010 $OPENSCADDIR/src/parser_yacc.hpp touch -t 200012121010 $OPENSCADDIR/src/lexer_lex.cpp ;; esac echo "Building GUI binary..." case $OS in UNIX_CROSS_WIN) # make main openscad.exe cd $DEPLOYDIR if [ $FAKEMAKE ]; then echo "notexe. debugging build process" > $TARGET/openscad.exe else make $TARGET -j$NUMCPU fi if [ ! -e $TARGET/openscad.exe ]; then echo "cant find $TARGET/openscad.exe. build failed. stopping." exit fi # make console pipe-able openscad.com - see winconsole.pro for info qmake ../winconsole/winconsole.pro make if [ ! -e $TARGET/openscad.com ]; then echo "cant find $TARGET/openscad.com. build failed. stopping." exit fi cd $OPENSCADDIR ;; LINUX) if [ $FAKEMAKE ]; then echo "notexe. debugging build process" > $TARGET/openscad else make $TARGET -j$NUMCPU fi ;; *) make -j$NUMCPU $TARGET ;; esac if [[ $? != 0 ]]; then echo "Error building OpenSCAD. Aborting." exit 1 fi echo "Building test suite..." if [ $BUILD_TESTS ]; then case $OS in UNIX_CROSS_WIN) TESTBUILD_MACHINE=x86_64-w64-mingw32 # dont use build-machine trilpe in TESTBINDIR because the 'mingw32' # will confuse people who are on 64 bit machines TESTBINDIR=tests-build export TESTBUILD_MACHINE export TESTBINDIR if [[ $ARCH == 32 ]]; then TESTBUILD_MACHINE=i686-pc-mingw32 fi cd $DEPLOYDIR mkdir $TESTBINDIR cd $TESTBINDIR cmake $OPENSCADDIR/tests/ \ -DCMAKE_TOOLCHAIN_FILE=../tests/CMingw-cross-env.cmake \ -DMINGW_CROSS_ENV_DIR=$MXEDIR \ -DMACHINE=$TESTBUILD_MACHINE if [ $FAKEMAKE ]; then echo "notexe. debugging build process" > openscad_nogui.exe else make -j$NUMCPU fi if [ ! -e openscad_nogui.exe ]; then echo 'test cross-build failed' exit 1 fi cd $OPENSCADDIR ;; *) echo 'test suite build not implemented for osx/linux' ;; esac fi # BUILD_TESTS echo "Creating directory structure..." case $OS in MACOSX) EXAMPLESDIR=OpenSCAD.app/Contents/Resources/examples LIBRARYDIR=OpenSCAD.app/Contents/Resources/libraries FONTDIR=OpenSCAD.app/Contents/Resources/fonts TRANSLATIONDIR=OpenSCAD.app/Contents/Resources/locale COLORSCHEMESDIR=OpenSCAD.app/Contents/Resources/color-schemes ;; UNIX_CROSS_WIN) cd $OPENSCADDIR EXAMPLESDIR=$DEPLOYDIR/openscad-$VERSION/examples/ LIBRARYDIR=$DEPLOYDIR/openscad-$VERSION/libraries/ FONTDIR=$DEPLOYDIR/openscad-$VERSION/fonts/ TRANSLATIONDIR=$DEPLOYDIR/openscad-$VERSION/locale/ COLORSCHEMESDIR=$DEPLOYDIR/openscad-$VERSION/color-schemes/ rm -rf $DEPLOYDIR/openscad-$VERSION mkdir $DEPLOYDIR/openscad-$VERSION ;; *) EXAMPLESDIR=openscad-$VERSION/examples/ LIBRARYDIR=openscad-$VERSION/libraries/ FONTDIR=openscad-$VERSION/fonts/ TRANSLATIONDIR=openscad-$VERSION/locale/ COLORSCHEMESDIR=openscad-$VERSION/color-schemes/ rm -rf openscad-$VERSION mkdir openscad-$VERSION ;; esac if [ -n $EXAMPLESDIR ]; then echo $EXAMPLESDIR mkdir -p $EXAMPLESDIR rm -f examples.tar tar cf examples.tar examples cd $EXAMPLESDIR/.. && tar xf $OPENSCADDIR/examples.tar && cd $OPENSCADDIR rm -f examples.tar chmod -R 644 $EXAMPLESDIR/*/* fi if [ -n $FONTDIR ]; then echo $FONTDIR mkdir -p $FONTDIR cp -a fonts/10-liberation.conf $FONTDIR cp -a fonts/Liberation-2.00.1 $FONTDIR case $OS in MACOSX) cp -a fonts/05-osx-fonts.conf $FONTDIR cp -a fonts-osx/* $FONTDIR ;; UNIX_CROSS_WIN) cp -a "$DEPLOYDIR"/mingw-cross-env/etc/fonts/. "$FONTDIR" ;; esac fi if [ -n $COLORSCHEMESDIR ]; then echo $COLORSCHEMESDIR mkdir -p $COLORSCHEMESDIR cp -a color-schemes/* $COLORSCHEMESDIR fi if [ -n $LIBRARYDIR ]; then echo $LIBRARYDIR mkdir -p $LIBRARYDIR # exclude the .git stuff from MCAD which is a git submodule. # tar is a relatively portable way to do exclusion, without the # risks of rm rm -f libraries.tar tar cf libraries.tar --exclude=.git* libraries cd $LIBRARYDIR/.. && tar xf $OPENSCADDIR/libraries.tar && cd $OPENSCADDIR rm -f libraries.tar chmod -R u=rwx,go=r,+X $LIBRARYDIR/* fi if [ -n $TRANSLATIONDIR ]; then echo $TRANSLATIONDIR mkdir -p $TRANSLATIONDIR cd locale && tar cvf $OPENSCADDIR/translations.tar */*/*.mo && cd $OPENSCADDIR cd $TRANSLATIONDIR && tar xvf $OPENSCADDIR/translations.tar && cd $OPENSCADDIR rm -f translations.tar fi echo "Creating archive.." case $OS in MACOSX) /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $VERSIONDATE" OpenSCAD.app/Contents/Info.plist macdeployqt OpenSCAD.app -dmg -no-strip mv OpenSCAD.dmg OpenSCAD-$VERSION.dmg hdiutil internet-enable -yes -quiet OpenSCAD-$VERSION.dmg echo "Binary created: OpenSCAD-$VERSION.dmg" ;; WIN) #package cp win32deps/* openscad-$VERSION cp $TARGET/openscad.exe openscad-$VERSION cp $TARGET/openscad.com openscad-$VERSION rm -f openscad-$VERSION.x86-$ARCH.zip "$ZIP" $ZIPARGS openscad-$VERSION.x86-$ARCH.zip openscad-$VERSION rm -rf openscad-$VERSION echo "Binary created: openscad-$VERSION.zip" ;; UNIX_CROSS_WIN) cd $OPENSCADDIR cd $DEPLOYDIR BINFILE=$DEPLOYDIR/OpenSCAD-$VERSION-x86-$ARCH.zip INSTFILE=$DEPLOYDIR/OpenSCAD-$VERSION-x86-$ARCH-Installer.exe #package echo "Creating binary zip package" cp $TARGET/openscad.exe openscad-$VERSION cp $TARGET/openscad.com openscad-$VERSION rm -f OpenSCAD-$VERSION.x86-$ARCH.zip "$ZIP" $ZIPARGS $BINFILE openscad-$VERSION cd $OPENSCADDIR echo "Binary zip package created" echo "Creating installer" echo "Copying NSIS files to $DEPLOYDIR/openscad-$VERSION" cp ./scripts/installer$ARCH.nsi $DEPLOYDIR/openscad-$VERSION/installer_arch.nsi cp ./scripts/installer.nsi $DEPLOYDIR/openscad-$VERSION/ cp ./scripts/mingw-file-association.nsh $DEPLOYDIR/openscad-$VERSION/ cp ./scripts/x64.nsh $DEPLOYDIR/openscad-$VERSION/ cp ./scripts/LogicLib.nsh $DEPLOYDIR/openscad-$VERSION/ cd $DEPLOYDIR/openscad-$VERSION NSISDEBUG=-V2 # NSISDEBUG= # leave blank for full log echo $MAKENSIS $NSISDEBUG installer.nsi $MAKENSIS $NSISDEBUG installer.nsi cp $DEPLOYDIR/openscad-$VERSION/openscad_setup.exe $INSTFILE cd $OPENSCADDIR if [ -e $BINFILE ]; then if [ -e $INSTFILE ]; then echo echo "Binary created:" $BINFILE echo "Installer created:" $INSTFILE echo else echo "Build failed. Cannot find" $INSTFILE fi else echo "Build failed. Cannot find" $BINFILE exit 1 fi ;; LINUX) # Do stuff from release-linux.sh mkdir openscad-$VERSION/bin mkdir -p openscad-$VERSION/lib/openscad cp scripts/openscad-linux openscad-$VERSION/bin/openscad cp openscad openscad-$VERSION/lib/openscad/ if [[ $ARCH == 64 ]]; then gcc -o chrpath_linux -DSIZEOF_VOID_P=8 scripts/chrpath_linux.c else gcc -o chrpath_linux -DSIZEOF_VOID_P=4 scripts/chrpath_linux.c fi ./chrpath_linux -d openscad-$VERSION/lib/openscad/openscad QTLIBDIR=$(dirname $(ldd openscad | grep Qt5Gui | head -n 1 | awk '{print $3;}')) ( ldd openscad ; ldd "$QTLIBDIR"/qt5/plugins/platforms/libqxcb.so ) \ | sed -re 's,.* => ,,; s,[\t ].*,,;' -e '/^$/d' -e '/libc\.so|libm\.so|libdl\.so|libgcc_|libpthread\.so/d' \ | sort -u \ | xargs cp -vt "openscad-$VERSION/lib/openscad/" PLATFORMDIR="openscad-$VERSION/lib/openscad/platforms/" mkdir -p "$PLATFORMDIR" cp -av "$QTLIBDIR"/qt5/plugins/platforms/libqxcb.so "$PLATFORMDIR" DRIDRIVERDIR=$(find /usr/lib -xdev -type d -name dri) if [ -d "$DRIDRIVERDIR" ] then DRILIB="openscad-$VERSION/lib/openscad/dri/" mkdir -p "$DRILIB" cp -av "$DRIDRIVERDIR"/swrast_dri.so "$DRILIB" fi strip openscad-$VERSION/lib/openscad/* mkdir -p openscad-$VERSION/share/appdata cp icons/openscad.{desktop,png,xml} openscad-$VERSION/share/appdata cp scripts/installer-linux.sh openscad-$VERSION/install.sh chmod 755 -R openscad-$VERSION/ PACKAGEFILE=openscad-$VERSION.x86-$ARCH.tar.gz tar cz openscad-$VERSION > $PACKAGEFILE echo echo "Binary created:" $PACKAGEFILE echo ;; esac if [ $BUILD_TESTS ]; then echo "Creating regression tests package..." case $OS in MACOSX) echo 'building regression test package on OSX not implemented' ;; WIN) echo 'building regression test package on Win not implemented' ;; UNIX_CROSS_WIN) # Build a .zip file containing all the files we need to run a # ctest on Windows(TM). For the sake of simplicity, we do not # create an installer for the tests. echo "Copying files..." cd $OPENSCADDIR # This copies a lot of unnecessary stuff but that's OK. # as above, we use tar as a somewhat portable way to do 'exclude' # while copying. rm -f ./ostests.tar for subdir in tests testdata libraries examples doc; do tar prvf ./ostests.tar --exclude=.git* --exclude=*/mingw64/* --exclude=*/mingw32/* --exclude=*.cc.obj --exclude=*.a $subdir done cd $DEPLOYDIR tar prvf $OPENSCADDIR/ostests.tar --exclude=.git* --exclude=*/mingw* --exclude=*.cc.obj --exclude=*.a $TESTBINDIR cd $DEPLOYDIR if [ -e ./OpenSCAD-Tests-$VERSION ]; then rm -rf ./OpenSCAD-Tests-$VERSION fi mkdir OpenSCAD-Tests-$VERSION cd OpenSCAD-Tests-$VERSION tar pxf $OPENSCADDIR/ostests.tar rm -f $OPENSCADDIR/ostests.tar # Now we have the basic files copied into our tree that will become # our .zip file. We also want to move some files around for easier # access for the user: cd $DEPLOYDIR cd ./OpenSCAD-Tests-$VERSION echo "Copying files for ease of use when running from cmdline" cp -v ./tests/OpenSCAD_Test_Console.py . cp -v ./tests/WinReadme.txt . cp -v ./tests/mingw_convert_ctest.py ./$TESTBINDIR cp -v ./tests/mingwcon.bat ./$TESTBINDIR echo "Creating mingw_cross_info.py file" cd $DEPLOYDIR cd ./OpenSCAD-Tests-$VERSION cd $TESTBINDIR if [ -e ./mingw_cross_info.py ]; then rm -f ./mingw_cross_info.py fi echo "# created automatically by release-common.sh from within linux " >> mingw_cross_info.py echo "linux_abs_basedir='"$OPENSCADDIR"'" >> mingw_cross_info.py echo "linux_abs_builddir='"$DEPLOYDIR/$TESTBINDIR"'" >> mingw_cross_info.py echo "bindir='"$TESTBINDIR"'" >> mingw_cross_info.py # fixme .. parse CTestTestfiles to find linux+convert python strings # or have CMake itself dump them during it's cross build cmake call echo "linux_python='"`which python`"'" >> mingw_cross_info.py # note- this has to match the CMakeLists.txt line that sets the # convert executable... and CMingw-cross-env.cmake's skip-imagemagick # setting. what a kludge! echo "linux_convert='/bin/echo'" >> mingw_cross_info.py echo "win_installdir='OpenSCAD_Tests_"$VERSIONDATE"'" >> mingw_cross_info.py echo 'Converting linefeed to carriage-return+linefeed' for textfile in `find . | grep txt$`; do lf2crlf $textfile; done for textfile in `find . | grep py$`; do lf2crlf $textfile; done for textfile in `find . | grep cmake$`; do lf2crlf $textfile; done for textfile in `find . | grep bat$`; do lf2crlf $textfile; done # Test binaries can be hundreds of megabytes due to debugging info. # By default, we strip that. In most cases we wont need it and it # causes too many problems to have >100MB files. echo "stripping .exe binaries" cd $DEPLOYDIR cd ./OpenSCAD-Tests-$VERSION cd $TESTBINDIR if [ "`command -v $TESTBUILD_MACHINE'-strip' `" ]; then for exefile in *exe; do ls -sh $exefile echo $TESTBUILD_MACHINE'-strip' $exefile $TESTBUILD_MACHINE'-strip' $exefile ls -sh $exefile done fi # Build the actual .zip archive based on the file tree we've built above cd $DEPLOYDIR ZIPFILE=OpenSCAD-Tests-$VERSION-x86-$ARCH.zip echo "Creating binary zip package for Tests:" $ZIPFILE rm -f ./$ZIPFILE "$ZIP" $ZIPARGS $ZIPFILE OpenSCAD-Tests-$VERSION if [ -e $ZIPFILE ]; then echo "ZIP package created:" `pwd`/$ZIPFILE else echo "Build of Regression Tests package failed. Cannot find" `pwd`/$ZIPFILE exit 1 fi cd $OPENSCADDIR ;; LINUX) echo 'building regression test package on linux not implemented' ;; esac else echo "Not building regression tests package" fi # BUILD_TESTS