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
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)
16 ConfigureOptions="--enable-warnings --enable-optimization=-Os --with-included-gettext"
19 MACOSX_DEPLOYMENT_TARGET="10.4" # Tiger support is default
22 echo Build script for LyX on Mac OS X
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}
32 echo "All other arguments with -- are passed to configure"
33 echo "including the defaults: ${ConfigureOptions}"
38 while [ $# -gt 0 ]; do
41 QTDIR=`echo ${1}|cut -d= -f2`
44 --tiger-support=[Nn][Oo])
45 MACOSX_DEPLOYMENT_TARGET=""
50 dict_deployment=`echo ${1}|cut -d= -f2`
54 qt4_deployment=`echo ${1}|cut -d= -f2`
58 ARCH=`echo ${1}|cut -d= -f2|tr ',' ' '`
59 ARCH_LIST="${ARCH_LIST} ${ARCH}"
62 --with-dmg-location=*)
63 DMGLocation=`echo ${1}|cut -d= -f2`
67 LyxBuildDir=`echo ${1}|cut -d= -f2`
74 ConfigureOptions="${ConfigureOptions} ${1}"
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
90 QtInstallDir=${QTDIR:-"/opt/qt4"}
91 QtFrameworkVersion="4"
92 ASpellSourceVersion="aspell-0.60.6"
93 ARCH_LIST=${ARCH_LIST:-"ppc i386"}
97 # detection of script home
98 LyxSourceDir=${1:-`dirname "$0"`}
99 if [ ! -d "${LyxSourceDir}" ]; then
100 echo Missing LyX source directory.
103 case "${LyxSourceDir}" in
105 LyxSourceDir=`dirname "${LyxSourceDir}"`
109 */development|development)
110 LyxSourceDir=`dirname "${LyxSourceDir}"`
111 LyxSourceDir=`cd "${LyxSourceDir}";pwd`
114 LyxSourceDir=`cd "${LyxSourceDir}";pwd`
118 LyxBuildDir=${LyxBuildDir:-`dirname "${LyxSourceDir}"`/lyx-build}
119 DMGLocation=${DMGLocation:-"${LyxBuildDir}"}
121 ASpellSourceDir=${ASPELLDIR:-`dirname "${LyxSourceDir}"`/${ASpellSourceVersion}}
122 ASpellInstallDir=${ASpellInstallDir:-"${LyxBuildDir}"/${ASpellSourceVersion}.lib}
124 if [ ! -f "${LyxSourceDir}"/configure ]; then
125 ( cd "${LyxSourceDir}" && sh autogen.sh )
127 if [ -z "${LyXVersion}" ]; then
128 LyXVersion=`grep AC_INIT "${LyxSourceDir}"/configure.ac | cut -d, -f2 | tr -d " ()"`
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"
140 BuildSystem=`"${LyxSourceDir}/config/config.guess"`
142 # ---------------------------------
143 # DON'T MODIFY ANYTHING BELOW HERE!
144 # ---------------------------------
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
151 HostSystem_i386="i686-apple-darwin8"
152 HostSystem_ppc="powerpc-apple-darwin8"
154 DMGNAME="${LyxBase}-Uncompressed.dmg"
156 COMPRESSEDDMGNAME="${LyxBase}.dmg"
157 BACKGROUND="${LyxAppDir}.app/Contents/Resources/images/banner.png"
159 # Check for existing SDKs
160 SDKs=`echo /Developer/SDKs/MacOSX10*sdk`
163 MACOSX_DEPLOYMENT_TARGET=${MACOSX_DEPLOYMENT_TARGET:-"10.5"}; export MACOSX_DEPLOYMENT_TARGET
164 case "${MACOSX_DEPLOYMENT_TARGET}" in
166 SDKROOT="/Developer/SDKs/MacOSX10.5.sdk"; export SDKROOT
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
177 MACOSX_DEPLOYMENT_TARGET="10.4"; export MACOSX_DEPLOYMENT_TARGET
178 SDKROOT="/Developer/SDKs/MacOSX10.4u.sdk"; export SDKROOT
181 echo Unknown or missing SDK for Mac OS X.
185 MYCFLAGS="-mmacosx-version-min=${MACOSX_DEPLOYMENT_TARGET}"
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 " ()"`
195 ASpellBase="${ASpellName}-${ASpellVersion}"
197 echo Build aspell library ${ASpellBase}
200 if [ -n "${ASpellLibZip}" -a -f "${ASpellLibZip}" ]; then rm "${ASpellLibZip}"; fi
201 if [ -d "${ASpellInstallDir}" ]; then rm -r "${ASpellInstallDir}"; fi
203 # ASpell builds inplace only :(
204 cd "${ASpellSourceDir}" && make distclean
206 # ----------------------------------------
207 # Build ASpell for different architectures
208 # ----------------------------------------
209 FILE_LIST="libaspell.15.dylib libpspell.15.dylib"
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}"\
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}
225 echo Cannot build and install ASpell for ${arch}.
231 # -------------------------
232 # Create universal binaries
233 # -------------------------
234 for file in ${FILE_LIST} ; do
236 for arch in ${ARCH_LIST} ; do
237 OBJ_LIST="${OBJ_LIST} lib/${file}-${arch}"
240 cd "${ASpellInstallDir}"
241 lipo -create ${OBJ_LIST} -o lib/${file}
247 for arch in ${ARCH_LIST} ; do
248 rm -f "${ASpellInstallDir}"/lib/*-${arch}
253 echo "Frameworks/${1}.framework"
256 FILE_LIST="lyx lyxclient tex2lyx"
257 BUNDLE_PATH="Contents/MacOS"
258 LYX_BUNDLE_PATH="${LyxAppPrefix}/${BUNDLE_PATH}"
261 if [ -n "${LyxAppZip}" -a -f "${LyxAppZip}" ]; then rm "${LyxAppZip}"; fi
262 if [ -d "${LyxAppPrefix}" ]; then rm -rf "${LyxAppPrefix}"; fi
264 # -------------------------------------
265 # Build LyX for different architectures
266 # -------------------------------------
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}"
276 for arch in ${ARCH_LIST} ; do
278 if [ -d "${LyxBuildDir}" ]; then rm -r "${LyxBuildDir}"; fi
279 mkdir "${LyxBuildDir}" && cd "${LyxBuildDir}"
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"`
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}"} \
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}"
299 echo ERROR: Cannot build and install LyX for ${arch}.
306 content_directory() {
308 content=`dirname "${target}"`
309 content=`dirname "${content}"`
313 private_framework() {
314 fwdir=`framework_name "$1"`
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}"
325 echo Correct library id reference to "${libnm}" in "${target}"
326 install_name_tool -change "${source}" "@executable_path/../${fwdir}/${libnm}" "${target}"
330 source="${QtInstallDir}"
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
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}"
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)
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}"\
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}"\
382 # -------------------------
383 # Create universal binaries
384 # -------------------------
385 convert_universal() {
387 for file in ${FILE_LIST} ; do
389 for arch in ${ARCH_LIST} ; do
390 if [ -f "${BUNDLE_PATH}/${file}-${arch}" ]; then
391 OBJ_LIST="${OBJ_LIST} ${BUNDLE_PATH}/${file}-${arch}"
394 if [ -n "${OBJ_LIST}" ]; then
395 lipo -create ${OBJ_LIST} -o "${BUNDLE_PATH}/${file}"
397 if [ -d "${ASpellInstallDir}" ]; then
398 private_framework Aspell "${ASpellInstallDir}/lib/libaspell.15.dylib" "${LYX_BUNDLE_PATH}/${file}"
400 if [ -d "${QtInstallDir}/lib/QtCore.framework/Versions/${QtFrameworkVersion}" -a "yes" = "${qt4_deployment}" ]; then
401 deploy_qtlibs "${LYX_BUNDLE_PATH}/${file}"
403 otool -L "${BUNDLE_PATH}/${file}" | while read reference ; do
404 case "${reference}" in
405 *"${LyxBuildDir}"*"("*")")
406 echo ERROR: Bad reference to "${reference}" found!!
411 for arch in ${ARCH_LIST} ; do
412 rm -f ${BUNDLE_PATH}/*-${arch}
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
429 function set_bundle_display_options() {
431 tell application "Finder"
432 set f to POSIX file ("${1}" as string) as alias
435 tell container window
436 set toolbar visible to false
437 set statusbar visible to false
438 set current view to icon view
440 set the bounds to {20, 50, $2, $3}
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
459 function make_dmg() {
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 }'`
468 rm -f ${COMPRESSEDDMGNAME}
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}"
474 # Mount the disk image
475 hdiutil attach ${DMGNAME}.sparseimage
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 ' ')
482 # copy in the application bundle
483 cp -Rp ${LyxAppDir}.app ${VOLUME}/${LyxName}.app
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
493 # Unmount the disk image
494 hdiutil detach ${DEV}
496 # Convert the disk image to read-only
497 hdiutil convert ${DMGNAME}.sparseimage -format UDBZ -o ${COMPRESSEDDMGNAME}
498 rm -f ${DMGNAME}.sparseimage
505 # ------------------------------
506 # Building distribution packages
507 # ------------------------------
509 test -n "${LyxAppZip}" && (
510 cd "${LyxAppPrefix}" && zip -r "${LyxAppZip}" .
513 test -n "${DMGLocation}" && make_dmg "${DMGLocation}"