User Tools

Site Tools


proj:macdev

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
proj:macdev [2015/03/14 21:47]
admin [ImageMagick/convert and Ghostscript]
proj:macdev [2016/04/21 04:35] (current)
admin [Testing Results]
Line 4: Line 4:
  
 ====== Mac Development Environment ====== ====== Mac Development Environment ======
 +
 +For packaging of latest version, see [[proj:​macinstallers]]
 +
 +This page is relevant to building new template (containing binaries etc).
 +
 +NOTE - need a new version to handle 10.7 (Lion) upwards. Explanation:​
 +
 +  Hi Grant,
 +  ​
 +  I remembered the reason that for OS X support sometimes being limited to 10.7.
 +  It's because of C++11. The standard library that goes with this, libc++, is only
 +  supported as far back as 10.7. If you want to support earlier versions then all
 +  of the C++ bits need to be built for and linked against the old stdc++ library.
 +  ​
 +  Cheers
 +  Glenn
  
 ===== Virtualising Mac OSX ===== ===== Virtualising Mac OSX =====
Line 77: Line 93:
   * sudo chown -R `whoami` /usr/local # otherwise symlinking won't work - see http://​developpeers.com/​blogs/​fix-for-homebrew-permission-denied-issues. Note - /usr/local gets made by brew it seems so can't do this step too early   * sudo chown -R `whoami` /usr/local # otherwise symlinking won't work - see http://​developpeers.com/​blogs/​fix-for-homebrew-permission-denied-issues. Note - /usr/local gets made by brew it seems so can't do this step too early
  
-===== ImageMagick/convert ​and Ghostscript ​===== +===== ImageMagick ​(convert=====
- +
- +
-  brew install ghostscript +
- +
-So we can include that in our imagemagick build.+
  
 Cannot use standard installers as are all 64-bit (will get Bad CPU error message). So ignore the binary-releases page. Homebrew works when osx 10.6.8 and xcode 3.2.2. (unlike 10.6.0 and 3.2) so ... Cannot use standard installers as are all 64-bit (will get Bad CPU error message). So ignore the binary-releases page. Homebrew works when osx 10.6.8 and xcode 3.2.2. (unlike 10.6.0 and 3.2) so ...
Line 112: Line 123:
 At one point there seemed to be a permissions problem with /usr/lib again so needed to sudo chown -R `whoami` /usr/local again and then brew link various libs: libtiff jbig2dec little-cms2 ghostscript. Might not be required but try it if a problem. At one point there seemed to be a permissions problem with /usr/lib again so needed to sudo chown -R `whoami` /usr/local again and then brew link various libs: libtiff jbig2dec little-cms2 ghostscript. Might not be required but try it if a problem.
  
 +===== Ghostscript (gs) =====
 +
 +Don't bother with a brew install. Just download latest source, extract, cd into folder with configure inside and:
 +
 +  ./configure --disable-dynamic --with-drivers=FILES
 +
 +I thought I could get away with --with-drivers=PNG but it failed but =FILES dropped it enough (about 17MB) and worked.
 +
 +--disable-dynamic bakes in a whole lot so gs doesn'​t try to find it outside e.g. gs_init.ps. No need to have a parallel share/​ghostscript/​...gs_init.ps
 +===== convert and gs =====
 +
 +  - Don't compile ghostscript with gslib on board
 +  - Do export MAGICK_CONFIGURE_PATH='/​...'​ whatever path you put delegates.xml in
 +  - Do put colors.xml in same folder (now you've got all the essential configuration files I need)
 +  - Ensure PATH is set to start with the folder gs is in. Removes need to hardwire in the path to gs all over the place.
 +
 +  export PATH=<​folder_gs_etc_are_in>:​${PATH}
 +
 +Success!
 +
 +If delegates.xml can't be found, the error message might be something like:
 +
 +  convert: UnableToOpenConfigureFile `delegates`.xml'​ @warning/​configure.c/​GetConfigureOptions/​706.
 +
 +If the command used to handle something doesn'​t work the error message from imagemagick is not very useful. It will be something like:
 +
 +  convert: NoImagesDefined `/​Users/​g/​Desktop/​test.png'​ @error/​convert.c/​ConvertImageCommand/​3212.
 ====== Linking Dependencies to @executable_path ====== ====== Linking Dependencies to @executable_path ======
  
Line 303: Line 341:
   * Frameworks   * Frameworks
     * convert     * convert
 +    * gs
     * pdftk     * pdftk
     * wkhtmltopdf     * wkhtmltopdf
 +    * and all the dylibs etc that these libraries require (other than pdftk - see below)
  
 Also a lib folder containing the dylibs required by pdftk (namely, the contents of /​opt/​pdflabs/​pdftk/​lib. pdftk expects its dylibs to be in ../lib) Also a lib folder containing the dylibs required by pdftk (namely, the contents of /​opt/​pdflabs/​pdftk/​lib. pdftk expects its dylibs to be in ../lib)
Line 323: Line 363:
  
   install_name_tool -change '/​usr/​local/​Cellar/​imagemagick/​6.9.0-3/​lib/​libMagickCore-6.Q16.2.dylib'​ '​@executable_path/​libMagickCore-6.Q16.2.dylib'​   install_name_tool -change '/​usr/​local/​Cellar/​imagemagick/​6.9.0-3/​lib/​libMagickCore-6.Q16.2.dylib'​ '​@executable_path/​libMagickCore-6.Q16.2.dylib'​
 +
 +I have automated this with a script called dependable.py:​
 +
 +#! /​usr/​local/​Cellar/​python/​2.7.9/​bin/​python2.7
 + # -*- coding: utf-8 -*-
 + """​
 + Inspired by http://​thecourtsofchaos.com/​2013/​09/​16/​how-to-copy-and-relink-binaries-on-osx/​
 +  ​
 + Copy everything into a working folder so we don't mess up any original binaries.
 +  ​
 + Must run as sudo otherwise no permissions.
 + """​
 + from __future__ import print_function
 + import os
 + import shutil
 + import subprocess
 +  ​
 + working_folder = "/​Users/​grantpaton-simpson/​Desktop/​indeps/"​
 + processed_binpaths = []
 +  ​
 + def relink_dep(working_binpath,​ dep_path):
 +     """​
 +     working_binpath - never want to change original versions of binaries - only 
 +     copies in the working folder.
 +     """​
 +     old_link = dep_path
 +     dep_fname = os.path.split(dep_path)[1]
 +     new_link = "​@executable_path/"​ + dep_fname
 +     retval = subprocess.call(["​install_name_tool",​ "​-change",​ old_link, new_link,
 + working_binpath])
 +     if retval != 0:
 + raise Exception("​Problem relinking %s inside %s" % (old_link, working_binpath))
 +  ​
 + def get_deps(orig_binpath,​ working_folder):​
 +     """​
 +     Adjust copy of file originally at orig_binpath so expects dependencies to be in
 +     same path it is in.
 +  ​
 +     Pass any dep files that have not been processed already back through get_deps.
 +     """​
 +     # check not a repeat
 +     if orig_binpath in processed_binpaths:​
 + print("​Not copying or relinking %s. Already handled"​ % orig_binpath)
 + return
 +     processed_binpaths.append(orig_binpath)
 +     # make working copy of binary (we never mess with the original)
 +     bin_fname = os.path.split(orig_binpath)[1]
 +     working_binpath = os.path.join(working_folder,​ bin_fname)
 +     shutil.copy(orig_binpath,​ working_binpath)
 +     # identify dependencies
 +     output = subprocess.check_output(["​otool",​ "​-L",​ working_binpath])
 +     dep_path_output = [x.strip().split("​ ")[0] for x in output.split("​\n"​) if x.strip() != ""​]
 +     if len(dep_path_output) < 2:
 + print("​%s has no dependencies"​ % working_binpath)
 + return
 +     else:
 + # Handle dependencies - flexibly relink to each and send them through again in case 
 + # they have their own dependencies.
 + dep_paths = dep_path_output[1:​] # always displays binary as first item so ignore that one
 + for dep_path in dep_paths:
 +     relink_dep(working_binpath,​ dep_path)
 +     get_deps(dep_path,​ working_folder) # back down the rabbit hole with you!
 +  ​
 + def fix_binpath(binpath,​ working_folder_root,​ bin_shortname=None):​
 +     if raw_input("​Are you running as sudo? y/n ") != "​y":​
 + print("​Maybe next time")
 + return
 +     if not bin_shortname:​
 + bin_shortname = os.path.split(binpath)[1]
 +     working_folder = working_folder_root + "​_"​ + bin_shortname ​
 +     try:
 + shutil.rmtree(working_folder)
 +     except OSError:
 + pass
 +     os.mkdir(working_folder)
 +     get_deps(binpath,​ working_folder)
 +     subprocess.call(["​chmod",​ "​-R",​ "​777",​ working_folder])
 +     print("​Processed:​\n"​ + ";​\n"​.join(processed_binpaths))
 +     print("​Finished"​)
 +  ​
 + fix_binpath(binpath="/​usr/​local/​Cellar/​imagemagick/​6.9.0-9/​bin/​convert",​
 +     working_folder_root="/​Users/​grantpaton-simpson/​Desktop/​indeps"​)
 +  ​
 + fix_binpath(binpath="/​usr/​local/​Cellar/​ghostscript/​9.15/​bin/​gs",​
 +     working_folder_root="/​Users/​grantpaton-simpson/​Desktop/​indeps"​)
 +
 +===== Practical Packaging =====
 +
 +To simplify things, maybe do the dependable.py strategy on pdftk so ALL files are in one folder. One less thing to have to handle.
 +
 +That would mean we have stable Frameworks (convert, gs, delegates.xml,​ colors.xml, wkhtmltopdf etc etc) and Resources folders (has sofastatistics.icns and all the pyinstaller bits and pieces) and the only thing that changes is the MacOS folder.
 +
 +So modify spec file to copy across those two folders into app once made, and copy contents from sofa.main into MacOS and we have a package ready to go.
 +
 +===== Testing Results =====
 +
 +^ OS X Version ​  ^ PDF   ^ Images ​   ^ Contact ​                        ^ Help more  ^ Other       ^
 +| Yosemite 10.10    | Yes | No  | R. B. Lenin - rblenin@gmail.com ​      | Yes | US |
 +| Yosemite 10.10.2 ​ | Yes | No  | Richard O'​Donovan - odonovan.richard@gmail.com | Yes | Percentage Label clipped on left in multiple bar charts. Can help TEST COMPILED files. |
 +| Lion 10.7.5 ​      | Yes | No  | Teresa Colucci - teresacolu12@att.net | Yes | US High School Maths Teacher |
 +| Snow Leopard 10.6 | Yes | Yes | Me                                    | Yes | |
 +| El Capitan 10.11 and Mavericks 10.9.5 | ? | ? | Rod Jacka - rod@panalysis.com | Yes | Managing Director Panalysis Pty Ltd Sydney Can COMPILE for me. |
 +| Maverick 10.10.5 | ? | ? | Brian Francis - bfrancis9898@gmail.com | Yes | on both Macbook Pro and Macbook Air |
proj/macdev.1426384050.txt.gz · Last modified: 2015/03/14 21:47 by admin