Size: 26195
Comment:
|
Size: 24603
Comment:
|
Deletions are marked like this. | Additions are marked like this. |
Line 6: | Line 6: |
This page contains instructions on compiling EMAN for OS X in a format suitable for distribution. This requires significantly more work than setting up a simple environment to use on just one machine. Instructions for a non-distributable build are here: [:EMAN_COMPILE_MacOS_X:] ------ = DEPENDENCIES = * boost (1_34_1) |
This page contains instructions on compiling EMAN for OS X in a format suitable for distribution for the 4 main OS X supported architectures: 32 and 64 bit PowerPC and Intel x86. This requires significantly more work than setting up a simple environment to use on just one machine. Instructions for a non-distributable build are here: [:EMAN_COMPILE_MacOS_X:] ------ = DEPENDENCIES TO INSTALL = * boost (1.34.1) |
Line 17: | Line 17: |
* jpeg (v6b) * png (1.2.23) * numpy (1.0.4) |
* jpeg (6b) |
Line 31: | Line 29: |
I opted to place my build environment in a disk image to make it easier to move it from machine to machine. I used Disk Utility to create a sparse disk image with a max size of 40gb (it will shrink to the total size of the files contained.) I called the disk image "EMAN" and used the following directory structure for organization. {{{ /build/ /10.5 and 10.4 /32 and 64 /EMAN /dep /10.5 and 10.4 /bin, lib, share, etc. /Resoureces /PkgInfo /icns /plists /scripts /src /patches /EMAN /vars10.5.sh }}} "build" is for EMAN build itself. "dep" is the dependency install tree root. "extlib" is for modified dependency libraries. "EMAN" is for the EMAN source. "Resources" are support files to be used in the creation of Mac OS X app bundles. "src" is for downloaded source tarballs and patches. "stage" is where the EMAN package will be prepared for distribution. "vars10.x.sh" is for environment variables specific to building for each Mac OS X version. |
I setup my build environment (segregated from /usr/local to keep things tidy) as below, as a disk image mounted under /Volumes/EMAN. Minor changes will be required to paths in the instructions if you chose a different setup. {{{ ./build/ # main builds ./EMAN # EMAN builds ./EMAN # EMAN source ./dep # Install prefix; used instead of /usr/local ./stage # Staging area to install EMAN and setup distribution bundle ./src # Dependency sources ./patches # Dependency patches ./extlib # Fixed dylibs (@loader_path..) that we'll link against and use in bundle ./Resources # Files for making Qt/Mac .app bundles ./PkgInfo ./icns ./plists ./scripts }}} My build environment was 10.5 Leopard on Intel host using Xcode 3.0. I recommend 10.5 for EMAN use; Python 2.5 is newer, the 10.5 Python interpreter includes readline support, and building some of the dependencies for 10.4 is a bit tricky. Building for 10.4 target on a 10.5 host is possible and requires Xcode 2.5 to be installed in parallel to Xcode 3.0 (this is how I prepared the 10.4 version for distribution; make sure you use the /Xcode2.5/usr/bin tools in your path, /Xcode2.5/SDKs/.., etc.) I have not attempted to build for 10.4 on a 10.4 host. |
Line 63: | Line 59: |
My build environment was 10.5 Leopard on Intel host using Xcode 3.0. I recommend 10.5 for EMAN use; Python 2.5 is newer, the 10.5 Python interpreter includes readline support, and building some of the dependencies for 10.4 is a bit tricky. Building for 10.4 target on a 10.5 host is possible and requires Xcode 2.5 to be installed in parallel to Xcode 3.0 (this is how I prepared the 10.4 version for distribution.) I have not attempted to build for 10.4 on a 10.4 host. |
|
Line 71: | Line 63: |
I use these two variables in most of the scripts I provide. Set BROOT to the root of the build environment; in my case it was the disk image I made. We'll only be covering 10.5 in these instructions, but set MACOSX_DEPLOYMENT_TARGET as well. | I use these two variables in most of the scripts I provide. Set BROOT to the root of the build environment; in my case it was the disk image I made mounted on /Volumes/EMAN. We'll only be covering 10.5 in these instructions, but set MACOSX_DEPLOYMENT_TARGET as well since some of the Apple tools look for it. |
Line 78: | Line 70: |
The following environment variables were sufficient to get clean universal builds of dependencies in most cases. I put these in vars10.5.sh for quick access: {{{ #10.5 export MACOSX_DEPLOYMENT_TARGET=10.5 |
The following environment variables were sufficient to get clean universal builds of dependencies in most cases. I put these in a file for quick access. {{{ |
Line 85: | Line 75: |
export SROOT="-isysroot /Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.5" export LDF="-Wl,-headerpad_max_install_names" export CFLAGS="$SROOT $UARCH -O2 -g" export LDFLAGS="$UARCH $LDF" export PATH=/bin:/usr/bin:/usr/sbin:/sbin:/usr/local/bin |
export CFLAGS="-isysroot /Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.5 $UARCH -O2 -g" export LDFLAGS="$UARCH -Wl,-headerpad_max_install_names" |
Line 102: | Line 89: |
* jpegpatch.zip * libtool135update.zip |
* jpeg-v6b-patch.tar.gz (includes all MacPorts jpeg-v6b patches) |
Line 116: | Line 102: |
./configure --prefix=$PREFIX --exec-prefix=$PREFIX/fat --disable-dependency-tracking --disable-static --enable-shared LDFLAGS="$LDFLAGS" CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" }}} make and make install.. |
./configure --prefix=$PREFIX --disable-dependency-tracking --disable-static --enable-shared LDFLAGS="$LDFLAGS" CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" make make install }}} |
Line 125: | Line 111: |
./configure --prefix=$PREFIX --exec-prefix=$PREFIX/fat --disable-dependency-tracking --disable-static --enable-shared CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" }}} make and make install.. |
./configure --prefix=$PREFIX --disable-dependency-tracking --disable-static --enable-shared CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" make make install }}} |
Line 134: | Line 120: |
./configure --prefix=$PREFIX --exec-prefix=$PREFIX/fat --disable-dependency-tracking --disable-static --enable-shared CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" }}} make and make install.. |
./configure --prefix=$PREFIX --disable-dependency-tracking --disable-static --enable-shared CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" make make install }}} |
Line 142: | Line 129: |
./configure --prefix=$PREFIX --exec-prefix=$PREFIX/fat --disable-dependency-tracking --disable-static --enable-shared CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" }}} make and make install.. |
./configure --prefix=$PREFIX --disable-dependency-tracking --disable-static --enable-shared CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" make make install }}} |
Line 149: | Line 137: |
Patch to add fat binary support: | Patch from Adobe to add fat binary support: |
Line 157: | Line 146: |
./configure --with-toolset=darwin --with-libraries=python --prefix=$PREFIX --exec-prefix=$PREFIX/fat | ./configure --with-toolset=darwin --with-libraries=python --prefix=$PREFIX |
Line 162: | Line 151: |
* Add 64 bit (ppc64, x86_64) to fat arch | * Add 64 bit (ppc64, x86_64) to fat arch: |
Line 173: | Line 162: |
./tools/jam/src/bin.macosxx86/bjam -d+2 --user-config=user-config.jam --prefix=$PREFIX --libdir=$PREFIX/fat/lib/ --exec-prefix=$PREFIX/fat/bin/ --with-python sdkroot=$MACOSX_DEPLOYMENT_TARGET arch=fat install | ./tools/jam/src/bin.macosxx86/bjam -d+2 --user-config=user-config.jam --prefix=$PREFIX --with-python sdkroot=$MACOSX_DEPLOYMENT_TARGET arch=fat install |
Line 179: | Line 168: |
Patches from http://www.kyngchaos.com/macosx/install/libjpeg or download from ["MacOSXBuildFiles"] page. {{{ unzip $BROOT/src/patches/libtool135update.zip unzip $BROOT/src/patches/jpegpatch.zip cp /usr/share/libtool/config.* ./ patch makefile.cfg makefile.cfg.patch }}} Configure.. {{{ ./configure --prefix=$PREFIX --exec-prefix=$PREFIX/fat --disable-dependency-tracking --disable-static --enable-shared CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" }}} In Makefile, change CC and move it below CFLAGS... {{{ CC=gcc $(CFLAGS) }}} Patch archive_cmds in libtool: needs $CFLAGS {{{ archive_cmds="\$nonopt \$(test .\$module = .yes && echo -bundle || echo -dynamiclib) $CFLAGS \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$linkopts -install_name \$rpath/\$soname \$verstring" }}} make and make install.. |
libjpeg is very old (1998) and needs much work to compile properly on a modern system. Patches from MacPorts (http://trac.macports.org/browser/trunk/dports/graphics/jpeg/files ) or download from ["MacOSXBuildFiles"] page. {{{ for i in $BROOT/src/patches/jpeg-6b/patch-*;do patch < $i;done }}} {{{ ./configure --prefix=$PREFIX --disable-dependency-tracking --disable-static --enable-shared CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" make make install }}} |
Line 212: | Line 184: |
version-number needs to be changed to current_version in libtool {{{ sed s/"version-number"/"current_version"/ Makefile.in > Makefile2.in sed s/"version-number"/"current_version"/ Makefile.am > Makefile2.am mv Makefile2.in Makefile.in mv Makefile2.am Makefile.am }}} Configure.. {{{ ./configure --prefix=$PREFIX --exec-prefix=$PREFIX/fat --disable-dependency-tracking --disable-static --enable-shared CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" }}} make and make install.. |
{{{ ./configure --prefix=$PREFIX --disable-dependency-tracking --disable-static --enable-shared CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" make make install }}} The extra steps previously described in this document only seem to be required for 10.4. |
Line 233: | Line 196: |
./configure --prefix=$PREFIX --exec-prefix=$PREFIX/fat --disable-dependency-tracking --disable-static --enable-shared CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" }}} Patch archive_cmds in libtool, needs $CFLAGS {{{ archive_cmds="\$nonopt \$(test \\\"x\$module\\\" = xyes && echo -bundle || echo -dynamiclib) $CFLAGS \$allow_undefined_flag }}} make and make install.. |
./configure --prefix=$PREFIX --disable-dependency-tracking --disable-static --enable-shared CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" }}} Universal support requires patch to archive_cmds in libtool, needs $CFLAGS: {{{ archive_cmds="\$nonopt \$(test \\\"x\$module\\\" = xyes && echo -bundle || echo -dynamiclib) $CFLAGS \$allow_undefined_flag -o \$lib \$libobjs \$deplibs\$linker_flags -install_name \$rpath/\$soname \$verstring" }}} {{{ make make install }}} |
Line 245: | Line 212: |
{{{ ./configure --prefix=$PREFIX --exec-prefix=$PREFIX/fat --enable-float --disable-fortran --disable-dependency-tracking --disable-static --enable-shared CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" }}} Patch archive_cmds to include $CFLAGS in libtool.. this one needs it twice. |
{{{ ./configure --prefix=$PREFIX --enable-float --disable-fortran --disable-dependency-tracking --disable-static --enable-shared CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" }}} Universal support requires patch to archive_cmds in libtool, needs $CFLAGS, fftw2 needs it twice: |
Line 255: | Line 221: |
make and make install.. | {{{ make make install }}} |
Line 267: | Line 236: |
Use patches from Fink, or download them from ["MacOSXBuildFiles"] downloads page. | Use one of patches (qt3mac.patch2.txt) from Fink, or download them from ["MacOSXBuildFiles"] downloads page. This is necessary for Qt/Mac 3.3.8 to work on 10.5. |
Line 271: | Line 240: |
Apply patches {{{ sed s/free-3.3.5/free-3.3.8/g $BROOT/src/patches/qt3mac.patch.txt > ./qt3mac.patch1.txt cmd="s|@PREFIX@|`pwd`|g" sed -e $cmd < ./qt3mac.patch1.txt | patch -p1 |
Apply patches and fix a flag in Makefile: {{{ |
Line 288: | Line 254: |
./configure -prefix $PREFIX/qt3 -bindir $PREFIX/fat/bin/qt3 -libdir $PREFIX/fat/lib/qt3 -plugindir $PREFIX/fat/plugins/qt3 -release -shared -qt-gif -system-zlib -qt-libjpeg -qt-libmng | ./configure -prefix $PREFIX/qt3 -release -shared -qt-gif -system-zlib -qt-libjpeg -qt-libmng |
Line 294: | Line 260: |
QMAKE_CFLAGS = -pipe -arch ppc -arch i386 -isysroot /Developer/SDKs/MacOSX10.4u.sdk QMAKE_LFLAGS = -headerpad_max_install_names -arch ppc -arch i386 -Wl,-syslibroot,/Developer/SDKs/MacOSX10.5.sdk }}} make and make install.. |
QMAKE_CFLAGS = -pipe -arch ppc -arch i386 -isysroot /Developer/SDKs/MacOSX10.5.sdk ... QMAKE_LFLAGS = -headerpad_max_install_names -arch ppc -arch i386 -Wl,-syslibroot,/Developer/SDKs/MacOSX10.5.sdk }}} {{{ make make install }}} |
Line 304: | Line 274: |
Make copies of the dylibs. e.g.: {{{ mkdir $BROOT/extlib/$MACOSX_DEPLOYMENT_TARGET cd $BROOT/dep/$MACOSX_DEPLOYMENT_TARGET/fat/lib cp libboost_python-1_34_1.dylib libfftw.dylib libgsl.dylib libgslcblas.dylib libhdf5.dylib libjpeg.dylib libpng.dylib libpng12.dylib librfftw.dylib libsz.dylib libtiff.dylib qt3/libqt.dylib $BROOT/extlib/$MACOSX_DEPLOYMENT_TARGET cd $BROOT/extlib/$MACOSX_DEPLOYMENT_TARGET |
Copy the built dylibs to extlib (yours may be slightly different): {{{ mkdir $BROOT/extlib cd $BROOT/dep/lib cp libboost_python-1_34_1.dylib libfftw.dylib libgsl.dylib libgslcblas.dylib libhdf5.dylib libjpeg.dylib librfftw.dylib libsz.dylib libtiff.dylib qt3/libqt.dylib $BROOT/extlib/ cd $BROOT/extlib |
Line 317: | Line 287: |
Set install_name. necessary for placing the app bundle wherever is convenient. | Set install_name. This is necessary for libraries to be located without polluting DYLD_LIBRARY_PATH. |
Line 327: | Line 297: |
qmake will fail without this: {{{ export DYLD_LIBRARY_PATH=$BROOT/dep/10.5/src/qt-mac-free-3.3.8/lib/ }}} Do not load vars script. cmake doesn't like it. {{{ $BROOT/dep/cmake/bin/ccmake -DCMAKE_INSTALL_NAME_DIR:STRING=@loader_path/../lib $BROOT/EMAN/ |
Clear the environment variables (CFLAGS, LFLAGS, ..) we made for the dependencies and run cmake. CMAKE_INSTALl_NAME_DIR sets dylib @loader_path references properly. You may need to change the paths below. {{{ $BROOT/dep/bin/ccmake -DCMAKE_INSTALL_NAME_DIR:STRING=@loader_path/../lib $BROOT/EMAN/ |
Line 344: | Line 308: |
BOOST_INCLUDE_PATH /Volumes/EMAN/dep/10.5/include/boost-1_34_1 BOOST_LIBRARY /Volumes/EMAN/extlib/10.5/libboost_python.dylib |
BOOST_INCLUDE_PATH /Volumes/EMAN/dep/include/boost-1_34_1 BOOST_LIBRARY /Volumes/EMAN/extlib/libboost_python.dylib |
Line 357: | Line 321: |
EMAN_INSTALL_PREFIX /Volumes/EMAN/stage/10.5/EMAN/EMAN | EMAN_INSTALL_PREFIX /Volumes/EMAN/stage/EMAN/EMAN |
Line 359: | Line 323: |
EXECUTABLE_OUTPUT_PATH /Volumes/EMAN/build/10.5/32/EMAN/bin FFTW_INCLUDE_PATH /Volumes/EMAN/dep/10.5/include FFTW_LIBRARY /Volumes/EMAN/extlib/10.5/libfftw.dylib GSL_CBLAS_LIBRARY /Volumes/EMAN/extlib/10.5/libgslcblas.dylib GSL_INCLUDE_PATH /Volumes/EMAN/dep/10.5/include GSL_LIBRARY /Volumes/EMAN/extlib/10.5/libgsl.dylib HDF_INCLUDE_PATH /Volumes/EMAN/dep/10.5/include HDF_LIBRARY /Volumes/EMAN/extlib/10.5/libhdf5.dylib JPEG_LIBRARY /Volumes/EMAN/extlib/10.5/libjpeg.dylib LIBRARY_OUTPUT_PATH /Volumes/EMAN/build/10.5/32/EMAN/lib |
FFTW_INCLUDE_PATH /Volumes/EMAN/dep/include FFTW_LIBRARY /Volumes/EMAN/extlib/libfftw.dylib GSL_CBLAS_LIBRARY /Volumes/EMAN/extlib/libgslcblas.dylib GSL_INCLUDE_PATH /Volumes/EMAN/dep/include GSL_LIBRARY /Volumes/EMAN/extlib/libgsl.dylib HDF_INCLUDE_PATH /Volumes/EMAN/dep/include HDF_LIBRARY /Volumes/EMAN/extlib/libhdf5.dylib JPEG_LIBRARY /Volumes/EMAN/extlib/libjpeg.dylib |
Line 370: | Line 332: |
PNG_LIBRARY /Volumes/EMAN/extlib/10.5/libpng.dylib | PNG_LIBRARY /Volumes/EMAN/extlib/libpng.dylib |
Line 373: | Line 335: |
QT_INCLUDE_DIR /Volumes/EMAN/dep/10.5/qt3/include QT_MOC_EXECUTABLE /Volumes/EMAN/dep/10.5/fat/bin/qt3/moc QT_QT_LIBRARY /Volumes/EMAN/extlib/10.5/libqt.dylib QT_UIC_EXECUTABLE /Volumes/EMAN/dep/10.5/fat/bin/qt3/uic RFFTW_LIBRARY /Volumes/EMAN/extlib/10.5/librfftw.dylib TIF_INCLUDE_PATH /Volumes/EMAN/dep/10.5/include TIF_LIBRARY /Volumes/EMAN/extlib/10.5/libtiff.dylib |
QT_INCLUDE_DIR /Volumes/EMAN/dep/qt3/include QT_MOC_EXECUTABLE /Volumes/EMAN/dep/qt3/bin/moc QT_QT_LIBRARY /Volumes/EMAN/extlib/libqt.dylib QT_UIC_EXECUTABLE /Volumes/EMAN/dep/qt3/bin/uic RFFTW_LIBRARY /Volumes/EMAN/extlib/librfftw.dylib TIF_INCLUDE_PATH /Volumes/EMAN/dep/include TIF_LIBRARY /Volumes/EMAN/extlib/libtiff.dylib |
Line 388: | Line 350: |
qmake may require something like this to find libqt: {{{ export DYLD_LIBRARY_PATH=$BROOT/dep/src/qt-mac-free-3.3.8/lib/ }}} |
|
Line 394: | Line 361: |
EMAN_INSTALL_PREFIX /Volumes/EMAN/stage/10.5/EMAN/EMAN.64 | EMAN_INSTALL_PREFIX /Volumes/EMAN/stage/EMAN/EMAN.64 |
Line 403: | Line 370: |
Hopefully EMAN compiled and installed without any problems. I installed my EMAN to a staging directory to prepare it for distribution, e.g. /Volumes/EMAN/stage/10.5/EMAN, which contains EMAN, EMAN.64, etc.. | Hopefully EMAN compiled and installed without any problems. I installed my EMAN to a staging directory to prepare it for distribution, e.g. /Volumes/EMAN/stage/EMAN, which contains EMAN, EMAN.64, etc.. |
Line 409: | Line 376: |
The 'makedist.sh' script does most of packaging work automatically, but I'll step through it below. |
|
Line 416: | Line 381: |
cp -vr $BROOT/extlib/$MACOSX_DEPLOYMENT_TARGET/ $BROOT/stage/$MACOSX_DEPLOYMENT_TARGET/extlib/ | cp -vr $BROOT/extlib/ $BROOT/stage/extlib/ |
Line 424: | Line 389: |
cd $BROOT/stage/$MACOSX_DEPLOYMENT_TARGET/EMAN/EMAN/lib/; \ | cd $BROOT/stage/EMAN/EMAN/lib/; \ |
Line 433: | Line 398: |
Qt/Mac GUI programs on Mac OS X will not connect properly to the window manager unless they have a .app bundle structure and correct Info.plist file. See the Apple Bundle documentation for more details. | Qt/Mac GUI programs on Mac OS X will not connect properly to the window manager unless they have an .app bundle structure and correct Info.plist file. See the Apple Bundle documentation for more details. |
Line 508: | Line 473: |
I have made Info.plist files for all the gui programs: boxer, checkslice, ctfit, eman, helixboxer, QHelp, qindex, qplot, qsegment, triplot, v2, and v4. I also made icons for the programs and file types that you can use. | The remainder of the gui programs (checkslice, ctfit, eman, helixboxer, QHelp, qindex, qplot, qsegment, triplot, v2, v4) follow a similar pattern, with changes to CFIconFile, CFExecutable, CFBundleName, and file type associations. You can copy the plist files I already prepared (which include file associations) and icons. |
Line 522: | Line 487: |
On Linux and Windows, launching a program from Explorer/Konqueror/etc typically just adds any files to be opened as command line args. On Mac OS X, however, it's instead passed as an Objective-C object to the application. You can patch your ported program to support this, or you can use a wrapper script that emulates argv support. I chose to use PythonObjC because it is installed by default on OS X. I modified a script provided by Apple to function as the wrapper. You can download it from the resources page and use it as 'argvemulator.py' in the following steps. | On Linux and Windows, launching a program from from the GUI file browser typically just adds any files to be opened as command line args. On Mac OS X, however, it's instead passed as an Objective-C object to the application. You can patch your ported program to support this, or you can use a wrapper script that emulates argv support. I chose to use PythonObjC because it is installed by default on OS X. I modified a script provided by Apple to function as the wrapper. You can download it from the resources page and use it as 'argvemulator.py' in the following steps. |
Line 526: | Line 491: |
I use the following script to automate the packaging. Be mindful of paths if you are using it with a different build/install environment directory structure. {{{ emandir=$BROOT/stage/$MACOSX_DEPLOYMENT_TARGET/EMAN/EMAN; |
I use the following steps to prepare the bundles. Be mindful of paths if you are using it with a different build/install environment directory structure. {{{ emandir=$BROOT/stage/EMAN/EMAN; |
Line 575: | Line 540: |
Create emaninit.sh, which will be 'source'd from .bashrc to setup PATH, PYTHONPATH, etc. {{{ ###EMAN |
Create an EMAN init script, which will be 'source'd from .bashrc to setup PATH, PYTHONPATH, etc. {{{ |
Line 583: | Line 547: |
###ENDEMAN }}} {{{ cp -vr $BROOT/Resources/scripts/emaninit.sh $BROOT/stage/$MACOSX_DEPLOYMENT_TARGET/EMAN/ |
}}} Add it to the bundle: {{{ cp -vr $BROOT/Resources/scripts/emaninit.sh $BROOT/stage/EMAN/ |
Line 595: | Line 560: |
hdiutil create -srcfolder 10.5 EMAN_Leopard.dmg | hdiutil create -srcfolder EMAN EMAN_Leopard.dmg |
Line 602: | Line 567: |
Copy $BROOT/stage/$MACOSX_DEPLOYMENT_TARGET/EMAN to /Applications using the Finder (this will read all the Info.plist files and install file type associations.) Alternatively, copy the disk image to another machine, attach the disk image, and copy EMAN from there to /Applications. |
Copy $BROOT/stage/EMAN to /Applications using the Finder (this will read all the Info.plist files and install file type associations.) Alternatively, attach the disk image, and copy EMAN from there to /Applications. |
PREFACE
This page contains instructions on compiling EMAN for OS X in a format suitable for distribution for the 4 main OS X supported architectures: 32 and 64 bit PowerPC and Intel x86. This requires significantly more work than setting up a simple environment to use on just one machine. Instructions for a non-distributable build are here: [:EMAN_COMPILE_MacOS_X:]
DEPENDENCIES TO INSTALL
- boost (1.34.1)
- cmake (2.4.8)
- fftw (2.1.5)
- gsl (1.8)
- hdf5 (1.6.6)
- jpeg (6b)
- Qt/Mac (3.3.8)
- szip (2.1)
- tiff (3.8.2)
- zlib (1.2.1)
(verisons I have used in my own builds. I have placed copies of all srcs in ["MacOSXBuildFiles"])
PREPARING BUILD ENVIRONMENT
I setup my build environment (segregated from /usr/local to keep things tidy) as below, as a disk image mounted under /Volumes/EMAN. Minor changes will be required to paths in the instructions if you chose a different setup.
./build/ # main builds ./EMAN # EMAN builds ./EMAN # EMAN source ./dep # Install prefix; used instead of /usr/local ./stage # Staging area to install EMAN and setup distribution bundle ./src # Dependency sources ./patches # Dependency patches ./extlib # Fixed dylibs (@loader_path..) that we'll link against and use in bundle ./Resources # Files for making Qt/Mac .app bundles ./PkgInfo ./icns ./plists ./scripts
My build environment was 10.5 Leopard on Intel host using Xcode 3.0.
I recommend 10.5 for EMAN use; Python 2.5 is newer, the 10.5 Python interpreter includes readline support, and building some of the dependencies for 10.4 is a bit tricky. Building for 10.4 target on a 10.5 host is possible and requires Xcode 2.5 to be installed in parallel to Xcode 3.0 (this is how I prepared the 10.4 version for distribution; make sure you use the /Xcode2.5/usr/bin tools in your path, /Xcode2.5/SDKs/.., etc.) I have not attempted to build for 10.4 on a 10.4 host.
Because 10.4 and 10.5 use different versions of Python, the EMAN Python bindings will only work on the version it was built against: Python 2.3 for 10.4, Python 2.5 for 10.5.
So, for simplicity's sake, I will only discuss building for 10.5 target on a 10.5 host in these instructions.
Mac OS X supports multiple architectures in a single "universal" or "fat" binary/library. This is achieved by passing -arch flags to gcc (this is a special Apple-gcc flag) which will take care of all the details. Alternatively you can compile for different architectures separately and merge them together afterwards. For 10.5 I built both 32 and 64 bit versions for both Intel and PowerPC (i386, x86_64, ppc, ppc64.) On 10.4 I built only 32 bit versions for Intel and PowerPC.
I use these two variables in most of the scripts I provide. Set BROOT to the root of the build environment; in my case it was the disk image I made mounted on /Volumes/EMAN. We'll only be covering 10.5 in these instructions, but set MACOSX_DEPLOYMENT_TARGET as well since some of the Apple tools look for it.
export BROOT=/Volumes/EMAN/ export MACOSX_DEPLOYMENT_TARGET=10.5
The following environment variables were sufficient to get clean universal builds of dependencies in most cases. I put these in a file for quick access.
export PREFIX=$BROOT/dep/$MACOSX_DEPLOYMENT_TARGET export UARCH="-arch i386 -arch ppc -arch x86_64 -arch ppc64" export CFLAGS="-isysroot /Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.5 $UARCH -O2 -g" export LDFLAGS="$UARCH -Wl,-headerpad_max_install_names"
If you want to install all the dependencies in /usr/local, set PREFIX to accordingly. I chose to keep everything on the disk image I made, separated by deployment target.
PATCHES REQUIRED
Several dependencies required patches to compile properly. Most of them are taken from fink/macports, or other internet sources. I have them available for download at ["MacOSXBuildFiles"]:
- boost.patch
- darwin.jam
jpeg-v6b-patch.tar.gz (includes all MacPorts jpeg-v6b patches)
- qt3mac.patch.txt
- qt3mac.patch2.txt
I placed the patches in $BROOT/src/patches.
BUILDING DEPENDENCIES
CMAKE
./configure --prefix=$PREFIX --disable-dependency-tracking --disable-static --enable-shared LDFLAGS="$LDFLAGS" CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" make make install
PNG
./configure --prefix=$PREFIX --disable-dependency-tracking --disable-static --enable-shared CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" make make install
SZIP
./configure --prefix=$PREFIX --disable-dependency-tracking --disable-static --enable-shared CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" make make install
GSL
./configure --prefix=$PREFIX --disable-dependency-tracking --disable-static --enable-shared CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" make make install
BOOST
Patch from Adobe to add fat binary support:
patch -p1 < $BROOT/src/patches/boost.patch
Build bjam:
./configure --with-toolset=darwin --with-libraries=python --prefix=$PREFIX
In tools/build/v2/tools/darwin.jam:
- change sdkroot to use /Developer/SDKs/MacOSX10.5.sdk
- Add 64 bit (ppc64, x86_64) to fat arch:
feature arch : native ppc i386 fat : composite propagated ; flags darwin.compile OPTIONS <arch>fat : -arch i386 -arch ppc -arch x86_64 -arch ppc64 ; flags darwin.link OPTIONS <arch>fat : -arch i386 -arch ppc -arch x86_64 -arch ppc64 ;
Compile and install..
./tools/jam/src/bin.macosxx86/bjam -d+2 --user-config=user-config.jam --prefix=$PREFIX --with-python sdkroot=$MACOSX_DEPLOYMENT_TARGET arch=fat install
JPEG
libjpeg is very old (1998) and needs much work to compile properly on a modern system. Patches from MacPorts (http://trac.macports.org/browser/trunk/dports/graphics/jpeg/files ) or download from ["MacOSXBuildFiles"] page.
for i in $BROOT/src/patches/jpeg-6b/patch-*;do patch < $i;done
./configure --prefix=$PREFIX --disable-dependency-tracking --disable-static --enable-shared CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" make make install
TIFF
./configure --prefix=$PREFIX --disable-dependency-tracking --disable-static --enable-shared CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" make make install
The extra steps previously described in this document only seem to be required for 10.4.
HDF5
./configure --prefix=$PREFIX --disable-dependency-tracking --disable-static --enable-shared CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS"
Universal support requires patch to archive_cmds in libtool, needs $CFLAGS:
archive_cmds="\$nonopt \$(test \\\"x\$module\\\" = xyes && echo -bundle || echo -dynamiclib) $CFLAGS \$allow_undefined_flag -o \$lib \$libobjs \$deplibs\$linker_flags -install_name \$rpath/\$soname \$verstring"
make make install
FFTW2
./configure --prefix=$PREFIX --enable-float --disable-fortran --disable-dependency-tracking --disable-static --enable-shared CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS"
Universal support requires patch to archive_cmds in libtool, needs $CFLAGS, fftw2 needs it twice:
archive_cmds="\$CC $CFLAGS -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs && \$CC \$(test .\$module = .yes && echo -bundle || echo -dynamiclib) $CFLAGS \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs\$linker_flags \$(test .\$module != .yes && echo -install_name \$rpath/\$soname \$verstring)"
make make install
EMAN expects srfftw.h, sfftw.h. After install, go to the include directory (in my case $BROOT/dep/$MACOSX_DEPLOYMENT_TARGET/include) and make these links:
ln -s fftw.h sfftw.h ln -s rfftw.h srfftw.h
Qt3-Mac
Use one of patches (qt3mac.patch2.txt) from Fink, or download them from ["MacOSXBuildFiles"] downloads page. This is necessary for Qt/Mac 3.3.8 to work on 10.5.
Carbon dependency makes it 32 bit only.
Apply patches and fix a flag in Makefile:
patch -p1 < $BROOT/src/patches/qt3mac.patch2.txt perl -pi.bak -e 's|cp \-P|cp \-Rp|' qmake/Makefile.unix
These must be in path for qmake to work correctly.
export DYLD_LIBRARY_PATH=`pwd`/lib export PATH=$PATH:`pwd`/bin
./configure -prefix $PREFIX/qt3 -release -shared -qt-gif -system-zlib -qt-libjpeg -qt-libmng
In mkspecs/macx-g++/qmake.conf:
QMAKE_CFLAGS = -pipe -arch ppc -arch i386 -isysroot /Developer/SDKs/MacOSX10.5.sdk ... QMAKE_LFLAGS = -headerpad_max_install_names -arch ppc -arch i386 -Wl,-syslibroot,/Developer/SDKs/MacOSX10.5.sdk
make make install
PREPARE LIBRARIES
Copy the built dylibs to extlib (yours may be slightly different):
mkdir $BROOT/extlib cd $BROOT/dep/lib cp libboost_python-1_34_1.dylib libfftw.dylib libgsl.dylib libgslcblas.dylib libhdf5.dylib libjpeg.dylib librfftw.dylib libsz.dylib libtiff.dylib qt3/libqt.dylib $BROOT/extlib/ cd $BROOT/extlib mv libboost_python-1_34_1.dylib libboost_python.dylib
Set install_name. This is necessary for libraries to be located without polluting DYLD_LIBRARY_PATH.
for i in *dylib;do install_name_tool -id @loader_path/../../extlib/$i $i;done
BUILD EMAN
Clear the environment variables (CFLAGS, LFLAGS, ..) we made for the dependencies and run cmake. CMAKE_INSTALl_NAME_DIR sets dylib @loader_path references properly. You may need to change the paths below.
$BROOT/dep/bin/ccmake -DCMAKE_INSTALL_NAME_DIR:STRING=@loader_path/../lib $BROOT/EMAN/
10.5, 32 bit
Default options except those below. Replace any /Volumes/EMAN.. paths with the correct path to your build/install environment. Link against the libraries you created with the modified install_names.
BOOST_INCLUDE_PATH /Volumes/EMAN/dep/include/boost-1_34_1 BOOST_LIBRARY /Volumes/EMAN/extlib/libboost_python.dylib CMAKE_BACKWARDS_COMPATIBILITY 2.4 CMAKE_CXX_FLAGS -mmacosx-version-min=10.5 CMAKE_C_FLAGS -mmacosx-version-min=10.5 CMAKE_INSTALL_NAME_DIR @loader_path/../lib CMAKE_OSX_ARCHITECTURES i386;ppc CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.5.sdk CMAKE_VERBOSE_MAKEFILE ON EMAN_INSTALL_PREFIX /Volumes/EMAN/stage/EMAN/EMAN FFTW_INCLUDE_PATH /Volumes/EMAN/dep/include FFTW_LIBRARY /Volumes/EMAN/extlib/libfftw.dylib GSL_CBLAS_LIBRARY /Volumes/EMAN/extlib/libgslcblas.dylib GSL_INCLUDE_PATH /Volumes/EMAN/dep/include GSL_LIBRARY /Volumes/EMAN/extlib/libgsl.dylib HDF_INCLUDE_PATH /Volumes/EMAN/dep/include HDF_LIBRARY /Volumes/EMAN/extlib/libhdf5.dylib JPEG_LIBRARY /Volumes/EMAN/extlib/libjpeg.dylib PNG_INCLUDE_PATH /Volumes/EMAN/dep/10.5/include PNG_LIBRARY /Volumes/EMAN/extlib/libpng.dylib PYTHON_INCLUDE_PATH /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/Python.framework/Versions/2.5/Headers PYTHON_LIBRARY /Developer/SDKs/MacOSX10.5.sdk/usr/lib/libpython.dylib QT_INCLUDE_DIR /Volumes/EMAN/dep/qt3/include QT_MOC_EXECUTABLE /Volumes/EMAN/dep/qt3/bin/moc QT_QT_LIBRARY /Volumes/EMAN/extlib/libqt.dylib QT_UIC_EXECUTABLE /Volumes/EMAN/dep/qt3/bin/uic RFFTW_LIBRARY /Volumes/EMAN/extlib/librfftw.dylib TIF_INCLUDE_PATH /Volumes/EMAN/dep/include TIF_LIBRARY /Volumes/EMAN/extlib/libtiff.dylib X11_X11_INCLUDE_PATH X11_X11_LIB X11_Xext_LIB X11_Xlib_INCLUDE_PATH X11_Xutil_INCLUDE_PATH Z_LIBRARY /Developer/SDKs/MacOSX10.5.sdk/usr/lib/libz.dylib
qmake may require something like this to find libqt:
export DYLD_LIBRARY_PATH=$BROOT/dep/src/qt-mac-free-3.3.8/lib/
10.5, 64 bit
Same as 10.5/32, but with changes:
EMAN_INSTALL_PREFIX /Volumes/EMAN/stage/EMAN/EMAN.64 CMAKE_OSX_ARCHITECTURES x86_64;ppc64 ENABLE_GUI OFF
EMAN POST-INSTALL
Hopefully EMAN compiled and installed without any problems. I installed my EMAN to a staging directory to prepare it for distribution, e.g. /Volumes/EMAN/stage/EMAN, which contains EMAN, EMAN.64, etc..
First, Load environment vars to get $BROOT and $MACOSX_DEPLOYMENT_TARGET.
Second, optionally, set staging dir icon using Finder... copy appropriate .icns file and paste into folder icon in 'get info'.
You can get all the files I will use on the ["MacOSXBuildFiles"] downloads page.
Copy extlibs to staging area
cp -vr $BROOT/extlib/ $BROOT/stage/extlib/
Python dylib links
The python dylib loader seems to only look for .so files instead of .dylib files. This creates these links. If you built EMAN for 64 bits as well, repeat for that as well.
cd $BROOT/stage/EMAN/EMAN/lib/; \ for i in *.dylib; do \ test=`echo $i | sed s/dylib/so/`; \ ln -sv $i $test; \ done;
Creating App Bundles
Qt/Mac GUI programs on Mac OS X will not connect properly to the window manager unless they have an .app bundle structure and correct Info.plist file. See the Apple Bundle documentation for more details.
This is the basic structure of an app bundle:
boxer.app/ /Contents /Info.plist # xml package definition /PkgInfo # identifies as application, framework, etc. /MacOS # bin directory /boxer # main executable /Resources # application resources dir /boxer.icns # app icon /icon-box.icns # file type icon
Our actual bundles will be slightly more complex and contain a few symlinks and wrappers to save on disk space and effort.
Info.plist files
First, we need to create Info.plist files for each EMAN GUI program. I'll use the boxer program as an example.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict>
This key tells the Finder which document types boxer can handle, as well as maps an icon to the file.
<key>CFBundleDocumentTypes</key> <array> <dict> <key>CFBundleTypeExtensions</key> <array> <string>box</string> </array> <key>CFBundleTypeIconFile</key> <string>icon-box.icns</string> <key>CFBundleTypeName</key> <string>Box database</string> <key>CFBundleTypeRole</key> <string>Editor</string> <key>LSIsAppleDefaultForType</key> <true/> </dict> </array>
CFBundleName is the localized display name for the application. If this is not set, it will be the name of the executable. Since we'll be using wrappers, we'll set this, otherwise the program will come up as "boxer.wrapper" or similar.
<key>CFBundleName</key> <string>Boxer</string>
The name of the executable that will run when opened via Finder
<key>CFBundleExecutable</key> <string>boxer.wrapper</string>
A few more keys that define the info string, the icon file to be used, etc.
<key>CFBundleGetInfoString</key> <string>EMAN</string> <key>CFBundleIconFile</key> <string>boxer</string> <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleSignature</key> <string>????</string> </dict> </plist>
The remainder of the gui programs (checkslice, ctfit, eman, helixboxer, QHelp, qindex, qplot, qsegment, triplot, v2, v4) follow a similar pattern, with changes to CFIconFile, CFExecutable, CFBundleName, and file type associations. You can copy the plist files I already prepared (which include file associations) and icons.
Command-line wrapper
To launch the GUI programs properly from the command line, you can either make your $PATH very complex, or just use a simple wrapper script. You'll use this as 'applaunch.sh' in the next few steps.
basename=`basename $0` $EMANDIR/apps/$basename.app/Contents/MacOS/$basename $@
Finder wrapper
On Linux and Windows, launching a program from from the GUI file browser typically just adds any files to be opened as command line args. On Mac OS X, however, it's instead passed as an Objective-C object to the application. You can patch your ported program to support this, or you can use a wrapper script that emulates argv support. I chose to use PythonObjC because it is installed by default on OS X. I modified a script provided by Apple to function as the wrapper. You can download it from the resources page and use it as 'argvemulator.py' in the following steps.
Creating bundle structure and copying files into it
I use the following steps to prepare the bundles. Be mindful of paths if you are using it with a different build/install environment directory structure.
emandir=$BROOT/stage/EMAN/EMAN; skeldir=$BROOT/Resources cd $emandir
Clean out any existing app directory, and create a list of all binaries that link against Qt/Mac.
rm -rf $emandir/apps mkdir $emandir/apps c="" cd $emandir/bin for i in *;do a=`otool -L $i | grep libqt`;if [ -n "$a" ];then c="$c $i";fi;done cd $emandir
Create the directory structure for the app bundle. Copy the PkgInfo file (they all use the same one.) Copy the icon file. Copy the correct plist file. Copy the argvemulator as a wrapper so it operates properly when launched from the Finder. Move the binary from the EMAN dir to a directory in the bundle. Link to another wrapper to make it launch properly (e.g. 'boxer') from the command line. Create symlinks 'lib' and 'extlib' so the dylibs can be found.
for i in $c;do \ cd $emandir; \ ad=$emandir/apps/$i.app; \ mkdir -v $ad; \ mkdir -v $ad/Contents; \ mkdir -v $ad/Contents/MacOS; \ mkdir -v $ad/Contents/Resources; \ mkdir -v $ad/Contents/Resources/EMAN; \ mkdir -v $ad/Contents/Resources/EMAN/bin; \ cp -v $skeldir/PkgInfo $ad/Contents/PkgInfo; \ cp -v $skeldir/icns/$i.icns $ad/Contents/Resources/$i.icns; \ cp -v $skeldir/plists/$i.plist $ad/Contents/Info.plist; \ cp -v $skeldir/scripts/argvemulator.py $ad/Contents/MacOS/$i.wrapper; \ mv -v $emandir/bin/$i $ad/Contents/Resources/EMAN/bin/$i; \ cd $emandir/bin; \ cp -v $skeldir/scripts/applaunch.sh ./$i; \ cd $ad/Contents/MacOS; \ ln -sv ../Resources/EMAN/bin/$i ./$i; \ cd $ad/Contents/Resources/EMAN; \ ln -sv ../../../../../lib ./lib; \ cd $ad/Contents/Resources; \ ln -sv ../../../../../extlib/ ./extlib; \ done
EMAN environment variables script
Create an EMAN init script, which will be 'source'd from .bashrc to setup PATH, PYTHONPATH, etc.
export EMANBASE=/Applications/EMAN/ export EMANDIR=$EMANBASE/EMAN export PATH=$PATH:$EMANBASE/EMAN/bin:$EMANBASE/EMAN2/bin export PYTHONPATH=$PYTHONPATH:$EMANBASE/EMAN/lib:$EMANBASE/EMAN2/lib
Add it to the bundle:
cp -vr $BROOT/Resources/scripts/emaninit.sh $BROOT/stage/EMAN/
Package into disk image
cd $BROOT/stage/ rm -v EMAN_*.dmg hdiutil create -srcfolder EMAN EMAN_Leopard.dmg
Installation
Copy $BROOT/stage/EMAN to /Applications using the Finder (this will read all the Info.plist files and install file type associations.)
Alternatively, attach the disk image, and copy EMAN from there to /Applications.
Add the following to your ~/.bashrc file:
test -r /Applications/EMAN/emaninit.sh && . /Applications/EMAN/emaninit.sh
Contact Information
If you have any difficulties, you may email me: Ian Rees, ian.rees at bcm edu.
Enjoy.