]> git.lyx.org Git - lyx.git/blob - development/LyX-Mac-binary-release.sh
Customization: correct some color names.
[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 (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 "${condir}/translations" ]; then
787                 mkdir -p "${condir}/translations"
788         fi
789         echo Copy Qt translations to "${condir}/translations"
790         cp -p "${source}"/translations/qt_*.qm "${condir}/translations"
791 }
792
793 # -------------------------
794 # Create universal binaries
795 # -------------------------
796 convert_universal() {
797         cd "${LyxAppPrefix}"
798         for file in ${LYX_FILE_LIST} ; do
799                 OBJ_LIST=
800                 for arch in ${ARCH_LIST} ; do
801                         if [ -f "${BUNDLE_PATH}/${file}-${arch}" ]; then
802                                 OBJ_LIST="${OBJ_LIST} ${BUNDLE_PATH}/${file}-${arch}"
803                         fi
804                 done
805                 if [ -n "${OBJ_LIST}" ]; then
806                         lipo -create ${OBJ_LIST} -o "${BUNDLE_PATH}/${file}"
807                 fi
808                 if [ -f "${LibMagicInstallDir}/lib/${LibMagicLibrary}" -a "yes" = "${libmagic_deployment}" ]; then
809                         private_framework LibMagic "${LibMagicInstallDir}/lib/${LibMagicLibrary}" "${LYX_BUNDLE_PATH}/${file}"
810                 fi
811                 if [ -f "${ASpellInstallDir}/lib/${ASpellLibrary}" -a "yes" = "${aspell_deployment}" ]; then
812                         private_framework Aspell "${ASpellInstallDir}/lib/${ASpellLibrary}" "${LYX_BUNDLE_PATH}/${file}"
813                 fi
814                 if [ -f "${HunSpellInstallDir}/lib/${HunSpellLibrary}" -a "yes" = "${hunspell_deployment}" ]; then
815                         private_framework Hunspell "${HunSpellInstallDir}/lib/${HunSpellLibrary}" "${LYX_BUNDLE_PATH}/${file}"
816                 fi
817                 if [ -d "${QtInstallDir}/lib/QtCore.framework/Versions/${QtFrameworkVersion}" -a "yes" = "${qt_deployment}" ]; then
818                         deploy_qtlibs "${LYX_BUNDLE_PATH}/${file}"
819                 fi
820                 otool -L "${BUNDLE_PATH}/${file}" | while read reference ; do
821                         case "${reference}" in
822                         *"${LyxBuildDir}"*"("*")")
823                                 echo ERROR: Bad reference to "${reference}" found!!
824                                 ;;
825                         esac
826                 done
827         done
828         for arch in ${ARCH_LIST} ; do
829                 rm -f ${BUNDLE_PATH}/*-${arch}
830         done
831 }
832
833 deduplicate() {
834         find "$@" -type f -print | while read file ; do
835                 echo $(md5 -q "$file") "$file"
836         done | sort | while read hash file ; do
837                 ppath=$(dirname "$pfile")
838                 path=$(dirname "$file")
839                 if [ "$phash" = "$hash" -a "$ppath" = "$path" ]; then
840                         pname=$(basename "$pfile")
841                         name=$(basename "$file")
842                         cmp -s "$pfile" "$file" && (
843                                 rm "$file"
844                                 cd "$path" && ln -s "$pname" "$name" && echo link for "$file" created
845                         )
846                 fi
847                 phash="$hash"
848                 pfile="$file"
849         done
850 }
851
852 copy_dictionaries() {
853         if [ -d "${ASpellInstallDir}" -a "yes" = "${aspell_dictionaries}" ]; then
854                 ASpellResources="${LyxAppPrefix}/Contents/Resources"
855                 # try to reuse macports dictionaries for now
856                 if [ -d /opt/local/lib/aspell-0.60 ]; then ASpellInstallDir=/opt/local ; fi
857                 mkdir -p "${ASpellResources}"
858                 echo Copy Aspell dictionaries from "${ASpellInstallDir}"
859                 mkdir -p "${ASpellResources}"/data "${ASpellResources}"/dicts
860                 cp -p -r "${ASpellInstallDir}/lib/aspell-0.60"/* "${ASpellResources}"/data
861                 cp -p -r "${ASpellInstallDir}/share/aspell"/* "${ASpellResources}"/dicts
862         fi
863         if [ -d "${HunSpellInstallDir}" -a "yes" = "${hunspell_dictionaries}" ]; then
864                 HunSpellResources="${LyxAppPrefix}/Contents/Resources"
865                 if [ -d "${DictionarySourceDir}" ]; then
866                         ( cd "${DictionarySourceDir}" && find dicts -name .svn -prune -o -type f -print | cpio -pmdv "${HunSpellResources}" )
867                         deduplicate "${HunSpellResources}"/dicts
868                 fi
869         fi
870         if [ -d "${DictionarySourceDir}" -a "yes" = "${thesaurus_deployment}" ]; then
871                 MyThesResources="${LyxAppPrefix}/Contents/Resources"
872                 ( cd "${DictionarySourceDir}" && find thes -name .svn -prune -o -type f -print | cpio -pmdv "${MyThesResources}" )
873                 deduplicate "${MyThesResources}"/thes
874         fi
875 }
876
877 set_bundle_display_options() {
878         X_BOUNDS=$2
879         Y_BOUNDS=$3
880         Y_POSITION=$((Y_BOUNDS - 65))
881         Y_BOUNDS=$((Y_BOUNDS + 20))
882         LYX_X_POSITION=$((X_BOUNDS / 4))
883         LYX_Y_POSITION=$Y_POSITION
884         APP_X_POSITION=$((3 * X_BOUNDS / 4))
885         APP_Y_POSITION=$Y_POSITION
886         WITH_DOCUMENTS=$(test -d "${1}/Documents" && echo true || echo false)
887         osascript <<-EOF
888         tell application "Finder"
889         set f to POSIX file ("${1}" as string) as alias
890         tell folder f
891             open
892             tell container window
893                 set toolbar visible to false
894                 set statusbar visible to false
895                 set current view to icon view
896                 delay 1 -- sync
897                 set the bounds to {20, 50, $X_BOUNDS, $Y_BOUNDS}
898             end tell
899             delay 1 -- sync
900             set icon size of the icon view options of container window to 64
901             set arrangement of the icon view options of container window to not arranged
902             if ${WITH_DOCUMENTS} then
903                set position of item "Documents" to {$LYX_X_POSITION,0}
904             end if
905             set position of item "${LyxName}.app" to {$LYX_X_POSITION,$LYX_Y_POSITION}
906             set position of item "Applications" to {$APP_X_POSITION,$APP_Y_POSITION}
907             set background picture of the icon view options\
908                of container window to file "background.png" of folder "Pictures"
909             set the bounds of the container window to {0, 0, $X_BOUNDS, $Y_BOUNDS}
910             update without registering applications
911             delay 5 -- sync
912             close
913         end tell
914         delay 5 -- sync
915     end tell
916 EOF
917 }
918
919 make_dmg() {
920         cd "${1}"
921
922         BGSIZE=$(file "$DmgBackground" | awk -F , '/PNG/{print $2 }' | tr x ' ')
923         BG_W=$(echo ${BGSIZE} | awk '{print $1 }')
924         BG_H=$(echo ${BGSIZE} | awk '{print $2 }')
925
926         rm -f "${DMGNAME}.sparseimage" "${DMGNAME}.dmg"
927
928         hdiutil create -type SPARSE -size ${DMGSIZE:-"250m"} -fs HFS+ -volname "${LyxBase}" "${DMGNAME}"
929         # Unmount currently mounted disk image
930         mount | grep "${LyxBase}" && umount /Volumes/"${LyxBase}"
931         test -d /Volumes/"${LyxBase}" && rmdir /Volumes/"${LyxBase}"
932
933         # Mount the disk image
934         hdiutil attach "${DMGNAME}.sparseimage"
935
936         # Obtain device information
937         DEVS=$(hdiutil attach "${DMGNAME}.sparseimage" | cut -f 1)
938         DEV=$(echo $DEVS | cut -f 1 -d ' ')
939         VOLUME=$(mount |grep ${DEV} | cut -f 3 -d ' ')
940
941         # copy in the application bundle
942         cp -Rp "${LyxAppDir}.app" "${VOLUME}/${LyxName}.app"
943
944         # copy in background image
945         mkdir -p "${VOLUME}/Pictures"
946         cp "${DmgBackground}" "${VOLUME}/Pictures/background.png"
947         # symlink applications
948         ln -s /Applications/ "${VOLUME}"/Applications
949         test -d "${DocumentationDir}" && cp -r "${DocumentationDir}" "${VOLUME}"
950         set_bundle_display_options "${VOLUME}" ${BG_W} ${BG_H}
951         ${XCODE_DEVELOPER}/Tools/SetFile -a C "${VOLUME}"
952         mv "${VOLUME}/Pictures" "${VOLUME}/.Pictures"
953
954         # Unmount the disk image
955         hdiutil detach ${DEV}
956
957         # Convert the disk image to read-only
958         hdiutil convert "${DMGNAME}.sparseimage" -format UDBZ -o "${DMGNAME}.dmg"
959         rm -f "${DMGNAME}.sparseimage"
960 }
961
962 # ------------------------------
963 # Building distribution packages
964 # ------------------------------
965
966 build_package() {
967         test -n "${LyxAppZip}" && (
968                 cd "${LyxAppPrefix}" && zip -r "${LyxAppZip}" .
969         )
970
971         DMGARCH=""
972         for arch in ${ARCH_LIST} ; do
973                 DMGARCH="${DMGARCH}-${arch}"
974         done
975         QtDmgArchSuffix=${QtMajorVersion}${DMGARCH}${QtAPI}.dmg
976
977         test -n "${DMGLocation}" && (
978                 make_dmg "${DMGLocation}"
979                 if [ -d "${QtInstallDir}/lib/QtCore.framework/Versions/${QtFrameworkVersion}" -a "yes" = "${qt_deployment}" ]; then
980                         rm -f "${DMGLocation}/${DMGNAME}+${QtDmgArchSuffix}"
981                         echo move to "${DMGLocation}/${DMGNAME}+${QtDmgArchSuffix}"
982                         mv "${DMGLocation}/${DMGNAME}.dmg" "${DMGLocation}/${DMGNAME}+${QtDmgArchSuffix}"
983                 fi
984         )
985 }
986
987 # ------------------------------
988 # main block
989 # ------------------------------
990
991 if [ ${LyxOnlyPackage:-"no"} = "no" ]; then
992         build_lyx
993         convert_universal
994         copy_dictionaries
995 fi
996 build_package