1#!/bin/bash
2
3#
4# make-bindist.sh - make binary distribution for the Mac OSX port
5#
6# Written by
7#  Christian Vogelgsang <chris@vogelgsang.org>
8#
9# This file is part of VICE, the Versatile Commodore Emulator.
10# See README for copyright notice.
11#
12#  This program is free software; you can redistribute it and/or modify
13#  it under the terms of the GNU General Public License as published by
14#  the Free Software Foundation; either version 2 of the License, or
15#  (at your option) any later version.
16#
17#  This program is distributed in the hope that it will be useful,
18#  but WITHOUT ANY WARRANTY; without even the implied warranty of
19#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20#  GNU General Public License for more details.
21#
22#  You should have received a copy of the GNU General Public License
23#  along with this program; if not, write to the Free Software
24#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25#  02111-1307  USA.
26#
27# Usage: make-bindist.sh <top_srcdir> <strip> <vice-version> <--enable-arch> <zip|nozip>
28#                         $1           $2      $3             $4              $5
29#
30
31RUN_PATH=`dirname $0`
32
33echo "Generating macOS binary distribution."
34
35TOP_DIR=$1
36STRIP=$2
37VICE_VERSION=$3
38ENABLEARCH=$4
39ZIP=$5
40
41# define UI type
42UI_TYPE=GTK3
43echo "  UI type: $UI_TYPE"
44
45# check binary type
46TEST_BIN=src/x64
47if [ ! -x $TEST_BIN ]; then
48  echo "error missing binary $TEST_BIN"
49  exit 1
50fi
51BIN_TYPE=`file $TEST_BIN | grep "$TEST_BIN:" | sed -e 's/executable//g' -e 's/Mach-O//g' -e 's/64-bit//g' | awk '{print $2}'`
52if [ x"$BIN_TYPE" = "xi386" ]; then
53  BIN_FORMAT=i386
54elif [ x"$BIN_TYPE" = "xx86_64" ]; then
55  BIN_FORMAT=x86_64
56elif [ x"$BIN_TYPE" = "xppc" ]; then
57  BIN_FORMAT=ppc
58else
59  echo "fatal: unknown bin type '$BIN_TYPE'"
60  exit 1
61fi
62echo "  binary format: $BIN_FORMAT"
63
64# setup BUILD dir
65if [ x"$SDK_TAG" != "x" ]; then
66  BUILD_DIR=VICE-macOS-$UI_TYPE-$BIN_FORMAT-$SDK_TAG-$VICE_VERSION
67else
68  BUILD_DIR=VICE-macOS-$UI_TYPE-$BIN_FORMAT-$VICE_VERSION
69fi
70if [ -d $BUILD_DIR ]; then
71  rm -rf $BUILD_DIR
72fi
73mkdir $BUILD_DIR
74if [ ! -d $BUILD_DIR ]; then
75  echo "error creating directory $BUILD_DIR"
76  exit 1
77fi
78
79# make tools dir
80TOOL_DIR=$BUILD_DIR/tools
81if [ ! -d $TOOL_DIR ]; then
82  mkdir $TOOL_DIR
83fi
84
85# define emulators and command line tools
86EMULATORS="x64 xscpu64 x64dtv x64sc x128 xcbm2 xcbm5x0 xpet xplus4 xvic vsid"
87TOOLS="c1541 petcat cartconv"
88
89# define data files for emulators
90ROM_COMMON="DRIVES PRINTER"
91ROM_x64=C64
92ROM_xscpu64=SCPU64
93ROM_x64sc=C64
94ROM_x64dtv=C64DTV
95ROM_x128=C128
96ROM_xcbm2=CBM-II
97ROM_xcbm5x0=CBM-II
98ROM_xpet=PET
99ROM_xplus4=PLUS4
100ROM_xvic=VIC20
101# files to remove from ROM directory
102ROM_REMOVE="{beos,amiga,dos,win,RO}*.vkm"
103DOC_REMOVE="Makefile.* *.c *.mak *.sh *.tex *.texi *.pl *.chm *.guide *.hlp *.inf building readmes"
104# define droppable file types
105DROP_TYPES="x64|p64|g64|d64|d71|d81|t64|tap|prg|p00|crt|reu"
106DROP_FORMATS="x64 p64 g64 d64 d71 d81 t64 tap prg p00 crt reu"
107
108# launcher script
109LAUNCHER=macOS-launcher.sh
110
111# multi apps
112MULTI_APPS=0
113if [ "$UI_TYPE" = "cocoa" -o "$UI_TYPE" = "sdl" ]; then
114  MULTI_APPS=1
115fi
116
117# use platypus or launcher directly
118PLATYPUS_PATH="`which platypus`"
119PLATYPUS=0
120if [ $MULTI_APPS -eq 0 ]; then
121  if [ -e "$PLATYPUS_PATH" -a "$NO_PLATYPUS" = "" ]; then
122    PLATYPUS_VERSION=`$PLATYPUS_PATH -v | cut -f 3 -d ' '`
123    echo "  using platypus: $PLATYPUS_PATH version $PLATYPUS_VERSION"
124    PLATYPUS=1
125  else
126    echo "  using launcher only"
127  fi
128fi
129
130# make sure icon is available
131if [ ! -e $RUN_PATH/Resources/VICE.icns ]; then
132  echo "ERROR: missing icon: $RUNPATH/Resources/VICE.icns"
133  exit 1
134fi
135
136# make sure Info.plist is available
137if [ ! -e $RUN_PATH/Info.plist ]; then
138  echo "ERROR: missing: $RUN_PATH/Info.plist"
139  exit 1
140fi
141
142# --- create bundles ---
143
144if [ $MULTI_APPS -eq 1 ]; then
145  # create a bundle for each emulator
146  BUNDLES="$EMULATORS"
147else
148  BUNDLES="VICE"
149fi
150
151copy_tree () {
152  (cd "$1" && tar --exclude 'Makefile*' --exclude .svn -c -f - .) | (cd "$2" && tar xf -)
153}
154
155ALL_ICONS="VICEFile floppy525 tape cartridge"
156
157create_info_plist () {
158  SRC="$1"
159  TGT="$2"
160
161  # add filetypes to Info.plist
162  if [ "$UI_TYPE" = "cocoa" ]; then
163    ADDON="  <key>CFBundleDocumentTypes</key><array>"
164    for type in $DROP_FORMATS ; do
165      # default icon
166      ICON="VICEFile"
167      case "$type" in
168      [xgd][678][41])
169        ICON="floppy525"
170        ;;
171      tap|t64)
172        ICON="tape"
173        ;;
174      crt)
175        ICON="cartridge"
176        ;;
177      esac
178      ADDLINE="<dict><key>CFBundleTypeExtensions</key><array><string>$type</string></array>"
179      ADDLINE="$ADDLINE <key>CFBundleTypeIconFile</key><string>$ICON</string>"
180      ADDLINE="$ADDLINE <key>CFBundleTypeName</key><string>$type VICE File</string>"
181      ADDLINE="$ADDLINE <key>CFBundleTypeRole</key><string>Editor</string></dict>"
182      ADDON="$ADDON $ADDLINE"
183    done
184    ADDON="$ADDON </array></dict>"
185    sed -e "s/XVERSIONX/$VICE_VERSION/g" \
186        -e "s/XNAMEX/$bundle/g" \
187        -e "s,</dict>,$ADDON," \
188        < "$SRC" > "$TGT"
189  else
190    sed -e "s/XVERSIONX/$VICE_VERSION/g" \
191        -e "s/XNAMEX/$bundle/g" \
192        < "$SRC" > "$TGT"
193  fi
194}
195
196for bundle in $BUNDLES ; do
197
198  APP_NAME=$BUILD_DIR/$bundle.app
199  APP_CONTENTS=$APP_NAME/Contents
200  APP_MACOS=$APP_CONTENTS/MacOS
201  APP_FRAMEWORKS=$APP_CONTENTS/Frameworks
202  APP_RESOURCES=$APP_CONTENTS/Resources
203  APP_ROMS=$APP_RESOURCES/ROM
204  APP_DOCS=$APP_RESOURCES/doc
205
206  if [ $MULTI_APPS -eq 1 ]; then
207    APP_BIN=$APP_MACOS
208    APP_LIB=$APP_MACOS
209  else
210    APP_BIN=$APP_RESOURCES/bin
211    APP_LIB=$APP_RESOURCES/lib
212    APP_ETC=$APP_RESOURCES/etc
213  fi
214
215  echo "  bundling $bundle.app: "
216  echo -n "    "
217
218  if [ "$PLATYPUS" = "1" ]; then
219    # --- use platypus for bundling ---
220    echo -n "[platypus] "
221    $PLATYPUS_PATH \
222        -a VICE \
223        -o None \
224        -i $RUN_PATH/Resources/VICE.icns \
225        -V "$VICE_VERSION" \
226        -u "The VICE Team" \
227        -I "org.viceteam.VICE" \
228        -c $RUN_PATH/$LAUNCHER \
229        $APP_NAME
230    PLATYPUS_STATUS=$?
231    if [ $PLATYPUS_STATUS -ne 0 ]; then
232      echo "ERROR: platypus failed with $PLATYPUS_STATUS"
233      exit $PLATYPUS_STATUS
234    fi
235
236    # where is the launcher script
237    LAUNCHER_SCRIPT_REL="Resources/script"
238    # make launcher executable
239    chmod 755 $APP_RESOURCES/script
240  else
241    # --- bundling without platypus ---
242    # create directory structure
243    echo -n "[app dirs] "
244    mkdir -p $APP_CONTENTS
245    mkdir -p $APP_MACOS
246    mkdir -p $APP_FRAMEWORKS
247    mkdir -p $APP_RESOURCES
248
249    # copy icons
250    ICON="$RUN_PATH/Resources/$bundle.icns"
251    if [ ! -e "$ICON" ]; then
252      ICON="$RUN_PATH/Resources/VICE.icns"
253    fi
254    ICON_BASE="`basename \"$ICON\"`"
255    echo -n "[icon=$ICON_BASE] "
256    cp $ICON $APP_RESOURCES/
257
258    # add VICE.icns
259    if [ "$bundle" != "VICE" ]; then
260      ICON="$RUN_PATH/Resources/VICE.icns"
261      cp $ICON $APP_RESOURCES/
262      echo -n "[icon=VICE] "
263    fi
264
265    # setup Info.plist
266    echo -n "[Info.plist] "
267    create_info_plist "$RUN_PATH/Info.plist" "$APP_CONTENTS/Info.plist"
268
269    # copy extra icons
270    echo -n "[FTIcons:"
271    for icon in $ALL_ICONS ; do
272      ICON_FILE="$RUN_PATH/Resources/$icon.icns"
273      if [ -e "$ICON_FILE" ]; then
274        echo -n "$icon "
275        cp $ICON_FILE $APP_RESOURCES/
276      fi
277    done
278    echo "] "
279    echo -n "    "
280
281    # copy launcher for non-cocoa
282    if [ $MULTI_APPS -eq 0 ]; then
283      echo -n "[launcher] "
284      if [ ! -e $RUN_PATH/$LAUNCHER ]; then
285        echo "ERROR: missing launcher script: $RUNPATH/$LAUNCHER"
286        exit 1
287      fi
288      MAIN_PROG=$APP_MACOS/VICE
289      cp $RUN_PATH/$LAUNCHER $MAIN_PROG
290      chmod 755 $MAIN_PROG
291
292      # where is the launcher script
293      LAUNCHER_SCRIPT_REL="MacOS/VICE"
294    elif [ "$UI_TYPE" = "cocoa" ]; then
295      # embed resources for cocoa
296      LOC_RESOURCES="$RUN_PATH/Resources"
297
298      # copy extra files from Resources
299      EXTRA_RES_FILES="Credits.html"
300      for f in $EXTRA_RES_FILES ; do
301        echo -n "[$f] "
302        cp "$LOC_RESOURCES/$f" "$APP_RESOURCES/"
303      done
304
305      # rename emu nib
306      RES_LANGUAGES="English"
307      for lang in $RES_LANGUAGES ; do
308        echo -n "[lang:$lang"
309
310        RES_DIR="$APP_RESOURCES/${lang}.lproj"
311        mkdir -p "$RES_DIR"
312        copy_tree "$LOC_RESOURCES/${lang}.lproj" "$RES_DIR"
313
314        # make emu nib the MainMenu.nib
315        EMU_NIB="$RES_DIR/$bundle.nib"
316        if [ -e "$EMU_NIB" ]; then
317          echo -n " nib"
318          MAIN_NIB="$RES_DIR/MainMenu.nib"
319          mv "$EMU_NIB" "$MAIN_NIB"
320        else
321          echo -n " **MISSING:nib"
322        fi
323        # remove unwanted emu nibs
324        find -d "$RES_DIR" -name "x*.nib" -exec rm -rf {} \;
325
326        echo -n "]"
327      done
328
329      # clean up nibs and remove developer files
330      echo -n "[clean nib] "
331      find "$APP_RESOURCES" \( -name "info.nib" -o -name "classes.nib" -o -name "designable.nib" \) -exec rm {} \;
332
333    fi
334  fi
335
336  echo -n "[dirs] "
337  mkdir -p $APP_ROMS
338  mkdir -p $APP_DOCS
339  mkdir -p $APP_BIN
340
341  # copy roms and data into bundle
342  echo -n "[common ROMs] "
343  for rom in $ROM_COMMON ; do
344    if [ ! -d $TOP_DIR/data/$rom ]; then
345      echo "ERROR: missing ROM: $TOP_DIR/data/$rom"
346      exit 1
347    fi
348    if [ ! -d "$APP_ROMS/$rom" ]; then
349        mkdir "$APP_ROMS/$rom"
350    fi
351    copy_tree "$TOP_DIR/data/$rom" "$APP_ROMS/$rom"
352    (cd "$APP_ROMS/$rom" && eval "rm -f $ROM_REMOVE")
353  done
354
355  # copy html docs into bundle
356  echo -n "[docs] "
357  copy_tree "$TOP_DIR/doc/html" "$APP_DOCS"
358  (cd $APP_DOCS && eval "rm -rf $DOC_REMOVE")
359
360  # embed c1541
361  echo -n "[c1541] "
362  if [ ! -e src/c1541 ]; then
363    echo "ERROR: missing binary: src/c1541"
364    exit 1
365  fi
366  cp src/c1541 $APP_BIN/
367
368  # strip embedded c1541 binary
369  if [ x"$STRIP" = "xstrip" ]; then
370    echo -n "[strip c1541] "
371    /usr/bin/strip $APP_BIN/c1541
372  fi
373
374  # any dylibs required?
375  if [ -d lib ]; then
376    mkdir -p $APP_LIB
377    DYLIBS=`find lib -name *.dylib`
378    NUMDYLIBS=`echo $DYLIBS | wc -w`
379    echo -n "[dylibs"
380    for lib in $DYLIBS ; do
381      echo -n "."
382      cp $lib $APP_LIB
383    done
384    echo -n "] "
385  fi
386
387  # any config files from /etc?
388  if [ -d etc ]; then
389    mkdir -p $APP_ETC
390    echo -n "[etc"
391    (cd etc && tar cf - *) | (cd "$APP_ETC" && tar xf -)
392    echo -n "] "
393  fi
394
395  # ready with bundle
396  echo
397
398  # --- embed binaries ---
399  if [ "$bundle" = "VICE" ]; then
400    BINARIES="$EMULATORS"
401  else
402    BINARIES="$bundle"
403  fi
404  for emu in $BINARIES ; do
405    echo -n "     embedding $emu: "
406
407    # copy binary
408    echo -n "[binary] "
409    if [ ! -e src/$emu ]; then
410      echo "ERROR: missing binary: src/$emu"
411      exit 1
412    fi
413    cp src/$emu $APP_BIN/$emu
414
415    # strip binary
416    if [ x"$STRIP" = "xstrip" ]; then
417      echo -n "[strip] "
418      /usr/bin/strip $APP_BIN/$emu
419    fi
420
421    # copy any needed "local" libs
422    LOCAL_LIBS=`otool -L $APP_BIN/$emu | egrep '^\s+/(opt|usr)/local/'  | awk '{print $1}'`
423    for lib in $LOCAL_LIBS; do
424        if [ ! -e "$APP_FRAMEWORKS/`basename $lib`" ]
425        then
426          cp $lib $APP_FRAMEWORKS
427        fi
428        lib_base=`basename $lib`
429        LOCAL_LIBS_LIBS=`otool -L $APP_FRAMEWORKS/$lib_base | egrep '^\s+/(opt|usr)/local/' | grep -v $lib_base | awk '{print $1}'`
430        for lib_lib in $LOCAL_LIBS_LIBS; do
431            if [ ! -e "$APP_FRAMEWORKS/`basename $lib_lib`" ]
432            then
433              cp $lib_lib $APP_FRAMEWORKS
434            fi
435            lib_lib_base=`basename $lib_lib`
436            chmod 644 $APP_FRAMEWORKS/$lib_base
437            install_name_tool -change $lib_lib @loader_path/../Frameworks/$lib_lib_base $APP_FRAMEWORKS/$lib_base
438        done
439        install_name_tool -change $lib @executable_path/../../Frameworks/$lib_base $APP_BIN/$emu
440    done
441
442    # copy emulator ROM
443    eval "ROM=\${ROM_$emu}"
444    echo -n "[ROM=$ROM] "
445    if [ ! -d $TOP_DIR/data/$ROM ]; then
446      echo "ERROR: missing ROM: $TOP_DIR/data/$ROM"
447      exit 1
448    fi
449    if [ ! -d "$APP_ROMS/$ROM" ]; then
450        mkdir "$APP_ROMS/$ROM"
451    fi
452    copy_tree "$TOP_DIR/data/$ROM" "$APP_ROMS/$ROM"
453    (cd $APP_ROMS/$ROM && eval "rm -f $ROM_REMOVE")
454
455    # ready
456    echo
457  done
458
459  # print bundle size
460  echo -n "    => " ; du -sh "$APP_NAME" | awk '{ print $1 }'
461
462done
463
464# --- copy tools ---
465for tool in $TOOLS ; do
466  echo -n "  copying tool $tool: "
467
468  # copy binary
469  echo -n "[binary] "
470  if [ ! -e src/$tool ]; then
471    echo "ERROR: missing binary: src/$tool"
472    exit 1
473  fi
474  cp src/$tool $TOOL_DIR/
475
476  # strip binary
477  if [ x"$STRIP" = "xstrip" ]; then
478    echo -n "[strip] "
479    /usr/bin/strip $TOOL_DIR/$tool
480  fi
481
482  # ready
483  echo
484done
485
486# --- copy command line launcher ---
487echo "  copying command line launcher"
488if [ ! -e "$RUN_PATH/vice-launcher.sh" ]; then
489  echo "Error: '$RUN_PATH/vice-launcher.sh' is missing!"
490  exit 1
491fi
492cp $RUN_PATH/vice-launcher.sh $TOOL_DIR
493chmod 755 $TOOL_DIR/vice-launcher.sh
494for emu in $EMULATORS ; do
495  (cd $TOOL_DIR && ln -sf vice-launcher.sh $emu)
496done
497
498# --- copy docs ---
499echo "  copying documents"
500cp $TOP_DIR/FEEDBACK $BUILD_DIR/FEEDBACK.txt
501cp $TOP_DIR/README $BUILD_DIR/README.txt
502mkdir "$BUILD_DIR/doc"
503copy_tree "$TOP_DIR/doc" "$BUILD_DIR/doc"
504mv $BUILD_DIR/doc/readmes/Readme-$UI_TYPE.txt $BUILD_DIR/
505(cd $BUILD_DIR/doc && eval "rm -rf $DOC_REMOVE")
506
507# --- copy fonts ---
508FONTS="CBM.ttf"
509if [ "$UI_TYPE" = "cocoa" ]; then
510  echo "  copying fonts"
511  mkdir "$BUILD_DIR/fonts"
512  for FONT in $FONTS ; do
513    cp "$TOP_DIR/data/fonts/$FONT" "$BUILD_DIR/fonts/"
514  done
515fi
516
517# --- make dmg? ---
518if [ x"$ZIP" = "xnozip" ]; then
519  echo "ready. created dist directory: $BUILD_DIR"
520  du -sh $BUILD_DIR
521else
522  # image name
523  BUILD_IMG=$BUILD_DIR.dmg
524  BUILD_TMP_IMG=$BUILD_DIR.tmp.dmg
525
526  # Create the image and format it
527  echo "  creating DMG"
528  hdiutil create -srcfolder $BUILD_DIR $BUILD_TMP_IMG -volname $BUILD_DIR -ov -quiet
529
530  # Compress the image
531  echo "  compressing DMG"
532  hdiutil convert $BUILD_TMP_IMG -format UDZO -o $BUILD_IMG -ov -quiet
533  rm -f $BUILD_TMP_IMG
534
535  echo "ready. created dist file: $BUILD_IMG"
536  du -sh $BUILD_IMG
537  md5 -q $BUILD_IMG
538fi
539if test x"$ENABLEARCH" = "xyes"; then
540  echo Warning: binaries are optimized for your system and might not run on a different system, use --enable-arch=no to avoid this
541fi
542