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