]> git.lyx.org Git - lyx.git/blob - development/LyX-Mac-binary-release.sh
a7f0620ff217f67606fa8dee9149bd25a4b28892
[lyx.git] / development / LyX-Mac-binary-release.sh
1 #!/bin/sh
2
3 # set -x
4
5 # This script automates creating universal binaries of LyX on Mac.
6 # Author: Bennett Helm (and extended by Konrad Hofbauer)
7 # latest changes by Stephan Witt
8 # Last modified: July 2014
9
10 QtAPI=${QtAPI:-"-cocoa"}
11 QtVersion=${QtVersion:-"4.6.3"}
12 QtSourceVersion="qt-everywhere-opensource-src-${QtVersion}"
13 QtBuildSubDir="qt-${QtVersion}-build${QtAPI}"
14 QtConfigureOptions=${QtConfigureOptions:-"-release"}
15
16 LibMagicVersion=${LibMagicVersion:-"5.19"}
17 LibMagicSource="file-${LibMagicVersion}"
18 LibMagicLibrary="libmagic.1.dylib"
19
20 ASpellVersion=${ASpellVersion:-"0.60.6.1"}
21 ASpellSource="aspell-${ASpellVersion}"
22 ASpellLibrary="libaspell.15.dylib"
23
24 HunSpellVersion=${HunSpellVersion:-"1.3.2"}
25 HunSpellSource="hunspell-${HunSpellVersion}"
26 HunSpellLibrary="libhunspell-1.3.0.dylib"
27
28 unset DYLD_LIBRARY_PATH LD_LIBRARY_PATH
29
30 # Prerequisite:
31 # * a decent checkout of LyX sources (probably you have it already)
32 # * Qt - build with shared or static libraries for the used platforms (default: i386 and ppc)
33 #   or - an unpacked source tree of Qt in $QTSOURCEDIR or in the sibling directory (variable QtSourceVersion)
34 # * for aspell support:
35 #   the aspell sources placed in a sibling directory (variable ASpellSource)
36 # * for hunspell support:
37 #   the hunspell sources placed in a sibling directory (variable HunSpellSource)
38 # * for dictionary deployment (per default thesauri only):
39 #   - aspell:   the dictionary files of macports (in /opt/local/share/aspell and /opt/local/lib/aspell-0.60)
40 #   - hunspell: the dictionary files in the sibling directory dictionaries/dicts
41 #   - mythes:   the data and idx files in the sibling directory dictionaries/thes
42 # * for magic file type detection support:
43 #   the libmagic sources placed in a sibling directory (variable LibMagicSource)
44
45 LyXConfigureOptions="--enable-warnings --enable-optimization=-Os --with-x=no"
46 LyXConfigureOptions="${LyXConfigureOptions} --disable-stdlib-debug"
47 AspellConfigureOptions="--enable-warnings --enable-optimization=-O0 --enable-debug --disable-nls --enable-compile-in-filters --disable-pspell-compatibility"
48 HunspellConfigureOptions="--with-warnings --disable-nls --disable-static"
49
50 QtMajorVersion=qt4
51 QtConfigureOptions="${QtConfigureOptions} -opensource -silent -shared -confirm-license"
52 # stupid special case...
53 case "${QtVersion}:${QtAPI}" in
54 4.6*:-carbon)
55         QtConfigureOptions="${QtConfigureOptions} -fast -no-exceptions"
56         QtConfigureOptions="${QtConfigureOptions} -no-webkit -no-qt3support -no-javascript-jit -no-dbus"
57         QtConfigureOptions="${QtConfigureOptions} -nomake examples -nomake demos -nomake docs -nomake tools"
58         ;;
59 5.0*)
60         QtConfigureOptions="${QtConfigureOptions} -fast -no-strip"
61         QtConfigureOptions="${QtConfigureOptions} -no-javascript-jit -no-pkg-config"
62         QtConfigureOptions="${QtConfigureOptions} -nomake examples -nomake demos -nomake docs -nomake tools"
63         QtMajorVersion=qt5
64         ;;
65 5.*)
66         QtConfigureOptions="${QtConfigureOptions} -no-strip"
67         QtConfigureOptions="${QtConfigureOptions} -no-kms -no-pkg-config"
68         QtConfigureOptions="${QtConfigureOptions} -nomake examples -nomake tools"
69         QtConfigureOptions="${QtConfigureOptions} -skip qtquick1 -skip qtwebkit -skip qtconnectivity -skip qtscript"
70         QtConfigureOptions="${QtConfigureOptions} -skip qtquickcontrols -skip qtdeclarative"
71         QtMajorVersion=qt5
72         ;;
73 *)
74         QtConfigureOptions="${QtConfigureOptions} -fast -no-exceptions"
75         QtConfigureOptions="${QtConfigureOptions} -no-webkit -no-qt3support -no-javascript-jit -no-dbus"
76         QtConfigureOptions="${QtConfigureOptions} -nomake examples -nomake demos -nomake docs -nomake tools"
77         QtConfigureOptions="${QtConfigureOptions} ${QtAPI}"
78         ;;
79 esac
80
81 aspell_dictionaries="no"
82 hunspell_dictionaries="yes"
83
84 libmagic_deployment="yes"
85 aspell_deployment="yes"
86 hunspell_deployment="yes"
87 thesaurus_deployment="yes"
88
89 qt_deployment="yes"
90
91 # auto detect Xcode location
92 if [ -d "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs" ]; then
93         DEVELOPER_SDKS="/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs"
94         XCODE_DEVELOPER="/Applications/Xcode.app/Contents/Developer"
95         MACOSX_DEPLOYMENT_TARGET="10.7" # Lion support is default
96         SDKROOT="${DEVELOPER_SDKS}/MacOSX10.7.sdk" # Lion build is default
97 elif [ -d "/Developer/SDKs" ]; then
98         DEVELOPER_SDKS="/Developer/SDKs"
99         XCODE_DEVELOPER="/Developer"
100         MACOSX_DEPLOYMENT_TARGET="10.4" # Tiger support is default
101         SDKROOT="${DEVELOPER_SDKS}/MacOSX10.5.sdk" # Leopard build is default
102 fi
103
104 # detection of script home
105 LyxSourceDir=$(dirname "$0")
106 if [ ! -d "${LyxSourceDir}" ]; then
107         echo Missing LyX source directory.
108         exit 2
109 fi
110 case "${LyxSourceDir}" in
111 /*/development)
112         LyxSourceDir=$(dirname "${LyxSourceDir}")
113         ;;
114 /*)
115         ;;
116 */development|development)
117         LyxSourceDir=$(dirname "${LyxSourceDir}")
118         LyxSourceDir=$(cd "${LyxSourceDir}";pwd)
119         ;;
120 *)
121         LyxSourceDir=$(cd "${LyxSourceDir}";pwd)
122         ;;
123 esac
124
125 usage() {
126         echo "*" Build script for LyX on Mac OS X
127         echo
128         echo Optional arguments:
129         echo " --aspell-deployment=yes|no ." default yes
130         echo " --with-qt-frameworks=yes|no." default no
131         echo " --qt-deployment=yes|no ....." default yes
132         echo " --with-macosx-target=TARGET " default 10.4 "(Tiger)"
133         echo " --with-sdkroot=SDKROOT ....." default 10.5 "(Leopard)"
134         echo " --with-arch=ARCH ..........." default ppc,i386
135         echo " --with-build-path=PATH ....." default \${lyx-src-dir}/../lyx-build
136         echo " --with-dmg-location=PATH ..." default \${build-path}
137         echo " --with-binary-strip=yes ...." default no
138         echo
139         echo "All other arguments with -- are passed to configure"
140         echo "including the defaults: ${LyXConfigureOptions}"
141         case "${1}" in
142         --help=short)
143                 ;;
144         *)
145                 if [ -x "${LyxSourceDir}/configure" ]; then
146                         echo
147                         echo "*" Configure options of LyX
148                         echo
149                         "${LyxSourceDir}/configure" --help
150                 fi
151         esac
152         exit 0
153 }
154
155 NCPU=$(sysctl -n hw.ncpu)
156 NCPU=$((NCPU / 2))
157 if [ $NCPU -gt 1 ]; then
158         MAKEJOBS=-j${NCPU}
159 fi
160
161 while [ $# -gt 0 ]; do
162         case "${1}" in
163         --with-qt-frameworks=*)
164                 configure_qt_frameworks=$(echo ${1}|cut -d= -f2)
165                 if [ "$configure_qt_frameworks" = "yes" ]; then
166                         unset QTDIR
167                         qt_deployment="no"
168                 fi
169                 shift
170                 ;;
171         --with-qt-dir=*)
172                 QTDIR=$(echo ${1}|cut -d= -f2)
173                 shift
174                 ;;
175         --with-macosx-target=*)
176                 MACOSX_DEPLOYMENT_TARGET=$(echo ${1}|cut -d= -f2)
177                 shift
178                 ;;
179         --with-sdkroot=*)
180                 SDKROOT=$(echo ${1}|cut -d= -f2)
181                 case "${SDKROOT}" in
182                 10.4)
183                         SDKROOT="${DEVELOPER_SDKS}/MacOSX10.4u.sdk"
184                         export CC=gcc-4.0
185                         export OBJC=gcc-4.0
186                         export CXX=g++-4.0
187                         ;;
188                 10.5|10.6|10.7|10.8|10.9|10.10)
189                         SDKROOT="${DEVELOPER_SDKS}/MacOSX${SDKROOT}.sdk"
190                         ;;
191                 *)
192                         usage
193                         ;;
194                 esac
195                 shift
196                 ;;
197         --libmagic-deployment=*)
198                 libmagic_deployment=$(echo ${1}|cut -d= -f2)
199                 shift
200                 ;;
201         --aspell-deployment=*)
202                 aspell_deployment=$(echo ${1}|cut -d= -f2)
203                 aspell_dictionaries=$aspell_deployment
204                 shift
205                 ;;
206         --hunspell-deployment=*)
207                 hunspell_deployment=$(echo ${1}|cut -d= -f2)
208                 hunspell_dictionaries=$hunspell_deployment
209                 shift
210                 ;;
211         --thesaurus-deployment=*)
212                 thesaurus_deployment=$(echo ${1}|cut -d= -f2)
213                 shift
214                 ;;
215         --qt-deployment=*)
216                 qt_deployment=$(echo ${1}|cut -d= -f2)
217                 shift
218                 ;;
219         --with-arch=*)
220                 ARCH=$(echo ${1}|cut -d= -f2|tr ',' ' ')
221                 ARCH_LIST="${ARCH_LIST} ${ARCH}"
222                 shift
223                 ;;
224         --with-dmg-location=*)
225                 DMGLocation=$(echo ${1}|cut -d= -f2)
226                 shift
227                 ;;
228         --with-binary-strip=yes)
229                 strip="-strip"
230                 shift
231                 ;;
232         --with-build-path=*)
233                 LyxBuildDir=$(echo ${1}|cut -d= -f2)
234                 shift
235                 ;;
236         --with-util-dir=*)
237                 LyXUtilitiesDir=$(echo ${1}|cut -d= -f2)
238                 shift
239                 ;;
240         --help|--help=*)
241                 usage "${1}"
242                 ;;
243         --without-aspell)
244                 LyXConfigureOptions="${LyXConfigureOptions} ${1}"
245                 aspell_deployment="no"
246                 shift
247                 ;;
248         --without-hunspell)
249                 LyXConfigureOptions="${LyXConfigureOptions} ${1}"
250                 hunspell_deployment="no"
251                 shift
252                 ;;
253         --only-package=*)
254                 LyxOnlyPackage=$(echo ${1}|cut -d= -f2)
255                 shift
256                 ;;
257         --*)
258                 LyXConfigureOptions="${LyXConfigureOptions} ${1}"
259                 shift
260                 ;;
261         *)
262                 break
263                 ;;
264         esac
265 done
266
267 if [ "${configure_qt_frameworks}" != "yes" ]; then
268         QtInstallDir=${QTDIR:-"/opt/qt4"}
269 fi
270
271 ARCH_LIST=${ARCH_LIST:-"ppc i386"}
272
273 aspellstrip=
274
275 LyxBuildDir=${LyxBuildDir:-$(dirname "${LyxSourceDir}")/lyx-build}
276 DMGLocation=${DMGLocation:-"${LyxBuildDir}"}
277
278 LyXUtilitiesDir=${LyXUtilitiesDir:-"${LyxBuildDir}"/utilities}
279
280 LibMagicSourceDir=${LIBMAGICDIR:-$(dirname "${LyxSourceDir}")/${LibMagicSource}}
281 LibMagicBuildDir="${LyxBuildDir}"/"${LibMagicSource}"
282 LibMagicInstallDir=${LibMagicInstallDir:-"${LyXUtilitiesDir}"}
283 LibMagicInstallHdr="${LibMagicInstallDir}/include/magic.h"
284
285 ASpellSourceDir=${ASPELLDIR:-$(dirname "${LyxSourceDir}")/${ASpellSource}}
286 ASpellBuildDir="${ASpellSourceDir}"
287 ASpellInstallDir=${ASpellInstallDir:-"${LyXUtilitiesDir}"}
288 ASpellInstallHdr="${ASpellInstallDir}/include/aspell.h"
289
290 HunSpellSourceDir=${HUNSPELLDIR:-$(dirname "${LyxSourceDir}")/${HunSpellSource}}
291 HunSpellBuildDir="${HunSpellSourceDir}"
292 HunSpellInstallDir=${HunSpellInstallDir:-"${LyXUtilitiesDir}"}
293 HunSpellInstallHdr="${HunSpellInstallDir}/include/hunspell/hunspell.h"
294
295 QtSourceDir=${QTSOURCEDIR:-$(dirname "${LyxSourceDir}")/${QtSourceVersion}}
296 QtBuildDir=${QtBuildDir:-"${LyxBuildDir}"/${QtBuildSubDir:-"qt-build"}}
297
298 DictionarySourceDir=${DICTIONARYDIR:-$(dirname "${LyxSourceDir}")/dictionaries}
299 DocumentationDir=$(dirname "${LyxSourceDir}")/Documents
300 DmgBackground="${LyxSourceDir}"/development/MacOSX/dmg-background.png
301
302 if [ -z "${LyXVersion}" ]; then
303         LyXVersion=$(grep AC_INIT "${LyxSourceDir}"/configure.ac | cut -d, -f2 | tr -d " ()")
304 fi
305 LyXVersionSuffix=${LyXVersionSuffix:-$(echo "${LyXVersion}" | cut -d. -f1-2)}
306 case "${LyXVersion}" in
307 *dev*)
308         LyXGitCommitHash=$(cd "${LyxSourceDir}" ; git log -1 --pretty=format:%h)
309         ;;
310 esac
311
312 LyxName="LyX"
313 LyxBase="${LyxName}-${LyXVersion}"
314 LyxApp="${LyxBase}.app"
315 LyxAppDir="${LyxBuildDir}"/"${LyxBase}"
316 LyxBuildDir="${LyxAppDir}.build"
317 LyxAppPrefix="${LyxAppDir}.app"
318 # if zip file is needed... remove the comment sign
319 #LyxAppZip="${LyxAppPrefix}.zip"
320
321 # ---------------------------------
322 # DON'T MODIFY ANYTHING BELOW HERE!
323 # ---------------------------------
324
325 # don't change order here...
326 case "${QtVersion}" in
327 5.0.*|5.1.*)
328         QtLibraries="QtSvg QtXml QtPrintSupport QtWidgets QtGui QtNetwork QtConcurrent QtCore"
329         QtFrameworkVersion="5"
330         ;;
331 5.2.*|5.3.*|5.4.*)
332         QtLibraries="QtSvg QtXml QtPrintSupport QtMacExtras QtWidgets QtGui QtNetwork QtConcurrent QtCore"
333         QtFrameworkVersion="5"
334         ;;
335 5*)
336         QtLibraries="QtSvg QtXml QtPrintSupport QtDBus QtMacExtras QtWidgets QtGui QtNetwork QtConcurrent QtCore"
337         QtFrameworkVersion="5"
338         ;;
339 *)
340         QtLibraries="QtSvg QtXml QtGui QtNetwork QtCore"
341         QtFrameworkVersion="4"
342         ;;
343 esac
344
345 DMGNAME="${LyxBase}${LyXGitCommitHash:+-}${LyXGitCommitHash}"
346 DMGSIZE="550m"
347
348 # Check for existing SDKs
349 SDKs=$(echo ${DEVELOPER_SDKS}/MacOSX10*sdk)
350 case $SDKs in
351 *${SDKROOT}*)
352         ;;
353 *10.6*)
354         MACOSX_DEPLOYMENT_TARGET=${MACOSX_DEPLOYMENT_TARGET:-"10.5"}; export MACOSX_DEPLOYMENT_TARGET
355         case "${MACOSX_DEPLOYMENT_TARGET}" in
356         10.6)
357                 SDKROOT="${DEVELOPER_SDKS}/MacOSX10.6.sdk"; export SDKROOT
358                 ;;
359         10.5|10.4)
360                 SDKROOT=${SDKROOT:-"${DEVELOPER_SDKS}/MacOSX10.5.sdk"}; export SDKROOT
361                 ;;
362         esac
363         ;;
364 *10.5*)
365         MACOSX_DEPLOYMENT_TARGET=${MACOSX_DEPLOYMENT_TARGET:-"10.4"}; export MACOSX_DEPLOYMENT_TARGET
366         SDKROOT=${SDKROOT:-"${DEVELOPER_SDKS}/MacOSX10.5.sdk"}; export SDKROOT
367         ;;
368 *)
369         echo Unknown or missing SDK for Mac OS X.
370         exit 1
371         ;;
372 esac
373 MYCFLAGS="-mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET}"
374
375 if [ "${configure_qt_frameworks}" != "yes" -a -d "${QtSourceDir}" -a ! \( -d "${QtBuildDir}" -a -d "${QtInstallDir}" \) ]; then
376         echo Build Qt library ${QtSourceDir}
377         if [ "${QtInstallDir}" = "${QtBuildDir}" ]; then
378                 echo Bad install directory for Qt.
379                 echo Must be different from build directory "${QtBuildDir}".
380                 exit 1
381         fi
382         (
383                 mkdir -p "${QtBuildDir}" && cd "${QtBuildDir}"
384                 for arch in ${ARCH_LIST} ; do
385                         ARCHS="${ARCHS} -arch ${arch}"
386                 done
387                 echo configure options:
388                 echo ${QtConfigureOptions} ${ARCHS} -prefix "${QtInstallDir}"
389                 "${QtSourceDir}"/configure ${QtConfigureOptions} ${ARCHS} -prefix "${QtInstallDir}"
390                 make -j1 && make -j1 install
391         )
392 fi
393 if [ -d "${QtInstallDir}" -a ! -f "${QtInstallDir}"/include/QtCore ]; then
394         cd "${QtInstallDir}" && (
395                 mkdir -p include
396                 cd include
397                 for libnm in ${QtLibraries} ; do
398                         test -d ${libnm} -o -L ${libnm} || \
399                         ( ln -s ../lib/${libnm}.framework/Headers ${libnm} && echo Link to framework ${libnm} )
400                 done
401         )
402 fi
403
404 if [ -d "${LibMagicSourceDir}" -a ! -f "${LibMagicInstallHdr}" ]; then
405         # we have a private libmagic (file(1)) source tree at hand...
406         # so let's build and install it
407         if [ -z "${LibMagicVersion}" ]; then
408                 LibMagicVersion=$(grep AC_INIT "${LibMagicSourceDir}"/configure.ac | cut -d, -f2|tr -d " ()")
409         fi
410
411         LibMagicName="LibMagic"
412         LibMagicBase="${LibMagicName}-${LibMagicVersion}"
413
414         echo Build libmagic library ${LibMagicBase}
415         echo configure options:
416         echo --prefix="${LibMagicInstallDir}" ${LibMagicConfigureOptions}
417
418         mkdir -p "${LibMagicBuildDir}" && cd "${LibMagicBuildDir}"
419
420         # ----------------------------------------
421         # Build LibMagic for different architectures
422         # ----------------------------------------
423         FILE_LIST="${LibMagicLibrary}"
424
425         for arch in ${ARCH_LIST} ; do
426                 CPPFLAGS="${SDKROOT:+-isysroot ${SDKROOT}} -arch ${arch} ${MYCFLAGS}"; export CPPFLAGS
427                 LDFLAGS="${SDKROOT:+-isysroot ${SDKROOT}} -arch ${arch} ${MYCFLAGS}"; export LDFLAGS
428                 "${LibMagicSourceDir}/configure"\
429                         --prefix="${LibMagicInstallDir}"\
430                         ${LibMagicConfigureOptions}
431                 make && make install${strip}
432                 for file in ${FILE_LIST} ; do
433                         if [ -f "${LibMagicInstallDir}"/lib/${file} ]; then
434                                 mv "${LibMagicInstallDir}"/lib/${file}\
435                                         "${LibMagicInstallDir}"/lib/${file}-${arch} 
436                         else
437                                 echo Cannot build and install LibMagic for ${arch}.
438                                 exit 1
439                         fi
440                 done
441         done
442         # -------------------------
443         # Create universal binaries
444         # -------------------------
445         for file in ${FILE_LIST} ; do
446                 OBJ_LIST=
447                 for arch in ${ARCH_LIST} ; do
448                         OBJ_LIST="${OBJ_LIST} lib/${file}-${arch}"
449                 done
450                 (
451                         cd "${LibMagicInstallDir}"
452                         lipo -create ${OBJ_LIST} -o lib/${file}
453                         # check for the "missing link"...
454                         test -f lib/libmagic.dylib || (cd lib ; ln -s "${LibMagicLibrary}" libmagic.dylib)
455                 )
456         done
457         # --------
458         # Clean up
459         # --------
460         for arch in ${ARCH_LIST} ; do
461                 rm -f "${LibMagicInstallDir}"/lib/*-${arch}
462         done
463 fi
464
465 if [ -d "${HunSpellSourceDir}" -a ! -f "${HunSpellInstallHdr}" ]; then
466         # we have a private HunSpell source tree at hand...
467         # so let's build and install it
468         if [ -z "${HunSpellVersion}" ]; then
469                 HunSpellVersion=$(grep AC_INIT "${HunSpellSourceDir}"/configure.ac | cut -d, -f2|tr -d " ()")
470         fi
471
472         HunSpellName="Hunspell"
473         HunSpellBase="${HunSpellName}-${HunSpellVersion}"
474
475         echo Build hunspell library ${HunSpellBase}
476         echo configure options:
477         echo --prefix="${HunSpellInstallDir}" ${HunspellConfigureOptions}
478
479         mkdir -p "${HunSpellBuildDir}" && cd "${HunSpellBuildDir}"
480
481         # ----------------------------------------
482         # Build HunSpell for different architectures
483         # ----------------------------------------
484         FILE_LIST="${HunSpellLibrary}"
485
486         for arch in ${ARCH_LIST} ; do
487                 make distclean
488                 CPPFLAGS="${SDKROOT:+-isysroot ${SDKROOT}} -arch ${arch} ${MYCFLAGS}"; export CPPFLAGS
489                 LDFLAGS="${SDKROOT:+-isysroot ${SDKROOT}} -arch ${arch} ${MYCFLAGS}"; export LDFLAGS
490                 "${HunSpellSourceDir}/configure"\
491                         --prefix="${HunSpellInstallDir}"\
492                         ${HunspellConfigureOptions}
493                 make && make install${strip}
494                 for file in ${FILE_LIST} ; do
495                         if [ -f "${HunSpellInstallDir}"/lib/${file} ]; then
496                                 mv "${HunSpellInstallDir}"/lib/${file}\
497                                         "${HunSpellInstallDir}"/lib/${file}-${arch} 
498                         else
499                                 echo Cannot build and install HunSpell for ${arch}.
500                                 exit 1
501                         fi
502                 done
503         done
504         # -------------------------
505         # Create universal binaries
506         # -------------------------
507         for file in ${FILE_LIST} ; do
508                 OBJ_LIST=
509                 for arch in ${ARCH_LIST} ; do
510                         OBJ_LIST="${OBJ_LIST} lib/${file}-${arch}"
511                 done
512                 (
513                         cd "${HunSpellInstallDir}"
514                         lipo -create ${OBJ_LIST} -o lib/${file}
515                         # check for the "missing link"...
516                         test -f lib/libhunspell.dylib || (cd lib ; ln -s "${HunSpellLibrary}" libhunspell.dylib)
517                 )
518         done
519         # --------
520         # Clean up
521         # --------
522         for arch in ${ARCH_LIST} ; do
523                 rm -f "${HunSpellInstallDir}"/lib/*-${arch}
524         done
525 fi
526
527 if [ -d "${ASpellSourceDir}" -a ! -f "${ASpellInstallHdr}" -a "yes" = "${aspell_deployment}" ]; then
528         # we have a private ASpell source tree at hand...
529         # so let's build and install it
530         if [ -z "${ASpellVersion}" ]; then
531                 ASpellVersion=$(grep AC_INIT "${ASpellSourceDir}"/configure.ac | cut -d, -f2|tr -d " ()")
532         fi
533
534         ASpellName="Aspell"
535         ASpellBase="${ASpellName}-${ASpellVersion}"
536
537         echo Build aspell library ${ASpellBase}
538         echo configure options:
539         echo --prefix="${ASpellInstallDir}" ${AspellConfigureOptions}
540
541         # ASpell builds inplace only :(
542         cd "${ASpellSourceDir}"
543
544         # ----------------------------------------
545         # Build ASpell for different architectures
546         # ----------------------------------------
547         FILE_LIST="${ASpellLibrary}"
548
549         for arch in ${ARCH_LIST} ; do
550                 make distclean
551                 CPPFLAGS="${SDKROOT:+-isysroot ${SDKROOT}} -arch ${arch} ${MYCFLAGS}"; export CPPFLAGS
552                 LDFLAGS="${SDKROOT:+-isysroot ${SDKROOT}} -arch ${arch} ${MYCFLAGS}"; export LDFLAGS
553                 CXXFLAGS=-g "${ASpellSourceDir}/configure"\
554                         --prefix="${ASpellInstallDir}"\
555                         ${AspellConfigureOptions}
556                 make && make install${aspellstrip}
557                 for file in ${FILE_LIST} ; do
558                         if [ -f "${ASpellInstallDir}"/lib/${file} ]; then
559                                 mv "${ASpellInstallDir}"/lib/${file}\
560                                         "${ASpellInstallDir}"/lib/${file}-${arch} 
561                         else
562                                 echo Cannot build and install ASpell for ${arch}.
563                                 exit 1
564                         fi
565                 done
566         done
567         # -------------------------
568         # Create universal binaries
569         # -------------------------
570         for file in ${FILE_LIST} ; do
571                 OBJ_LIST=
572                 for arch in ${ARCH_LIST} ; do
573                         OBJ_LIST="${OBJ_LIST} lib/${file}-${arch}"
574                 done
575                 (
576                         cd "${ASpellInstallDir}"
577                         lipo -create ${OBJ_LIST} -o lib/${file}
578                 )
579         done
580         # --------
581         # Clean up
582         # --------
583         for arch in ${ARCH_LIST} ; do
584                 rm -f "${ASpellInstallDir}"/lib/*-${arch}
585         done
586 fi
587
588
589 framework_name() {
590         echo "Frameworks/${1}.framework"
591 }
592
593 LYX_FILE_LIST="lyx lyxclient tex2lyx"
594 BUNDLE_PATH="Contents/MacOS"
595 LYX_BUNDLE_PATH="${LyxAppPrefix}/${BUNDLE_PATH}"
596 build_lyx() {
597         # Clear Output
598         if [ -n "${LyxAppZip}" -a -f "${LyxAppZip}" ]; then rm "${LyxAppZip}"; fi
599         if [ -d "${LyxAppPrefix}" ]; then rm -rf "${LyxAppPrefix}"; fi
600
601         # -------------------------------------
602         # Automate configure check
603         # -------------------------------------
604         if [ ! -f "${LyxSourceDir}"/configure -o "${LyxSourceDir}"/configure -ot "${LyxSourceDir}"/configure.ac ]; then
605                 ( cd "${LyxSourceDir}" && sh autogen.sh )
606         else
607                 find "${LyxSourceDir}" -name Makefile.am -print | while read file ; do
608                         dname=$(dirname "$file")
609                         if [ -f "$dname/Makefile.in" -a "$dname/Makefile.in" -ot "$file" ]; then
610                                 ( cd "${LyxSourceDir}" && sh autogen.sh )
611                                 break
612                         fi
613                 done
614         fi
615         # -------------------------------------
616         # Build LyX for different architectures
617         # -------------------------------------
618
619         if [ -d "${ASpellInstallDir}" -a "yes" = "${aspell_deployment}" ]; then
620                 ConfigureExtraInc="--with-extra-inc=${ASpellInstallDir}/include"
621                 ConfigureExtraLib="--with-extra-lib=${ASpellInstallDir}/lib"
622         fi
623
624         if [ -d "${HunSpellInstallDir}" -a "yes" = "${hunspell_deployment}" ]; then
625                 HunSpellFramework=$(framework_name Hunspell)
626                 HunSpellFramework=$(basename "${HunSpellFramework}")
627                 ConfigureExtraInc="--with-extra-inc=${HunSpellInstallDir}/include"
628                 ConfigureExtraLib="--with-extra-lib=${HunSpellInstallDir}/lib"
629                 # LyXConfigureOptions="${LyXConfigureOptions} --with-hunspell-framework=${HunSpellFramework}"
630         fi
631         LyXConfigureOptions="${LyXConfigureOptions} ${ConfigureExtraInc}"
632         LyXConfigureOptions="${LyXConfigureOptions} ${ConfigureExtraLib}"
633
634         for arch in ${ARCH_LIST} ; do
635
636                 if [ -d "${LyxBuildDir}" ];  then rm -r "${LyxBuildDir}"; fi
637                 mkdir -p "${LyxBuildDir}" && cd "${LyxBuildDir}"
638
639                 CPPFLAGS="${SDKROOT:+-isysroot ${SDKROOT}} -arch ${arch} ${MYCFLAGS}"
640                 LDFLAGS="${SDKROOT:+-isysroot ${SDKROOT}} -arch ${arch} ${MYCFLAGS}"
641
642                 if [ "$configure_qt_frameworks" = "yes" ]; then
643                         export QT_CORE_CFLAGS="-FQtCore"
644                         export QT_CORE_LIBS="-framework QtCore"
645                         export QT_FRONTEND_CFLAGS="-FQtGui"
646                         export QT_FRONTEND_LIBS="-framework QtGui"
647                         CPPFLAGS="${CPPFLAGS} -I${SDKROOT}/Library/Frameworks/QtCore.framework/Headers"
648                         CPPFLAGS="${CPPFLAGS} -I${SDKROOT}/Library/Frameworks/QtGui.framework/Headers"
649                 fi
650
651                 echo LDFLAGS="${LDFLAGS}"
652                 export LDFLAGS
653                 echo CPPFLAGS="${CPPFLAGS}"
654                 export CPPFLAGS
655                 echo CONFIGURE_OPTIONS="${LyXConfigureOptions}" ${QtInstallDir:+"--with-qt-dir=${QtInstallDir}"}
656                 "${LyxSourceDir}/configure"\
657                         --prefix="${LyxAppPrefix}" --with-version-suffix="-${LyXVersionSuffix}"\
658                         ${QtInstallDir:+"--with-qt-dir=${QtInstallDir}"} \
659                         ${LyXConfigureOptions}\
660                         --enable-build-type=rel && \
661                 make ${MAKEJOBS} && make install${strip}
662                 for file in ${LYX_FILE_LIST} ; do
663                         if [ -f "${LYX_BUNDLE_PATH}/${file}" ]; then
664                                 mv "${LYX_BUNDLE_PATH}/${file}"\
665                                         "${LYX_BUNDLE_PATH}/${file}-${arch}" 
666                         else
667                                 echo ERROR: Cannot build and install LyX for ${arch}.
668                                 exit 1
669                         fi
670                 done
671         done
672 }
673
674 content_directory() {
675         target="$1"
676         content=$(dirname "${target}")
677         content=$(dirname "${content}")
678         echo "${content}"
679 }
680
681 installname() {
682                 echo install_name_tool "$@"
683                 install_name_tool "$@"
684 }
685
686 private_framework() {
687         fwdir=$(framework_name "$1")
688         source="$2"
689         target="$3"
690         condir=$(content_directory "${target}")
691         libnm=$(basename "${source}")
692         mkdir -p "${condir}/${fwdir}"
693         if [ ! -f "${condir}/${fwdir}/${libnm}" ]; then
694                 cp -p "${source}" "${condir}/${fwdir}"
695                 installname -id "@executable_path/../${fwdir}/${libnm}" "${condir}/${fwdir}/${libnm}"
696         fi
697         installname -change "${source}" "@executable_path/../${fwdir}/${libnm}" "${target}"
698 }
699
700 deploy_qtlibs() {
701         source="${QtInstallDir}"
702         target="$1"
703         version="Versions/${QtFrameworkVersion}/"
704         condir=$(content_directory "${target}")
705         mkdir -p "${condir}/Resources"
706         test -f "${condir}/Resources/qt.conf" || cat - > "${condir}/Resources/qt.conf" <<-EOF
707 [Paths]
708 Plugins = PlugIns
709 Translations = translations
710 EOF
711         if [ ! -d "${condir}/PlugIns" ]; then
712                 mkdir -p "${condir}/PlugIns"
713                 find "${source}/plugins" -name \*.dylib -print | grep -v _debug.dylib | while read libname ; do
714                         echo Copy plugin "${libname}"
715                         dylib=$(basename "${libname}")
716                         dirname=$(dirname "${libname}")
717                         dirname=$(basename "${dirname}")
718                         mkdir -p "${condir}/PlugIns/${dirname}"
719                         cp -p "${libname}" "${condir}/PlugIns/${dirname}"
720                 done
721         fi
722         for libnm in ${QtLibraries} ; do
723                 fwdir=$(framework_name "$libnm")
724                 dirname=$(dirname "${fwdir}")
725                 mkdir -p "${condir}/${dirname}"
726                 dirname=$(basename "${fwdir}")
727                 test -d "${condir}/${fwdir}" || (
728                         echo Copy framework "${source}/lib/"$(basename "${fwdir}")
729                         cp -pR "${source}/lib/"$(basename "${fwdir}") "${condir}/${fwdir}"
730                         installname -id "@executable_path/../${fwdir}/${version}${libnm}" "${condir}/${fwdir}/${version}${libnm}"
731                         find "${condir}/PlugIns" "${condir}/"$(dirname "${fwdir}") -name Headers -prune -o -type f -print | while read filename ; do
732                                 if [ "${filename}" != "${target}" ]; then
733                                         otool -L "${filename}" 2>/dev/null | sort -u | while read library ; do
734                                                 # pattern match for: /path/to/qt/lib/QtGui.framework/Versions/4/QtGui (compatibility version 4.6.0, current version 4.6.2)
735                                                 case "${library}" in
736                                                 *@rpath/*"${libnm}"*"("*version*")"*)
737                                                         echo rpath based name for ${libnm} is ok.
738                                                         ;;
739                                                 *"${libnm}"*"("*version*")"*)
740                                                         installname -change\
741                                                                 "${source}/lib/${dirname}/${version}${libnm}"\
742                                                                 "@executable_path/../${fwdir}/${version}${libnm}"\
743                                                                 "${filename}"
744                                                         ;;
745                                                 esac
746                                         done
747                                 fi
748                         done
749                 )
750                 installname -change\
751                         "${source}/lib/${dirname}/${version}${libnm}"\
752                         "@executable_path/../${fwdir}/${version}${libnm}"\
753                         "${target}"
754         done
755         if [ ! -d "${condir}/translations" ]; then
756                 mkdir -p "${condir}/translations"
757         fi
758         echo Copy Qt translations to "${condir}/translations"
759         cp -p "${source}"/translations/qt_*.qm "${condir}/translations"
760 }
761
762 # -------------------------
763 # Create universal binaries
764 # -------------------------
765 convert_universal() {
766         cd "${LyxAppPrefix}"
767         for file in ${LYX_FILE_LIST} ; do
768                 OBJ_LIST=
769                 for arch in ${ARCH_LIST} ; do
770                         if [ -f "${BUNDLE_PATH}/${file}-${arch}" ]; then
771                                 OBJ_LIST="${OBJ_LIST} ${BUNDLE_PATH}/${file}-${arch}"
772                         fi
773                 done
774                 if [ -n "${OBJ_LIST}" ]; then
775                         lipo -create ${OBJ_LIST} -o "${BUNDLE_PATH}/${file}"
776                 fi
777                 if [ -f "${LibMagicInstallDir}/lib/${LibMagicLibrary}" -a "yes" = "${libmagic_deployment}" ]; then
778                         private_framework LibMagic "${LibMagicInstallDir}/lib/${LibMagicLibrary}" "${LYX_BUNDLE_PATH}/${file}"
779                 fi
780                 if [ -f "${ASpellInstallDir}/lib/${ASpellLibrary}" -a "yes" = "${aspell_deployment}" ]; then
781                         private_framework Aspell "${ASpellInstallDir}/lib/${ASpellLibrary}" "${LYX_BUNDLE_PATH}/${file}"
782                 fi
783                 if [ -f "${HunSpellInstallDir}/lib/${HunSpellLibrary}" -a "yes" = "${hunspell_deployment}" ]; then
784                         private_framework Hunspell "${HunSpellInstallDir}/lib/${HunSpellLibrary}" "${LYX_BUNDLE_PATH}/${file}"
785                 fi
786                 if [ -d "${QtInstallDir}/lib/QtCore.framework/Versions/${QtFrameworkVersion}" -a "yes" = "${qt_deployment}" ]; then
787                         deploy_qtlibs "${LYX_BUNDLE_PATH}/${file}"
788                 fi
789                 otool -L "${BUNDLE_PATH}/${file}" | while read reference ; do
790                         case "${reference}" in
791                         *"${LyxBuildDir}"*"("*")")
792                                 echo ERROR: Bad reference to "${reference}" found!!
793                                 ;;
794                         esac
795                 done
796         done
797         for arch in ${ARCH_LIST} ; do
798                 rm -f ${BUNDLE_PATH}/*-${arch}
799         done
800 }
801
802 deduplicate() {
803         find "$@" -type f -print | while read file ; do
804                 echo $(md5 -q "$file") "$file"
805         done | sort | while read hash file ; do
806                 if [ "$phash" = "$hash" ]; then
807                         cmp -s "$pfile" "$file" && (
808                                 rm "$file"
809                                 ln -s "$pfile" "$file" && echo link for "$file" created
810                         )
811                 fi
812                 phash="$hash"
813                 pfile="$file"
814         done
815 }
816
817 copy_dictionaries() {
818         if [ -d "${ASpellInstallDir}" -a "yes" = "${aspell_dictionaries}" ]; then
819                 ASpellResources="${LyxAppPrefix}/Contents/Resources"
820                 # try to reuse macports dictionaries for now
821                 if [ -d /opt/local/lib/aspell-0.60 ]; then ASpellInstallDir=/opt/local ; fi
822                 mkdir -p "${ASpellResources}"
823                 echo Copy Aspell dictionaries from "${ASpellInstallDir}"
824                 mkdir -p "${ASpellResources}"/data "${ASpellResources}"/dicts
825                 cp -p -r "${ASpellInstallDir}/lib/aspell-0.60"/* "${ASpellResources}"/data
826                 cp -p -r "${ASpellInstallDir}/share/aspell"/* "${ASpellResources}"/dicts
827         fi
828         if [ -d "${HunSpellInstallDir}" -a "yes" = "${hunspell_dictionaries}" ]; then
829                 HunSpellResources="${LyxAppPrefix}/Contents/Resources"
830                 if [ -d "${DictionarySourceDir}" ]; then
831                         ( cd "${DictionarySourceDir}" && find dicts -name .svn -prune -o -type f -print | cpio -pmdv "${HunSpellResources}" )
832                         deduplicate "${HunSpellResources}"/dicts
833                 fi
834         fi
835         if [ -d "${DictionarySourceDir}" -a "yes" = "${thesaurus_deployment}" ]; then
836                 MyThesResources="${LyxAppPrefix}/Contents/Resources"
837                 ( cd "${DictionarySourceDir}" && find thes -name .svn -prune -o -type f -print | cpio -pmdv "${MyThesResources}" )
838                 deduplicate "${MyThesResources}"/thes
839         fi
840 }
841
842 set_bundle_display_options() {
843         X_BOUNDS=$2
844         Y_BOUNDS=$3
845         Y_POSITION=$((Y_BOUNDS - 65))
846         Y_BOUNDS=$((Y_BOUNDS + 20))
847         LYX_X_POSITION=$((X_BOUNDS / 4))
848         LYX_Y_POSITION=$Y_POSITION
849         APP_X_POSITION=$((3 * X_BOUNDS / 4))
850         APP_Y_POSITION=$Y_POSITION
851         WITH_DOCUMENTS=$(test -d "${1}/Documents" && echo true || echo false)
852         osascript <<-EOF
853         tell application "Finder"
854         set f to POSIX file ("${1}" as string) as alias
855         tell folder f
856             open
857             tell container window
858                 set toolbar visible to false
859                 set statusbar visible to false
860                 set current view to icon view
861                 delay 1 -- sync
862                 set the bounds to {20, 50, $X_BOUNDS, $Y_BOUNDS}
863             end tell
864             delay 1 -- sync
865             set icon size of the icon view options of container window to 64
866             set arrangement of the icon view options of container window to not arranged
867             if ${WITH_DOCUMENTS} then
868                set position of item "Documents" to {$LYX_X_POSITION,0}
869             end if
870             set position of item "${LyxName}.app" to {$LYX_X_POSITION,$LYX_Y_POSITION}
871             set position of item "Applications" to {$APP_X_POSITION,$APP_Y_POSITION}
872             set background picture of the icon view options\
873                of container window to file "background.png" of folder "Pictures"
874             set the bounds of the container window to {0, 0, $X_BOUNDS, $Y_BOUNDS}
875             update without registering applications
876             delay 5 -- sync
877             close
878         end tell
879         delay 5 -- sync
880     end tell
881 EOF
882 }
883
884 make_dmg() {
885         cd "${1}"
886
887         BGSIZE=$(file "$DmgBackground" | awk -F , '/PNG/{print $2 }' | tr x ' ')
888         BG_W=$(echo ${BGSIZE} | awk '{print $1 }')
889         BG_H=$(echo ${BGSIZE} | awk '{print $2 }')
890
891         rm -f "${DMGNAME}.sparseimage" "${DMGNAME}.dmg"
892
893         hdiutil create -type SPARSE -size ${DMGSIZE:-"250m"} -fs HFS+ -volname "${LyxBase}" "${DMGNAME}"
894         # Unmount currently mounted disk image
895         mount | grep "${LyxBase}" && umount /Volumes/"${LyxBase}"
896         test -d /Volumes/"${LyxBase}" && rmdir /Volumes/"${LyxBase}"
897
898         # Mount the disk image
899         hdiutil attach "${DMGNAME}.sparseimage"
900
901         # Obtain device information
902         DEVS=$(hdiutil attach "${DMGNAME}.sparseimage" | cut -f 1)
903         DEV=$(echo $DEVS | cut -f 1 -d ' ')
904         VOLUME=$(mount |grep ${DEV} | cut -f 3 -d ' ')
905
906         # copy in the application bundle
907         cp -Rp "${LyxAppDir}.app" "${VOLUME}/${LyxName}.app"
908
909         # copy in background image
910         mkdir -p "${VOLUME}/Pictures"
911         cp "${DmgBackground}" "${VOLUME}/Pictures/background.png"
912         # symlink applications
913         ln -s /Applications/ "${VOLUME}"/Applications
914         test -d "${DocumentationDir}" && cp -r "${DocumentationDir}" "${VOLUME}"
915         set_bundle_display_options "${VOLUME}" ${BG_W} ${BG_H}
916         ${XCODE_DEVELOPER}/Tools/SetFile -a C "${VOLUME}"
917         mv "${VOLUME}/Pictures" "${VOLUME}/.Pictures"
918
919         # Unmount the disk image
920         hdiutil detach ${DEV}
921
922         # Convert the disk image to read-only
923         hdiutil convert "${DMGNAME}.sparseimage" -format UDBZ -o "${DMGNAME}.dmg"
924         rm -f "${DMGNAME}.sparseimage"
925 }
926
927 # ------------------------------
928 # Building distribution packages
929 # ------------------------------
930
931 build_package() {
932         test -n "${LyxAppZip}" && (
933                 cd "${LyxAppPrefix}" && zip -r "${LyxAppZip}" .
934         )
935
936         DMGARCH=""
937         for arch in ${ARCH_LIST} ; do
938                 DMGARCH="${DMGARCH}-${arch}"
939         done
940         QtDmgArchSuffix=${QtMajorVersion}${DMGARCH}${QtAPI}.dmg
941
942         test -n "${DMGLocation}" && (
943                 make_dmg "${DMGLocation}"
944                 if [ -d "${QtInstallDir}/lib/QtCore.framework/Versions/${QtFrameworkVersion}" -a "yes" = "${qt_deployment}" ]; then
945                         rm -f "${DMGLocation}/${DMGNAME}+${QtDmgArchSuffix}"
946                         echo move to "${DMGLocation}/${DMGNAME}+${QtDmgArchSuffix}"
947                         mv "${DMGLocation}/${DMGNAME}.dmg" "${DMGLocation}/${DMGNAME}+${QtDmgArchSuffix}"
948                 fi
949         )
950 }
951
952 # ------------------------------
953 # main block
954 # ------------------------------
955
956 if [ ${LyxOnlyPackage:-"no"} = "no" ]; then
957         build_lyx
958         convert_universal
959         copy_dictionaries
960 fi
961 build_package