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