]> git.lyx.org Git - lyx.git/blob - development/LyX-Mac-binary-release.sh
This is a dummy commit for posting the real changelog for the the last
[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 # modified by Stephan Witt
8 # Last modified: 17 April 2010
9
10 # Prerequisite:
11 # * a decent checkout of LyX sources (probably you have it already)
12 # * Qt4 - build with shared or static libraries for the used platforms (i386 and ppc)
13 # * for aspell support:
14 #   the aspell sources placed in a sibling directory (variable ASpellSourceVersion)
15
16 ConfigureOptions="--enable-warnings --enable-optimization=-Os --with-included-gettext"
17 dict_deployment="yes"
18 qt4_deployment="yes"
19 MACOSX_DEPLOYMENT_TARGET="10.4" # Tiger support is default
20
21 usage() {
22         echo Build script for LyX on Mac OS X
23         echo
24         echo Optional arguments:
25         echo " --tiger-support=yes|no ....." default yes
26         echo " --dict-deployment=yes|no ..." default yes
27         echo " --qt4-deployment=yes|no ...." default yes
28         echo " --with-arch=ARCH ..........." default ppc,i386
29         echo " --with-build-path=PATH ....." default \${lyx-src-dir}/../lyx-build
30         echo " --with-dmg-location=PATH ..." default \${build-path}
31         echo
32         echo "All other arguments with -- are passed to configure"
33         echo "including the defaults: ${ConfigureOptions}"
34         echo
35         exit 0
36 }
37
38 while [ $# -gt 0 ]; do
39         case "${1}" in
40         --with-qt4-dir=*)
41                 QTDIR=`echo ${1}|cut -d= -f2`
42                 shift
43                 ;;
44         --tiger-support=[Nn][Oo])
45                 MACOSX_DEPLOYMENT_TARGET=""
46                 MYCFLAGS=""
47                 shift
48                 ;;
49         --dict-deployment=*)
50                 dict_deployment=`echo ${1}|cut -d= -f2`
51                 shift
52                 ;;
53         --qt4-deployment=*)
54                 qt4_deployment=`echo ${1}|cut -d= -f2`
55                 shift
56                 ;;
57         --with-arch=*)
58                 ARCH=`echo ${1}|cut -d= -f2|tr ',' ' '`
59                 ARCH_LIST="${ARCH_LIST} ${ARCH}"
60                 shift
61                 ;;
62         --with-dmg-location=*)
63                 DMGLocation=`echo ${1}|cut -d= -f2`
64                 shift
65                 ;;
66         --with-build-path=*)
67                 LyxBuildDir=`echo ${1}|cut -d= -f2`
68                 shift
69                 ;;
70         --help)
71                 usage
72                 ;;
73         --*)
74                 ConfigureOptions="${ConfigureOptions} ${1}"
75                 shift
76                 ;;
77         *)
78                 break
79                 ;;
80         esac
81 done
82
83 # Set these variables -- to
84 # (1) the location of your Qt4 installation
85 # (2) the location of resulting DMG
86 # (3) the version of private aspell installation
87 #     (to define the location assign ASpellSourceDir instead)
88 # (4) the list of architectures to build for
89
90 QtInstallDir=${QTDIR:-"/opt/qt4"}
91 QtFrameworkVersion="4"
92 ASpellSourceVersion="aspell-0.60.6"
93 ARCH_LIST=${ARCH_LIST:-"ppc i386"}
94
95 strip="-strip"
96
97 # detection of script home
98 LyxSourceDir=${1:-`dirname "$0"`}
99 if [ ! -d "${LyxSourceDir}" ]; then
100         echo Missing LyX source directory.
101         exit 2
102 fi
103 case "${LyxSourceDir}" in
104 /*/development)
105         LyxSourceDir=`dirname "${LyxSourceDir}"`
106         ;;
107 /*)
108         ;;
109 */development|development)
110         LyxSourceDir=`dirname "${LyxSourceDir}"`
111         LyxSourceDir=`cd "${LyxSourceDir}";pwd`
112         ;;
113 *)
114         LyxSourceDir=`cd "${LyxSourceDir}";pwd`
115         ;;
116 esac
117
118 LyxBuildDir=${LyxBuildDir:-`dirname "${LyxSourceDir}"`/lyx-build}
119 DMGLocation=${DMGLocation:-"${LyxBuildDir}"}
120
121 ASpellSourceDir=${ASPELLDIR:-`dirname "${LyxSourceDir}"`/${ASpellSourceVersion}}
122 ASpellInstallDir=${ASpellInstallDir:-"${LyxBuildDir}"/${ASpellSourceVersion}.lib}
123
124 if [ ! -f "${LyxSourceDir}"/configure ]; then
125         ( cd "${LyxSourceDir}" && sh autogen.sh )
126 fi
127 if [ -z "${LyXVersion}" ]; then
128         LyXVersion=`grep AC_INIT "${LyxSourceDir}"/configure.ac | cut -d, -f2 | tr -d " ()"`
129 fi
130
131 LyxName="LyX"
132 LyxBase="${LyxName}-${LyXVersion}"
133 LyxApp="${LyxBase}.app"
134 LyxAppDir="${LyxBuildDir}"/"${LyxBase}"
135 LyxBuildDir="${LyxAppDir}.build"
136 LyxAppPrefix="${LyxAppDir}.app"
137 # if zip file is needed... remove the comment sign
138 #LyxAppZip="${LyxAppPrefix}.zip"
139
140 BuildSystem=`"${LyxSourceDir}/config/config.guess"`
141
142 # ---------------------------------
143 # DON'T MODIFY ANYTHING BELOW HERE!
144 # ---------------------------------
145
146 # These variables define the identifiers of the
147 # system (both Intel and PowerPC) to compile for.
148 # (Note: darwin8 is 10.4; darwin9 is 10.5.)
149 # Only change these if necessary
150
151 HostSystem_i386="i686-apple-darwin8"
152 HostSystem_ppc="powerpc-apple-darwin8"
153
154 DMGNAME="${LyxBase}-Uncompressed.dmg"
155 DMGSIZE="550m"
156 COMPRESSEDDMGNAME="${LyxBase}.dmg"
157 BACKGROUND="${LyxAppDir}.app/Contents/Resources/images/banner.png"
158
159 # Check for existing SDKs
160 SDKs=`echo /Developer/SDKs/MacOSX10*sdk`
161 case "$SDKs" in
162 *10.6*)
163         MACOSX_DEPLOYMENT_TARGET=${MACOSX_DEPLOYMENT_TARGET:-"10.5"}; export MACOSX_DEPLOYMENT_TARGET
164         case "${MACOSX_DEPLOYMENT_TARGET}" in
165         10.5)
166                 SDKROOT="/Developer/SDKs/MacOSX10.5.sdk"; export SDKROOT
167                 ;;
168         10.4)
169                 SDKROOT="/Developer/SDKs/MacOSX10.4u.sdk"; export SDKROOT
170                 CC=gcc-4.0 ; export CC
171                 CXX=g++-4.0 ; export CXX
172                 OBJC=gcc-4.0 ; export OBJC
173                 ;;
174         esac
175         ;;
176 *10.5*)
177         MACOSX_DEPLOYMENT_TARGET="10.4"; export MACOSX_DEPLOYMENT_TARGET
178         SDKROOT="/Developer/SDKs/MacOSX10.4u.sdk"; export SDKROOT
179         ;;
180 *)
181         echo Unknown or missing SDK for Mac OS X.
182         exit 1
183         ;;
184 esac
185 MYCFLAGS="-mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET}"
186
187 if [ -d "${ASpellSourceDir}" -a ! -d "${ASpellInstallDir}" ]; then
188         # we have a private ASpell source tree at hand...
189         # so let's build and install it
190         if [ -z "${ASpellVersion}" ]; then
191                 ASpellVersion=`grep AC_INIT "${ASpellSourceDir}"/configure.ac | cut -d, -f2|tr -d " ()"`
192         fi
193
194         ASpellName="Aspell"
195         ASpellBase="${ASpellName}-${ASpellVersion}"
196
197         echo Build aspell library ${ASpellBase}
198
199         # Clear Output
200         if [ -n "${ASpellLibZip}" -a -f "${ASpellLibZip}" ]; then rm "${ASpellLibZip}"; fi
201         if [ -d "${ASpellInstallDir}" ]; then rm -r "${ASpellInstallDir}"; fi
202
203         # ASpell builds inplace only :(
204         cd "${ASpellSourceDir}" && make distclean
205
206         # ----------------------------------------
207         # Build ASpell for different architectures
208         # ----------------------------------------
209         FILE_LIST="libaspell.15.dylib libpspell.15.dylib"
210
211         for arch in ${ARCH_LIST} ; do
212                 CPPFLAGS="${SDKROOT:+-isysroot ${SDKROOT}} -arch ${arch} ${MYCFLAGS}"; export CPPFLAGS
213                 LDFLAGS="${SDKROOT:+-isysroot ${SDKROOT}} -arch ${arch}"; export LDFLAGS
214                 HOSTSYSTEM=`eval "echo \\$HostSystem_$arch"`
215                 "${ASpellSourceDir}/configure"\
216                         --prefix="${ASpellInstallDir}"\
217                         ${ConfigureOptions}\
218                         --host="${HOSTSYSTEM}" ${BuildSystem:+"--build=${BuildSystem}"} --enable-build-type=rel
219                 make && make install${strip}
220                 for file in ${FILE_LIST} ; do
221                         if [ -f "${ASpellInstallDir}"/lib/${file} ]; then
222                                 mv "${ASpellInstallDir}"/lib/${file}\
223                                         "${ASpellInstallDir}"/lib/${file}-${arch} 
224                         else
225                                 echo Cannot build and install ASpell for ${arch}.
226                                 exit 1
227                         fi
228                 done
229                 make distclean
230         done
231         # -------------------------
232         # Create universal binaries
233         # -------------------------
234         for file in ${FILE_LIST} ; do
235                 OBJ_LIST=
236                 for arch in ${ARCH_LIST} ; do
237                         OBJ_LIST="${OBJ_LIST} lib/${file}-${arch}"
238                 done
239                 (
240                         cd "${ASpellInstallDir}"
241                         lipo -create ${OBJ_LIST} -o lib/${file}
242                 )
243         done
244         # --------
245         # Clean up
246         # --------
247         for arch in ${ARCH_LIST} ; do
248                 rm -f "${ASpellInstallDir}"/lib/*-${arch}
249         done
250 fi
251
252 framework_name() {
253         echo "Frameworks/${1}.framework"
254 }
255
256 FILE_LIST="lyx lyxclient tex2lyx"
257 BUNDLE_PATH="Contents/MacOS"
258 LYX_BUNDLE_PATH="${LyxAppPrefix}/${BUNDLE_PATH}"
259 build_lyx() {
260         # Clear Output
261         if [ -n "${LyxAppZip}" -a -f "${LyxAppZip}" ]; then rm "${LyxAppZip}"; fi
262         if [ -d "${LyxAppPrefix}" ]; then rm -rf "${LyxAppPrefix}"; fi
263
264         # -------------------------------------
265         # Build LyX for different architectures
266         # -------------------------------------
267
268         if [ -d "${ASpellInstallDir}" ]; then
269                 ASpellFramework=`framework_name Aspell`
270                 ASpellFramework=`basename "${ASpellFramework}"`
271                 ConfigureOptions="${ConfigureOptions} --with-extra-inc=${ASpellInstallDir}/include"
272                 ConfigureOptions="${ConfigureOptions} --with-extra-lib=${ASpellInstallDir}/lib"
273                 ConfigureOptions="${ConfigureOptions} --with-aspell-framework=${ASpellFramework}"
274         fi
275
276         for arch in ${ARCH_LIST} ; do
277
278                 if [ -d "${LyxBuildDir}" ];  then rm -r "${LyxBuildDir}"; fi
279                 mkdir "${LyxBuildDir}" && cd "${LyxBuildDir}"
280
281                 CPPFLAGS="${SDKROOT:+-isysroot ${SDKROOT}} -arch ${arch} ${MYCFLAGS}"; export CPPFLAGS
282                 LDFLAGS="${SDKROOT:+-isysroot ${SDKROOT}} -arch ${arch}"; export LDFLAGS
283                 HOSTSYSTEM=`eval "echo \\$HostSystem_$arch"`
284
285                 echo LDFLAGS="${LDFLAGS}"
286                 echo CPPFLAGS="${CPPFLAGS}"
287                 echo CONFIGURE_OPTIONS="${ConfigureOptions}"
288                 "${LyxSourceDir}/configure"\
289                         --prefix="${LyxAppPrefix}" --with-version-suffix="-${LyXVersion}"\
290                         ${QtInstallDir:+"--with-qt4-dir=${QtInstallDir}"} \
291                         ${ConfigureOptions}\
292                         --host="${HOSTSYSTEM}" --build="${BuildSystem}" --enable-build-type=rel
293                 make && make install${strip}
294                 for file in ${FILE_LIST} ; do
295                         if [ -f "${LYX_BUNDLE_PATH}/${file}" ]; then
296                                 mv "${LYX_BUNDLE_PATH}/${file}"\
297                                         "${LYX_BUNDLE_PATH}/${file}-${arch}" 
298                         else
299                                 echo ERROR: Cannot build and install LyX for ${arch}.
300                                 exit 1
301                         fi
302                 done
303         done
304 }
305
306 content_directory() {
307         target="$1"
308         content=`dirname "${target}"`
309         content=`dirname "${content}"`
310         echo "${content}"
311 }
312
313 private_framework() {
314         fwdir=`framework_name "$1"`
315         source="$2"
316         target="$3"
317         condir=`content_directory "${target}"`
318         libnm=`basename "${source}"`
319         mkdir -p "${condir}/${fwdir}"
320         if [ ! -f "${condir}/${fwdir}/${libnm}" ]; then
321                 cp -p "${source}" "${condir}/${fwdir}"
322                 echo Set library id in "${condir}/${fwdir}/${libnm}"
323                 install_name_tool -id "@executable_path/../${fwdir}/${libnm}" "${condir}/${fwdir}/${libnm}"
324         fi
325         echo Correct library id reference to "${libnm}" in "${target}"
326         install_name_tool -change "${source}" "@executable_path/../${fwdir}/${libnm}" "${target}"
327 }
328
329 deploy_qtlibs() {
330         source="${QtInstallDir}"
331         target="$1"
332         version="Versions/${QtFrameworkVersion}/"
333         condir=`content_directory "${target}"`
334         mkdir -p "${condir}/Resources"
335         test -f "${condir}/Resources/qt.conf" || cat - > "${condir}/Resources/qt.conf" <<-EOF
336 [Paths]
337 Plugins = PlugIns
338 EOF
339         if [ ! -d "${condir}/PlugIns" ]; then
340                 mkdir -p "${condir}/PlugIns"
341                 find "${source}/plugins" -name \*.dylib -print | while read libname ; do
342                         echo Copy plugin "${libname}"
343                         dylib=`basename "${libname}"`
344                         dirname=`dirname "${libname}"`
345                         dirname=`basename "${dirname}"`
346                         mkdir -p "${condir}/PlugIns/${dirname}"
347                         cp -p "${libname}" "${condir}/PlugIns/${dirname}"
348                 done
349         fi
350         # don't change order here...
351         for libnm in QtSvg QtXml QtGui QtNetwork QtCore ; do
352                 fwdir=`framework_name "$libnm"`
353                 dirname=`basename "${fwdir}"`
354                 test -d "${condir}/${fwdir}" || (
355                         echo Copy framework "${source}/lib/"`basename "${fwdir}"`
356                         cp -pR "${source}/lib/"`basename "${fwdir}"` "${condir}/${fwdir}"
357                         echo Set library id in "${condir}/${fwdir}/${version}${libnm}"
358                         install_name_tool -id "@executable_path/../${fwdir}/${version}${libnm}" "${condir}/${fwdir}/${version}${libnm}"
359                         find "${condir}/PlugIns" "${condir}/"`dirname "${fwdir}"` -name Headers -prune -o -type f -print | while read filename ; do
360                                 otool -L "${filename}" 2>/dev/null | while read library ; do
361                                         # pattern match for: /path/to/qt4/lib/QtGui.framework/Versions/4/QtGui (compatibility version 4.6.0, current version 4.6.2)
362                                         case "${library}" in
363                                         *"${libnm}"*"("*")"*)
364                                                 echo Correct library id reference to "${libnm}" in "${filename}"
365                                                 install_name_tool -change\
366                                                         "${source}/lib/${dirname}/${version}${libnm}"\
367                                                         "@executable_path/../${fwdir}/${version}${libnm}"\
368                                                         "${filename}"
369                                                 ;;
370                                         esac
371                                 done
372                         done
373                 )
374                 echo Correct library id reference to "${libnm}" in "${target}"
375                 install_name_tool -change\
376                         "${source}/lib/${dirname}/${version}${libnm}"\
377                         "@executable_path/../${fwdir}/${version}${libnm}"\
378                         "${target}"
379         done
380 }
381
382 # -------------------------
383 # Create universal binaries
384 # -------------------------
385 convert_universal() {
386         cd "${LyxAppPrefix}"
387         for file in ${FILE_LIST} ; do
388                 OBJ_LIST=
389                 for arch in ${ARCH_LIST} ; do
390                         if [ -f "${BUNDLE_PATH}/${file}-${arch}" ]; then
391                                 OBJ_LIST="${OBJ_LIST} ${BUNDLE_PATH}/${file}-${arch}"
392                         fi
393                 done
394                 if [ -n "${OBJ_LIST}" ]; then
395                         lipo -create ${OBJ_LIST} -o "${BUNDLE_PATH}/${file}"
396                 fi
397                 if [ -d "${ASpellInstallDir}" ]; then
398                         private_framework Aspell "${ASpellInstallDir}/lib/libaspell.15.dylib" "${LYX_BUNDLE_PATH}/${file}"
399                 fi
400                 if [ -d "${QtInstallDir}/lib/QtCore.framework/Versions/${QtFrameworkVersion}" -a "yes" = "${qt4_deployment}" ]; then
401                         deploy_qtlibs "${LYX_BUNDLE_PATH}/${file}"
402                 fi
403                 otool -L "${BUNDLE_PATH}/${file}" | while read reference ; do
404                         case "${reference}" in
405                         *"${LyxBuildDir}"*"("*")")
406                                 echo ERROR: Bad reference to "${reference}" found!!
407                                 ;;
408                         esac
409                 done
410         done
411         for arch in ${ARCH_LIST} ; do
412                 rm -f ${BUNDLE_PATH}/*-${arch}
413         done
414 }
415
416 copy_dictionaries() {
417         if [ -d "${ASpellInstallDir}" -a "yes" = "${dict_deployment}" ]; then
418                 ASpellFramework=`framework_name Aspell`
419                 ASpellResources="${LyxAppPrefix}/Contents/${ASpellFramework}/Resources"
420                 # try to reuse macports dictionaries for now
421                 if [ -d /opt/local/lib/aspell-0.60 ]; then ASpellInstallDir=/opt/local ; fi
422                 mkdir -p "${ASpellResources}"
423                 echo Copy Aspell dictionaries from "${ASpellInstallDir}"
424                 cp -p -r "${ASpellInstallDir}/lib/aspell-0.60" "${ASpellResources}"/data
425                 cp -p -r "${ASpellInstallDir}/share/aspell" "${ASpellResources}"/dict
426         fi
427 }
428
429 function set_bundle_display_options() {
430         osascript <<-EOF
431     tell application "Finder"
432         set f to POSIX file ("${1}" as string) as alias
433         tell folder f
434             open
435             tell container window
436                 set toolbar visible to false
437                 set statusbar visible to false
438                 set current view to icon view
439                 delay 1 -- sync
440                 set the bounds to {20, 50, $2, $3}
441             end tell
442             delay 1 -- sync
443             set icon size of the icon view options of container window to 64
444             set arrangement of the icon view options of container window to not arranged
445             set position of item "${LyxName}.app" to {100,$4}
446             set position of item "Applications" to {280,$4}
447             set background picture of the icon view options\
448                                         of container window to file "background.png" of folder "Pictures"
449             set the bounds of the container window to {0, 0, $2, $3}
450             update without registering applications
451             delay 5 -- sync
452             close
453         end tell
454         delay 5 -- sync
455     end tell
456 EOF
457 }
458
459 function make_dmg() {
460         cd "${1}"
461
462         BGSIZE=`file "$BACKGROUND" | awk -F , '/PNG/{print $2 }' | tr x ' '`
463         BG_W=`echo ${BGSIZE} | awk '{print $1 }'`
464         BG_H=`echo ${BGSIZE} | awk '{h = $2 + 20 ;print h }'`
465         BG_Y=`echo ${BGSIZE} | awk '{y = $2 - 60 ;print y }'`
466
467         rm -f ${DMGNAME}
468         rm -f ${COMPRESSEDDMGNAME}
469
470         hdiutil create -type SPARSE -size ${DMGSIZE:-"250m"} -fs HFS+ -volname "${LyxBase}" "${DMGNAME}"
471         # Unmount currently mounted disk image
472         test -d /Volumes/"${LyxBase}" && umount /Volumes/"${LyxBase}"
473
474         # Mount the disk image
475         hdiutil attach ${DMGNAME}.sparseimage
476
477         # Obtain device information
478         DEVS=$(hdiutil attach ${DMGNAME}.sparseimage | cut -f 1)
479         DEV=$(echo $DEVS | cut -f 1 -d ' ')
480         VOLUME=$(mount |grep ${DEV} | cut -f 3 -d ' ')
481
482         # copy in the application bundle
483         cp -Rp ${LyxAppDir}.app ${VOLUME}/${LyxName}.app
484
485         # copy in background image
486         mkdir -p ${VOLUME}/Pictures
487         cp ${BACKGROUND} ${VOLUME}/Pictures/background.png
488         # symlink applications
489         ln -s /Applications/ ${VOLUME}/Applications
490         set_bundle_display_options ${VOLUME} ${BG_W} ${BG_H} ${BG_Y}
491         mv ${VOLUME}/Pictures ${VOLUME}/.Pictures
492
493         # Unmount the disk image
494         hdiutil detach ${DEV}
495
496         # Convert the disk image to read-only
497         hdiutil convert ${DMGNAME}.sparseimage -format UDBZ -o ${COMPRESSEDDMGNAME}
498         rm -f ${DMGNAME}.sparseimage
499 }
500
501 build_lyx
502 convert_universal
503 copy_dictionaries
504
505 # ------------------------------
506 # Building distribution packages
507 # ------------------------------
508
509 test -n "${LyxAppZip}" && (
510         cd "${LyxAppPrefix}" && zip -r "${LyxAppZip}" .
511 )
512
513 test -n "${DMGLocation}" && make_dmg "${DMGLocation}"