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