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