]> git.lyx.org Git - features.git/blob - development/LyX-Mac-binary-release.sh
2f8897fac51a7b55298576df5b9990b520b6748d
[features.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*|5.7*)
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         --enable-cxx11)
280                 LyXConfigureOptions="${LyXConfigureOptions} ${1}"
281                 EnableCXX11="--enable-cxx11"
282                 shift
283                 ;;
284         --*)
285                 LyXConfigureOptions="${LyXConfigureOptions} ${1}"
286                 shift
287                 ;;
288         *)
289                 break
290                 ;;
291         esac
292 done
293
294 if [ "${configure_qt_frameworks}" != "yes" ]; then
295         QtInstallDir=${QTDIR:-"/opt/qt4"}
296 fi
297
298 ARCH_LIST=${ARCH_LIST:-"ppc i386"}
299
300 aspellstrip=
301
302 LyxBuildDir=${LyxBuildDir:-$(dirname "${LyxSourceDir}")/lyx-build}
303 DMGLocation=${DMGLocation:-"${LyxBuildDir}"}
304
305 LyXUtilitiesDir=${LyXUtilitiesDir:-"${LyxBuildDir}"/utilities}
306
307 LibMagicSourceDir=${LIBMAGICDIR:-$(dirname "${LyxSourceDir}")/${LibMagicSource}}
308 LibMagicBuildDir="${LyxBuildDir}"/"${LibMagicSource}"
309 LibMagicInstallDir=${LibMagicInstallDir:-"${LyXUtilitiesDir}"}
310 LibMagicInstallHdr="${LibMagicInstallDir}/include/magic.h"
311
312 ASpellSourceDir=${ASPELLDIR:-$(dirname "${LyxSourceDir}")/${ASpellSource}}
313 ASpellBuildDir="${ASpellSourceDir}"
314 ASpellInstallDir=${ASpellInstallDir:-"${LyXUtilitiesDir}"}
315 ASpellInstallHdr="${ASpellInstallDir}/include/aspell.h"
316
317 HunSpellSourceDir=${HUNSPELLDIR:-$(dirname "${LyxSourceDir}")/${HunSpellSource}}
318 HunSpellBuildDir="${HunSpellSourceDir}"
319 HunSpellInstallDir=${HunSpellInstallDir:-"${LyXUtilitiesDir}"}
320 HunSpellInstallHdr="${HunSpellInstallDir}/include/hunspell/hunspell.h"
321
322 QtSourceDir=${QTSOURCEDIR:-$(dirname "${LyxSourceDir}")/${QtSourceVersion}}
323 QtBuildDir=${QtBuildDir:-"${LyxBuildDir}"/${QtBuildSubDir:-"qt-build"}}
324
325 DictionarySourceDir=${DICTIONARYDIR:-$(dirname "${LyxSourceDir}")/dictionaries}
326 DocumentationDir=$(dirname "${LyxSourceDir}")/Documents
327 DmgBackground="${LyxSourceDir}"/development/MacOSX/dmg-background.png
328
329 if [ -z "${LyXVersion}" ]; then
330         LyXVersion=$(grep AC_INIT "${LyxSourceDir}"/configure.ac | cut -d, -f2 | tr -d " ()")
331 fi
332 LyXVersionSuffix=${LyXVersionSuffix:-$(echo "${LyXVersion}" | cut -d. -f1-2)}
333 case "${LyXVersion}" in
334 *dev*)
335         LyXGitCommitHash=$(cd "${LyxSourceDir}" ; git log -1 --pretty=format:%h)
336         ;;
337 esac
338
339 LyxName="LyX"
340 LyxBase="${LyxName}-${LyXVersion}"
341 LyxApp="${LyxBase}.app"
342 LyxAppDir="${LyxBuildDir}"/"${LyxBase}"
343 LyxBuildDir="${LyxAppDir}.build"
344 LyxAppPrefix="${LyxAppDir}.app"
345 # if zip file is needed... remove the comment sign
346 #LyxAppZip="${LyxAppPrefix}.zip"
347
348 # ---------------------------------
349 # DON'T MODIFY ANYTHING BELOW HERE!
350 # ---------------------------------
351
352 # don't change order here...
353 case "${QtVersion}" in
354 5.0.*|5.1.*)
355         QtLibraries="QtSvg QtXml QtPrintSupport QtWidgets QtGui QtNetwork QtConcurrent QtCore"
356         QtFrameworkVersion="5"
357         ;;
358 5*)
359         QtLibraries="QtSvg QtXml QtPrintSupport QtMacExtras QtWidgets QtGui QtNetwork QtConcurrent QtCore"
360         QtFrameworkVersion="5"
361         ;;
362 *)
363         QtLibraries="QtSvg QtXml QtGui QtNetwork QtCore"
364         QtFrameworkVersion="4"
365         ;;
366 esac
367
368 DMGNAME="${LyxBase}${LyXGitCommitHash:+-}${LyXGitCommitHash}"
369 DMGSIZE="550m"
370
371 # Check for existing SDKs
372 SDKs=$(echo ${DEVELOPER_SDKS}/MacOSX10*sdk)
373 case $SDKs in
374 *${SDKROOT}*)
375         ;;
376 *10.6*)
377         MACOSX_DEPLOYMENT_TARGET=${MACOSX_DEPLOYMENT_TARGET:-"10.5"}; export MACOSX_DEPLOYMENT_TARGET
378         case "${MACOSX_DEPLOYMENT_TARGET}" in
379         10.6)
380                 SDKROOT="${DEVELOPER_SDKS}/MacOSX10.6.sdk"; export SDKROOT
381                 ;;
382         10.5|10.4)
383                 SDKROOT=${SDKROOT:-"${DEVELOPER_SDKS}/MacOSX10.5.sdk"}; export SDKROOT
384                 ;;
385         esac
386         ;;
387 *10.5*)
388         MACOSX_DEPLOYMENT_TARGET=${MACOSX_DEPLOYMENT_TARGET:-"10.4"}; export MACOSX_DEPLOYMENT_TARGET
389         SDKROOT=${SDKROOT:-"${DEVELOPER_SDKS}/MacOSX10.5.sdk"}; export SDKROOT
390         ;;
391 *)
392         echo Unknown or missing SDK for Mac OS X.
393         exit 1
394         ;;
395 esac
396 MYCFLAGS="-mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET}"
397
398 build_qt() {
399         echo Build Qt library ${QtSourceDir}
400         if [ "${QtInstallDir}" = "${QtBuildDir}" ]; then
401                 echo Bad install directory for Qt.
402                 echo Must be different from build directory "${QtBuildDir}".
403                 exit 1
404         fi
405         (
406                 mkdir -p "${QtBuildDir}" && cd "${QtBuildDir}"
407                 echo configure options:
408                 echo ${QtConfigureOptions} ${QTARCHS} -prefix "${QtInstallDir}"
409                 "${QtSourceDir}"/configure ${QtConfigureOptions} ${QTARCHS} -prefix "${QtInstallDir}"
410                 make -j1 && make -j1 install
411         )
412         if [ -d "${QtInstallDir}" -a ! -f "${QtInstallDir}"/include/QtCore ]; then
413                 cd "${QtInstallDir}" && (
414                         mkdir -p include
415                         cd include
416                         for libnm in ${QtLibraries} ; do
417                                 test -d ${libnm} -o -L ${libnm} || \
418                                 ( ln -s ../lib/${libnm}.framework/Headers ${libnm} && echo Link to framework ${libnm} )
419                         done
420                 )
421         fi
422 }
423
424 case ${QtOnlyPackage:-"no"} in
425 y*)
426         build_qt
427         exit 0
428         ;;
429 *)
430         if [ "${configure_qt_frameworks}" != "yes" -a -d "${QtSourceDir}" -a ! \( -d "${QtBuildDir}" -a -d "${QtInstallDir}" \) ]; then
431                 build_qt
432         fi
433         ;;
434 esac
435
436 if [ -d "${LibMagicSourceDir}" -a ! -f "${LibMagicInstallHdr}" ]; then
437         # we have a private libmagic (file(1)) source tree at hand...
438         # so let's build and install it
439         if [ -z "${LibMagicVersion}" ]; then
440                 LibMagicVersion=$(grep AC_INIT "${LibMagicSourceDir}"/configure.ac | cut -d, -f2|tr -d " ()")
441         fi
442
443         LibMagicName="LibMagic"
444         LibMagicBase="${LibMagicName}-${LibMagicVersion}"
445
446         echo Build libmagic library ${LibMagicBase}
447         echo configure options:
448         echo --prefix="${LibMagicInstallDir}" ${LibMagicConfigureOptions}
449
450         mkdir -p "${LibMagicBuildDir}" && cd "${LibMagicBuildDir}"
451
452         # ----------------------------------------
453         # Build LibMagic for different architectures
454         # ----------------------------------------
455         FILE_LIST="${LibMagicLibrary}"
456
457         for arch in ${ARCH_LIST} ; do
458                 CPPFLAGS="${SDKROOT:+-isysroot ${SDKROOT}} -arch ${arch} ${MYCFLAGS}"; export CPPFLAGS
459                 LDFLAGS="${SDKROOT:+-isysroot ${SDKROOT}} -arch ${arch} ${MYCFLAGS}"; export LDFLAGS
460                 "${LibMagicSourceDir}/configure"\
461                         --prefix="${LibMagicInstallDir}"\
462                         ${LibMagicConfigureOptions}
463                 make && make install${strip}
464                 for file in ${FILE_LIST} ; do
465                         if [ -f "${LibMagicInstallDir}"/lib/${file} ]; then
466                                 mv "${LibMagicInstallDir}"/lib/${file}\
467                                         "${LibMagicInstallDir}"/lib/${file}-${arch} 
468                         else
469                                 echo Cannot build and install LibMagic for ${arch}.
470                                 exit 1
471                         fi
472                 done
473         done
474         # -------------------------
475         # Create universal binaries
476         # -------------------------
477         for file in ${FILE_LIST} ; do
478                 OBJ_LIST=
479                 for arch in ${ARCH_LIST} ; do
480                         OBJ_LIST="${OBJ_LIST} lib/${file}-${arch}"
481                 done
482                 (
483                         cd "${LibMagicInstallDir}"
484                         lipo -create ${OBJ_LIST} -o lib/${file}
485                         # check for the "missing link"...
486                         test -f lib/libmagic.dylib || (cd lib ; ln -s "${LibMagicLibrary}" libmagic.dylib)
487                 )
488         done
489         # --------
490         # Clean up
491         # --------
492         for arch in ${ARCH_LIST} ; do
493                 rm -f "${LibMagicInstallDir}"/lib/*-${arch}
494         done
495 fi
496
497 if [ -d "${HunSpellSourceDir}" -a ! -f "${HunSpellInstallHdr}" ]; then
498         # we have a private HunSpell source tree at hand...
499         # so let's build and install it
500         if [ -z "${HunSpellVersion}" ]; then
501                 HunSpellVersion=$(grep AC_INIT "${HunSpellSourceDir}"/configure.ac | cut -d, -f2|tr -d " ()")
502         fi
503
504         HunSpellName="Hunspell"
505         HunSpellBase="${HunSpellName}-${HunSpellVersion}"
506
507         echo Build hunspell library ${HunSpellBase}
508         echo configure options:
509         echo --prefix="${HunSpellInstallDir}" ${HunspellConfigureOptions}
510
511         mkdir -p "${HunSpellBuildDir}" && cd "${HunSpellBuildDir}"
512
513         # ----------------------------------------
514         # Build HunSpell for different architectures
515         # ----------------------------------------
516         FILE_LIST="${HunSpellLibrary}"
517
518         for arch in ${ARCH_LIST} ; do
519                 make distclean
520                 CPPFLAGS="${SDKROOT:+-isysroot ${SDKROOT}} -arch ${arch} ${MYCFLAGS}"; export CPPFLAGS
521                 LDFLAGS="${SDKROOT:+-isysroot ${SDKROOT}} -arch ${arch} ${MYCFLAGS}"; export LDFLAGS
522                 "${HunSpellSourceDir}/configure"\
523                         --prefix="${HunSpellInstallDir}"\
524                         ${HunspellConfigureOptions}
525                 make && make install${strip}
526                 for file in ${FILE_LIST} ; do
527                         if [ -f "${HunSpellInstallDir}"/lib/${file} ]; then
528                                 mv "${HunSpellInstallDir}"/lib/${file}\
529                                         "${HunSpellInstallDir}"/lib/${file}-${arch} 
530                         else
531                                 echo Cannot build and install HunSpell for ${arch}.
532                                 exit 1
533                         fi
534                 done
535         done
536         # -------------------------
537         # Create universal binaries
538         # -------------------------
539         for file in ${FILE_LIST} ; do
540                 OBJ_LIST=
541                 for arch in ${ARCH_LIST} ; do
542                         OBJ_LIST="${OBJ_LIST} lib/${file}-${arch}"
543                 done
544                 (
545                         cd "${HunSpellInstallDir}"
546                         lipo -create ${OBJ_LIST} -o lib/${file}
547                         # check for the "missing link"...
548                         test -f lib/libhunspell.dylib || (cd lib ; ln -s "${HunSpellLibrary}" libhunspell.dylib)
549                 )
550         done
551         # --------
552         # Clean up
553         # --------
554         for arch in ${ARCH_LIST} ; do
555                 rm -f "${HunSpellInstallDir}"/lib/*-${arch}
556         done
557 fi
558
559 if [ -d "${ASpellSourceDir}" -a ! -f "${ASpellInstallHdr}" -a "yes" = "${aspell_deployment}" ]; then
560         # we have a private ASpell source tree at hand...
561         # so let's build and install it
562         if [ -z "${ASpellVersion}" ]; then
563                 ASpellVersion=$(grep AC_INIT "${ASpellSourceDir}"/configure.ac | cut -d, -f2|tr -d " ()")
564         fi
565
566         ASpellName="Aspell"
567         ASpellBase="${ASpellName}-${ASpellVersion}"
568
569         echo Build aspell library ${ASpellBase}
570         echo configure options:
571         echo --prefix="${ASpellInstallDir}" ${AspellConfigureOptions}
572
573         # ASpell builds inplace only :(
574         cd "${ASpellSourceDir}"
575
576         # ----------------------------------------
577         # Build ASpell for different architectures
578         # ----------------------------------------
579         FILE_LIST="${ASpellLibrary}"
580
581         for arch in ${ARCH_LIST} ; do
582                 make distclean
583                 CPPFLAGS="${SDKROOT:+-isysroot ${SDKROOT}} -arch ${arch} ${MYCFLAGS}"; export CPPFLAGS
584                 LDFLAGS="${SDKROOT:+-isysroot ${SDKROOT}} -arch ${arch} ${MYCFLAGS}"; export LDFLAGS
585                 CXXFLAGS=-g "${ASpellSourceDir}/configure"\
586                         --prefix="${ASpellInstallDir}"\
587                         ${AspellConfigureOptions}
588                 make && make install${aspellstrip}
589                 for file in ${FILE_LIST} ; do
590                         if [ -f "${ASpellInstallDir}"/lib/${file} ]; then
591                                 mv "${ASpellInstallDir}"/lib/${file}\
592                                         "${ASpellInstallDir}"/lib/${file}-${arch} 
593                         else
594                                 echo Cannot build and install ASpell for ${arch}.
595                                 exit 1
596                         fi
597                 done
598         done
599         # -------------------------
600         # Create universal binaries
601         # -------------------------
602         for file in ${FILE_LIST} ; do
603                 OBJ_LIST=
604                 for arch in ${ARCH_LIST} ; do
605                         OBJ_LIST="${OBJ_LIST} lib/${file}-${arch}"
606                 done
607                 (
608                         cd "${ASpellInstallDir}"
609                         lipo -create ${OBJ_LIST} -o lib/${file}
610                 )
611         done
612         # --------
613         # Clean up
614         # --------
615         for arch in ${ARCH_LIST} ; do
616                 rm -f "${ASpellInstallDir}"/lib/*-${arch}
617         done
618 fi
619
620
621 framework_name() {
622         echo "Frameworks/${1}.framework"
623 }
624
625 LYX_FILE_LIST="lyx lyxclient tex2lyx"
626 BUNDLE_PATH="Contents/MacOS"
627 LYX_BUNDLE_PATH="${LyxAppPrefix}/${BUNDLE_PATH}"
628 build_lyx() {
629         # Clear Output
630         if [ -n "${LyxAppZip}" -a -f "${LyxAppZip}" ]; then rm "${LyxAppZip}"; fi
631         if [ -d "${LyxAppPrefix}" ]; then rm -rf "${LyxAppPrefix}"; fi
632
633         case "${EnableCXX11}" in
634         "--enable-cxx11")
635                 export CC=cc
636                 export CXX="c++ -stdlib=libc++"
637                 export CXXFLAGS=-std=c++11
638                 ;;
639         esac
640
641         # -------------------------------------
642         # Automate configure check
643         # -------------------------------------
644         if [ ! -f "${LyxSourceDir}"/configure -o "${LyxSourceDir}"/configure -ot "${LyxSourceDir}"/configure.ac ]; then
645                 ( cd "${LyxSourceDir}" && sh autogen.sh )
646         else
647                 find "${LyxSourceDir}" -name Makefile.am -print | while read file ; do
648                         dname=$(dirname "$file")
649                         if [ -f "$dname/Makefile.in" -a "$dname/Makefile.in" -ot "$file" ]; then
650                                 ( cd "${LyxSourceDir}" && sh autogen.sh )
651                                 break
652                         fi
653                 done
654         fi
655         # -------------------------------------
656         # Build LyX for different architectures
657         # -------------------------------------
658
659         if [ -d "${ASpellInstallDir}" -a "yes" = "${aspell_deployment}" ]; then
660                 ConfigureExtraInc="--with-extra-inc=${ASpellInstallDir}/include"
661                 ConfigureExtraLib="--with-extra-lib=${ASpellInstallDir}/lib"
662         fi
663
664         if [ -d "${HunSpellInstallDir}" -a "yes" = "${hunspell_deployment}" ]; then
665                 HunSpellFramework=$(framework_name Hunspell)
666                 HunSpellFramework=$(basename "${HunSpellFramework}")
667                 ConfigureExtraInc="--with-extra-inc=${HunSpellInstallDir}/include"
668                 ConfigureExtraLib="--with-extra-lib=${HunSpellInstallDir}/lib"
669                 # LyXConfigureOptions="${LyXConfigureOptions} --with-hunspell-framework=${HunSpellFramework}"
670         fi
671         LyXConfigureOptions="${LyXConfigureOptions} ${ConfigureExtraInc}"
672         LyXConfigureOptions="${LyXConfigureOptions} ${ConfigureExtraLib}"
673
674         for arch in ${ARCH_LIST} ; do
675
676                 if [ -d "${LyxBuildDir}" ];  then rm -r "${LyxBuildDir}"; fi
677                 mkdir -p "${LyxBuildDir}" && cd "${LyxBuildDir}"
678
679                 CPPFLAGS="${SDKROOT:+-isysroot ${SDKROOT}} -arch ${arch} ${MYCFLAGS}"
680                 LDFLAGS="${SDKROOT:+-isysroot ${SDKROOT}} -arch ${arch} ${MYCFLAGS}"
681
682                 if [ "$configure_qt_frameworks" = "yes" ]; then
683                         export QT_CORE_CFLAGS="-FQtCore"
684                         export QT_CORE_LIBS="-framework QtCore"
685                         export QT_FRONTEND_CFLAGS="-FQtGui"
686                         export QT_FRONTEND_LIBS="-framework QtGui"
687                         CPPFLAGS="${CPPFLAGS} -I${SDKROOT}/Library/Frameworks/QtCore.framework/Headers"
688                         CPPFLAGS="${CPPFLAGS} -I${SDKROOT}/Library/Frameworks/QtGui.framework/Headers"
689                 fi
690
691                 echo LDFLAGS="${LDFLAGS}"
692                 export LDFLAGS
693                 echo CPPFLAGS="${CPPFLAGS}"
694                 export CPPFLAGS
695                 echo CONFIGURE_OPTIONS="${LyXConfigureOptions}" ${QtInstallDir:+"--with-qt-dir=${QtInstallDir}"}
696                 "${LyxSourceDir}/configure"\
697                         --prefix="${LyxAppPrefix}" --with-version-suffix="-${LyXVersionSuffix}"\
698                         ${QtInstallDir:+"--with-qt-dir=${QtInstallDir}"} \
699                         ${LyXConfigureOptions}\
700                         --enable-build-type=rel && \
701                 make ${MAKEJOBS} && make install${strip}
702                 for file in ${LYX_FILE_LIST} ; do
703                         if [ -f "${LYX_BUNDLE_PATH}/${file}" ]; then
704                                 mv "${LYX_BUNDLE_PATH}/${file}"\
705                                         "${LYX_BUNDLE_PATH}/${file}-${arch}" 
706                         else
707                                 echo ERROR: Cannot build and install LyX for ${arch}.
708                                 exit 1
709                         fi
710                 done
711         done
712 }
713
714 content_directory() {
715         target="$1"
716         content=$(dirname "${target}")
717         content=$(dirname "${content}")
718         echo "${content}"
719 }
720
721 installname() {
722                 echo install_name_tool "$@"
723                 install_name_tool "$@"
724 }
725
726 private_framework() {
727         fwdir=$(framework_name "$1")
728         source="$2"
729         target="$3"
730         condir=$(content_directory "${target}")
731         libnm=$(basename "${source}")
732         mkdir -p "${condir}/${fwdir}"
733         if [ ! -f "${condir}/${fwdir}/${libnm}" ]; then
734                 cp -p "${source}" "${condir}/${fwdir}"
735                 installname -id "@executable_path/../${fwdir}/${libnm}" "${condir}/${fwdir}/${libnm}"
736         fi
737         installname -change "${source}" "@executable_path/../${fwdir}/${libnm}" "${target}"
738 }
739
740 deploy_qtlibs() {
741         source="${QtInstallDir}"
742         target="$1"
743         version="Versions/${QtFrameworkVersion}/"
744         condir=$(content_directory "${target}")
745         mkdir -p "${condir}/Resources"
746         test -f "${condir}/Resources/qt.conf" || cat - > "${condir}/Resources/qt.conf" <<-EOF
747 [Paths]
748 Plugins = PlugIns
749 Translations = translations
750 EOF
751         if [ ! -d "${condir}/PlugIns" ]; then
752                 mkdir -p "${condir}/PlugIns"
753                 find "${source}/plugins" -name \*.dylib -print | grep -v _debug.dylib | while read libname ; do
754                         echo Copy plugin "${libname}"
755                         dylib=$(basename "${libname}")
756                         dirname=$(dirname "${libname}")
757                         dirname=$(basename "${dirname}")
758                         mkdir -p "${condir}/PlugIns/${dirname}"
759                         cp -p "${libname}" "${condir}/PlugIns/${dirname}"
760                 done
761         fi
762         for libnm in ${QtLibraries} ; do
763                 fwdir=$(framework_name "$libnm")
764                 dirname=$(dirname "${fwdir}")
765                 mkdir -p "${condir}/${dirname}"
766                 dirname=$(basename "${fwdir}")
767                 test -d "${condir}/${fwdir}" || (
768                         echo Copy framework "${source}/lib/"$(basename "${fwdir}")
769                         cp -pR "${source}/lib/"$(basename "${fwdir}") "${condir}/${fwdir}"
770                         installname -id "@executable_path/../${fwdir}/${version}${libnm}" "${condir}/${fwdir}/${version}${libnm}"
771                         find "${condir}/PlugIns" "${condir}/"$(dirname "${fwdir}") -name Headers -prune -o -type f -print | while read filename ; do
772                                 if [ "${filename}" != "${target}" ]; then
773                                         otool -L "${filename}" 2>/dev/null | sort -u | while read library ; do
774                                                 # pattern match for: /path/to/qt/lib/QtGui.framework/Versions/4/QtGui (compatibility version 4.6.0, current version 4.6.2)
775                                                 case "${library}" in
776                                                 *@rpath/*"${libnm}"*"("*version*")"*)
777                                                         echo rpath based name for ${libnm} is ok.
778                                                         ;;
779                                                 *"${libnm}"*"("*version*")"*)
780                                                         installname -change\
781                                                                 "${source}/lib/${dirname}/${version}${libnm}"\
782                                                                 "@executable_path/../${fwdir}/${version}${libnm}"\
783                                                                 "${filename}"
784                                                         ;;
785                                                 esac
786                                         done
787                                 fi
788                         done
789                 )
790                 installname -change\
791                         "${source}/lib/${dirname}/${version}${libnm}"\
792                         "@executable_path/../${fwdir}/${version}${libnm}"\
793                         "${target}"
794         done
795         if [ -d "${source}"/translations ]; then
796                 if [ ! -d "${condir}/translations" ]; then
797                         mkdir -p "${condir}/translations"
798                 fi
799                 echo Copy Qt translations to "${condir}/translations"
800                 cp -p "${source}"/translations/qt_*.qm "${condir}/translations"
801         fi
802 }
803
804 # -------------------------
805 # Create universal binaries
806 # -------------------------
807 convert_universal() {
808         cd "${LyxAppPrefix}"
809         for file in ${LYX_FILE_LIST} ; do
810                 OBJ_LIST=
811                 for arch in ${ARCH_LIST} ; do
812                         if [ -f "${BUNDLE_PATH}/${file}-${arch}" ]; then
813                                 OBJ_LIST="${OBJ_LIST} ${BUNDLE_PATH}/${file}-${arch}"
814                         fi
815                 done
816                 if [ -n "${OBJ_LIST}" ]; then
817                         lipo -create ${OBJ_LIST} -o "${BUNDLE_PATH}/${file}"
818                 fi
819                 if [ -f "${LibMagicInstallDir}/lib/${LibMagicLibrary}" -a "yes" = "${libmagic_deployment}" ]; then
820                         private_framework LibMagic "${LibMagicInstallDir}/lib/${LibMagicLibrary}" "${LYX_BUNDLE_PATH}/${file}"
821                 fi
822                 if [ -f "${ASpellInstallDir}/lib/${ASpellLibrary}" -a "yes" = "${aspell_deployment}" ]; then
823                         private_framework Aspell "${ASpellInstallDir}/lib/${ASpellLibrary}" "${LYX_BUNDLE_PATH}/${file}"
824                 fi
825                 if [ -f "${HunSpellInstallDir}/lib/${HunSpellLibrary}" -a "yes" = "${hunspell_deployment}" ]; then
826                         private_framework Hunspell "${HunSpellInstallDir}/lib/${HunSpellLibrary}" "${LYX_BUNDLE_PATH}/${file}"
827                 fi
828                 if [ -d "${QtInstallDir}/lib/QtCore.framework/Versions/${QtFrameworkVersion}" -a "yes" = "${qt_deployment}" ]; then
829                         deploy_qtlibs "${LYX_BUNDLE_PATH}/${file}"
830                 fi
831                 otool -L "${BUNDLE_PATH}/${file}" | while read reference ; do
832                         case "${reference}" in
833                         *"${LyxBuildDir}"*"("*")")
834                                 echo ERROR: Bad reference to "${reference}" found!!
835                                 ;;
836                         esac
837                 done
838         done
839         for arch in ${ARCH_LIST} ; do
840                 rm -f ${BUNDLE_PATH}/*-${arch}
841         done
842 }
843
844 deduplicate() {
845         find "$@" -type f -print | while read file ; do
846                 echo $(md5 -q "$file") "$file"
847         done | sort | while read hash file ; do
848                 ppath=$(dirname "$pfile")
849                 path=$(dirname "$file")
850                 if [ "$phash" = "$hash" -a "$ppath" = "$path" ]; then
851                         pname=$(basename "$pfile")
852                         name=$(basename "$file")
853                         cmp -s "$pfile" "$file" && (
854                                 rm "$file"
855                                 cd "$path" && ln -s "$pname" "$name" && echo link for "$file" created
856                         )
857                 fi
858                 phash="$hash"
859                 pfile="$file"
860         done
861 }
862
863 copy_dictionaries() {
864         if [ -d "${ASpellInstallDir}" -a "yes" = "${aspell_dictionaries}" ]; then
865                 ASpellResources="${LyxAppPrefix}/Contents/Resources"
866                 # try to reuse macports dictionaries for now
867                 if [ -d /opt/local/lib/aspell-0.60 ]; then ASpellInstallDir=/opt/local ; fi
868                 mkdir -p "${ASpellResources}"
869                 echo Copy Aspell dictionaries from "${ASpellInstallDir}"
870                 mkdir -p "${ASpellResources}"/data "${ASpellResources}"/dicts
871                 cp -p -r "${ASpellInstallDir}/lib/aspell-0.60"/* "${ASpellResources}"/data
872                 cp -p -r "${ASpellInstallDir}/share/aspell"/* "${ASpellResources}"/dicts
873         fi
874         if [ -d "${HunSpellInstallDir}" -a "yes" = "${hunspell_dictionaries}" ]; then
875                 HunSpellResources="${LyxAppPrefix}/Contents/Resources"
876                 if [ -d "${DictionarySourceDir}" ]; then
877                         ( cd "${DictionarySourceDir}" && find dicts -name .svn -prune -o -type f -print | cpio -pmdv "${HunSpellResources}" )
878                         deduplicate "${HunSpellResources}"/dicts
879                 fi
880         fi
881         if [ -d "${DictionarySourceDir}" -a "yes" = "${thesaurus_deployment}" ]; then
882                 MyThesResources="${LyxAppPrefix}/Contents/Resources"
883                 ( cd "${DictionarySourceDir}" && find thes -name .svn -prune -o -type f -print | cpio -pmdv "${MyThesResources}" )
884                 deduplicate "${MyThesResources}"/thes
885         fi
886 }
887
888 set_bundle_display_options() {
889         X_BOUNDS=$2
890         Y_BOUNDS=$3
891         Y_POSITION=$((Y_BOUNDS - 65))
892         Y_BOUNDS=$((Y_BOUNDS + 20))
893         LYX_X_POSITION=$((X_BOUNDS / 4))
894         LYX_Y_POSITION=$Y_POSITION
895         APP_X_POSITION=$((3 * X_BOUNDS / 4))
896         APP_Y_POSITION=$Y_POSITION
897         WITH_DOCUMENTS=$(test -d "${1}/Documents" && echo true || echo false)
898         osascript <<-EOF
899         tell application "Finder"
900         set f to POSIX file ("${1}" as string) as alias
901         tell folder f
902             open
903             tell container window
904                 set toolbar visible to false
905                 set statusbar visible to false
906                 set current view to icon view
907                 delay 1 -- sync
908                 set the bounds to {20, 50, $X_BOUNDS, $Y_BOUNDS}
909             end tell
910             delay 1 -- sync
911             set icon size of the icon view options of container window to 64
912             set arrangement of the icon view options of container window to not arranged
913             if ${WITH_DOCUMENTS} then
914                set position of item "Documents" to {$LYX_X_POSITION,0}
915             end if
916             set position of item "${LyxName}.app" to {$LYX_X_POSITION,$LYX_Y_POSITION}
917             set position of item "Applications" to {$APP_X_POSITION,$APP_Y_POSITION}
918             set background picture of the icon view options\
919                of container window to file "background.png" of folder "Pictures"
920             set the bounds of the container window to {0, 0, $X_BOUNDS, $Y_BOUNDS}
921             update without registering applications
922             delay 5 -- sync
923             close
924         end tell
925         delay 5 -- sync
926     end tell
927 EOF
928 }
929
930 make_dmg() {
931         cd "${1}"
932
933         BGSIZE=$(file "$DmgBackground" | awk -F , '/PNG/{print $2 }' | tr x ' ')
934         BG_W=$(echo ${BGSIZE} | awk '{print $1 }')
935         BG_H=$(echo ${BGSIZE} | awk '{print $2 }')
936
937         rm -f "${DMGNAME}.sparseimage" "${DMGNAME}.dmg"
938
939         hdiutil create -type SPARSE -size ${DMGSIZE:-"250m"} -fs HFS+ -volname "${LyxBase}" "${DMGNAME}"
940         # Unmount currently mounted disk image
941         mount | grep "${LyxBase}" && umount /Volumes/"${LyxBase}"
942         test -d /Volumes/"${LyxBase}" && rmdir /Volumes/"${LyxBase}"
943
944         # Mount the disk image
945         hdiutil attach "${DMGNAME}.sparseimage"
946
947         # Obtain device information
948         DEVS=$(hdiutil attach "${DMGNAME}.sparseimage" | cut -f 1)
949         DEV=$(echo $DEVS | cut -f 1 -d ' ')
950         VOLUME=$(mount |grep ${DEV} | cut -f 3 -d ' ')
951
952         # copy in the application bundle
953         cp -Rp "${LyxAppDir}.app" "${VOLUME}/${LyxName}.app"
954
955         # copy in background image
956         mkdir -p "${VOLUME}/Pictures"
957         cp "${DmgBackground}" "${VOLUME}/Pictures/background.png"
958         # symlink applications
959         ln -s /Applications/ "${VOLUME}"/Applications
960         test -d "${DocumentationDir}" && cp -r "${DocumentationDir}" "${VOLUME}"
961         set_bundle_display_options "${VOLUME}" ${BG_W} ${BG_H}
962         ${XCODE_DEVELOPER}/Tools/SetFile -a C "${VOLUME}"
963         mv "${VOLUME}/Pictures" "${VOLUME}/.Pictures"
964
965         # Unmount the disk image
966         hdiutil detach ${DEV}
967
968         # Convert the disk image to read-only
969         hdiutil convert "${DMGNAME}.sparseimage" -format UDBZ -o "${DMGNAME}.dmg"
970         rm -f "${DMGNAME}.sparseimage"
971 }
972
973 # ------------------------------
974 # Building distribution packages
975 # ------------------------------
976
977 build_package() {
978         test -n "${LyxAppZip}" && (
979                 cd "${LyxAppPrefix}" && zip -r "${LyxAppZip}" .
980         )
981
982         DMGARCH=""
983         for arch in ${ARCH_LIST} ; do
984                 DMGARCH="${DMGARCH}-${arch}"
985         done
986         QtDmgArchSuffix=${QtMajorVersion}${DMGARCH}${QtAPI}.dmg
987
988         test -n "${DMGLocation}" && (
989                 make_dmg "${DMGLocation}"
990                 if [ -d "${QtInstallDir}/lib/QtCore.framework/Versions/${QtFrameworkVersion}" -a "yes" = "${qt_deployment}" ]; then
991                         rm -f "${DMGLocation}/${DMGNAME}+${QtDmgArchSuffix}"
992                         echo move to "${DMGLocation}/${DMGNAME}+${QtDmgArchSuffix}"
993                         mv "${DMGLocation}/${DMGNAME}.dmg" "${DMGLocation}/${DMGNAME}+${QtDmgArchSuffix}"
994                 fi
995         )
996 }
997
998 # ------------------------------
999 # main block
1000 # ------------------------------
1001
1002 if [ ${LyxOnlyPackage:-"no"} = "no" ]; then
1003         build_lyx
1004         convert_universal
1005         copy_dictionaries
1006 fi
1007 build_package