Skip to content

Instantly share code, notes, and snippets.

@marnen

marnen/bin-files Secret

Last active January 11, 2020 06:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marnen/137b056d95b1c8400af8f823dced54f0 to your computer and use it in GitHub Desktop.
Save marnen/137b056d95b1c8400af8f823dced54f0 to your computer and use it in GitHub Desktop.
Files needed to go in Lilypond 2.19 .app bundle
# ls -1 /Applications/LilyPond\ 2.19.app/Contents/Resources/bin
# Files that need to go into the bin directory of the app bundle
abc2ly
convert-ly
dfont2res
eps2eps
etf2ly
fc-cache
fc-cat
fc-list
fc-match
flex
fondu
frombin
gapplication
gdbus
gdbus-codegen
gio-querymodules
glib-compile-resources
glib-compile-schemas
glib-genmarshal
gobject-query
gresource
gs
gsettings
gsx
gtester
gtester-report
guile
guile-snarf
guile-tools
hb-ot-shape-closure
hb-shape
lilymidi
lilypond
lilypond-book
lilypond-invoke-editor
lilysong
lprsetup.sh
lumper
midi2ly
musicxml2ly
pango-view
pdf2dsc
pdf2ps
pfbtopfa
pphs
ps2ascii
ps2epsi
ps2pdf
ps2pdf12
ps2pdf13
ps2pdf14
ps2pdfwr
ps2ps
ps2ps2
recode-sr-latin
setfondname
showfond
tobin
ufond
abc2ly
convert-ly
dfont2res
eps2eps
etf2ly
fc-cache
fc-cat
fc-list
fc-match
flex
fondu
frombin
gapplication
gdbus
gdbus-codegen
gio-querymodules
glib-compile-resources
glib-compile-schemas
glib-genmarshal
gobject-query
gresource
gsc
gsettings
gsx
gtester
gtester-report
guile18
guile18-snarf
guile18-tools
hb-ot-shape-closure
hb-shape
lilymidi
lilypond-book
lilypond-invoke-editor
lilysong
lprsetup.sh
lumper
midi2ly
musicxml2ly
pango-view
pdf2dsc
pdf2ps
pfbtopfa
pphs
ps2ascii
ps2epsi
ps2pdf
ps2pdf12
ps2pdf13
ps2pdf14
ps2pdfwr
ps2ps
ps2ps2
recode-sr-latin
setfondname
showfond
tobin
ufond
prependdir GS_FONTPATH=$INSTALLER_PREFIX/share/ghostscript/9.50/fonts
prependdir GS_FONTPATH=$INSTALLER_PREFIX/share/ghostscript/fonts
prependdir GS_LIB=$INSTALLER_PREFIX/share/ghostscript/9.50/Resource
prependdir GS_LIB=$INSTALLER_PREFIX/share/ghostscript/9.50/Resource/Init
#!/bin/sh
realpath() { # adapted from https://stackoverflow.com/a/18443300
ourpwd=$PWD
cd "$(dirname "$1")"
LINK=$(readlink "$(basename "$1")")
while [ "$LINK" ]; do
cd "$(dirname "$LINK")"
new_base=$(basename "$LINK")
LINK=$(readlink "$new_base")
done
REALPATH="$PWD/${new_base}"
cd "$ourpwd"
echo "$REALPATH"
}
LILYPOND_PATH=$(realpath $0)
GUILE_WARN_DEPRECATED="no"
LTDL_LIBRARY_PATH="${LILYPOND_PATH}/../lib:${LTDL_LIBRARY_PATH}"
export GUILE_WARN_DEPRECATED LTDL_LIBRARY_PATH
exec ${LILYPOND_PATH}/../libexec/lilypond-bin "$@"
bash-completion
emacs
fontconfig
gdb
ghostscript
glib-2.0
guile
lilypond
locale
xml
# diff -ur ~/Downloads/LilyPond.app /Applications/LilyPond\ 2.19.app
Only in /Users/marnen/Downloads/LilyPond.app/Contents/Frameworks/Python.framework: Python
Only in /Users/marnen/Downloads/LilyPond.app/Contents/Frameworks/Python.framework: Resources
Only in /Applications/LilyPond 2.19.app/Contents/Frameworks/Python.framework/Versions: 2.6
Only in /Users/marnen/Downloads/LilyPond.app/Contents/Frameworks/Python.framework/Versions: 2.7
Only in /Users/marnen/Downloads/LilyPond.app/Contents/Frameworks/Python.framework/Versions: Current
Only in /Users/marnen/Downloads/LilyPond.app/Contents/Frameworks: libbz2.1.0.8.dylib
Only in /Users/marnen/Downloads/LilyPond.app/Contents/Frameworks: libbz2.1.0.dylib
Only in /Users/marnen/Downloads/LilyPond.app/Contents/Frameworks: libcrypto.1.1.dylib
Only in /Users/marnen/Downloads/LilyPond.app/Contents/Frameworks: libexpat.1.6.11.dylib
Only in /Users/marnen/Downloads/LilyPond.app/Contents/Frameworks: libexpat.1.dylib
Only in /Users/marnen/Downloads/LilyPond.app/Contents/Frameworks: libffi.6.dylib
Only in /Users/marnen/Downloads/LilyPond.app/Contents/Frameworks: libiconv.2.dylib
Only in /Users/marnen/Downloads/LilyPond.app/Contents/Frameworks: libintl.8.dylib
Only in /Users/marnen/Downloads/LilyPond.app/Contents/Frameworks: libssl.1.1.dylib
Only in /Users/marnen/Downloads/LilyPond.app/Contents/Frameworks: libz.1.2.11.dylib
Only in /Users/marnen/Downloads/LilyPond.app/Contents/Frameworks: libz.1.dylib
diff -ur /Users/marnen/Downloads/LilyPond.app/Contents/Info.plist /Applications/LilyPond 2.19.app/Contents/Info.plist
--- /Users/marnen/Downloads/LilyPond.app/Contents/Info.plist 2020-01-08 13:19:05.000000000 -0500
+++ /Applications/LilyPond 2.19.app/Contents/Info.plist 2017-05-20 18:13:19.000000000 -0400
@@ -1,5 +1,5 @@
<?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">
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
@@ -34,7 +34,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
- <string>2.15.22-1
+ <string>2.19.61-1
</string>
<key>CFBundleSignature</key>
<string>????</string>
@@ -54,7 +54,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
- <string>Build from 08-01-2020 18:18
+ <string>Build from Sat May 20 23:13:18 2017
</string>
<key>LSHasLocalizedDisplayName</key>
<false/>
@@ -80,37 +80,33 @@
<false/>
<key>argv_emulation</key>
<false/>
- <key>emulate_shell_environment</key>
- <false/>
<key>no_chdir</key>
<false/>
+ <key>optimize</key>
+ <integer>0</integer>
<key>prefer_ppc</key>
<false/>
<key>site_packages</key>
<false/>
- <key>use_faulthandler</key>
- <false/>
<key>use_pythonpath</key>
<false/>
- <key>verbose</key>
- <false/>
</dict>
<key>PyResourcePackages</key>
<array>
</array>
<key>PyRuntimeLocations</key>
<array>
- <string>@executable_path/../Frameworks/Python.framework/Versions/2.7/Python</string>
+ <string>@executable_path/../Frameworks/Python.framework/Versions/2.6/Python</string>
</array>
<key>PythonInfoDict</key>
<dict>
<key>PythonExecutable</key>
- <string>/Users/marnen/lilypad/macosx/venv/bin/python</string>
+ <string>/Library/Frameworks/Python.framework/Versions/2.6/Resources/Python.app/Contents/MacOS/Python</string>
<key>PythonLongVersion</key>
- <string>2.7.17 (default, Oct 21 2019, 05:03:22)
-[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)]</string>
+ <string>2.6.6 (r266:84374, Aug 31 2010, 11:00:51)
+[GCC 4.0.1 (Apple Inc. build 5493)]</string>
<key>PythonShortVersion</key>
- <string>2.7</string>
+ <string>2.6</string>
<key>py2app</key>
<dict>
<key>alias</key>
@@ -118,7 +114,7 @@
<key>template</key>
<string>app</string>
<key>version</key>
- <string>0.19</string>
+ <string>0.5.3</string>
</dict>
</dict>
</dict>
Only in /Applications/LilyPond 2.19.app/Contents: Info.plist~
Binary files /Users/marnen/Downloads/LilyPond.app/Contents/MacOS/LilyPond and /Applications/LilyPond 2.19.app/Contents/MacOS/LilyPond differ
Binary files /Users/marnen/Downloads/LilyPond.app/Contents/MacOS/python and /Applications/LilyPond 2.19.app/Contents/MacOS/python differ
diff -ur /Users/marnen/Downloads/LilyPond.app/Contents/Resources/LilyPond.py /Applications/LilyPond 2.19.app/Contents/Resources/LilyPond.py
--- /Users/marnen/Downloads/LilyPond.app/Contents/Resources/LilyPond.py 2020-01-08 13:19:05.000000000 -0500
+++ /Applications/LilyPond 2.19.app/Contents/Resources/LilyPond.py 2017-05-20 18:13:19.000000000 -0400
@@ -106,7 +106,6 @@
firstStart = False
- @objc.python_method
def readFromUTF8(self, path):
f = file(path)
text = unicode(f.read(), "utf8")
@@ -193,7 +192,6 @@
wc.setWindowTitle_ ('LilyPond -- ' + self.fileName())
wc.runProcessWithCallback (call, self.open_pdf)
- @objc.python_method
def open_pdf (self, data):
pdf_file = os.path.splitext (self.fileName())[0] + '.pdf'
if os.path.exists (pdf_file):
diff -ur /Users/marnen/Downloads/LilyPond.app/Contents/Resources/ProcessLog.py /Applications/LilyPond 2.19.app/Contents/Resources/ProcessLog.py
--- /Users/marnen/Downloads/LilyPond.app/Contents/Resources/ProcessLog.py 2020-01-08 13:19:05.000000000 -0500
+++ /Applications/LilyPond 2.19.app/Contents/Resources/ProcessLog.py 2017-05-20 18:13:19.000000000 -0400
@@ -21,7 +21,6 @@
return self
# the actual base class is NSObject
- @objc.python_method
def setProcess (self, process):
self.out_str = ''
if self.isLive():
@@ -107,8 +106,7 @@
if self.processLog.isLive ():
self.processLog.killProcess ()
# rest is handled by timer.
-
- @objc.python_method
+
def runProcessWithCallback (self, process, finish_callback):
self.finish_callback = finish_callback
self.processLog.setProcess (process)
@@ -149,7 +147,6 @@
range.length = ts_len
tv.replaceCharactersInRange_withString_ (range, '')
- @objc.python_method
def addText (self, str):
tv = self.textView
ts_len = tv.textStorage().length ()
Only in /Applications/LilyPond 2.19.app/Contents/Resources: ProcessLog.pyc
diff -ur /Users/marnen/Downloads/LilyPond.app/Contents/Resources/Welcome-to-LilyPond-MacOS.ly /Applications/LilyPond 2.19.app/Contents/Resources/Welcome-to-LilyPond-MacOS.ly
--- /Users/marnen/Downloads/LilyPond.app/Contents/Resources/Welcome-to-LilyPond-MacOS.ly 2020-01-08 13:19:05.000000000 -0500
+++ /Applications/LilyPond 2.19.app/Contents/Resources/Welcome-to-LilyPond-MacOS.ly 2017-05-20 18:13:19.000000000 -0400
@@ -32,4 +32,4 @@
}
-\version "2.12.0" % necessary for upgrading to future LilyPond versions.
+\version "2.19.61" % necessary for upgrading to future LilyPond versions.
Only in /Applications/LilyPond 2.19.app/Contents/Resources: Welcome-to-LilyPond-MacOS.ly~
diff -ur /Users/marnen/Downloads/LilyPond.app/Contents/Resources/__boot__.py /Applications/LilyPond 2.19.app/Contents/Resources/__boot__.py
--- /Users/marnen/Downloads/LilyPond.app/Contents/Resources/__boot__.py 2020-01-08 13:19:05.000000000 -0500
+++ /Applications/LilyPond 2.19.app/Contents/Resources/__boot__.py 2017-05-20 18:13:19.000000000 -0400
@@ -1,98 +1,31 @@
-def _reset_sys_path():
- # Clear generic sys.path[0]
- import sys
- import os
-
- resources = os.environ['RESOURCEPATH']
- while sys.path[0] == resources:
- del sys.path[0]
-
-
-_reset_sys_path()
-
-
def _chdir_resource():
import os
os.chdir(os.environ['RESOURCEPATH'])
-
-
_chdir_resource()
def _disable_linecache():
import linecache
-
def fake_getline(*args, **kwargs):
return ''
-
linecache.orig_getline = linecache.getline
linecache.getline = fake_getline
-
-
_disable_linecache()
-import re
-import sys
-
-cookie_re = re.compile(b"coding[:=]\s*([-\w.]+)")
-if sys.version_info[0] == 2:
- default_encoding = 'ascii'
-else:
- default_encoding = 'utf-8'
-
-
-def guess_encoding(fp):
- for i in range(2):
- ln = fp.readline()
-
- m = cookie_re.search(ln)
- if m is not None:
- return m.group(1).decode('ascii')
-
- return default_encoding
-
-
-def _run():
+def _run(*scripts):
global __file__
- import os
- import site # noqa: F401
+ import os, sys, site
sys.frozen = 'macosx_app'
base = os.environ['RESOURCEPATH']
-
- argv0 = os.path.basename(os.environ['ARGVZERO'])
- script = SCRIPT_MAP.get(argv0, DEFAULT_SCRIPT) # noqa: F821
-
- path = os.path.join(base, script)
- sys.argv[0] = __file__ = path
- if sys.version_info[0] == 2:
- with open(path, 'rU') as fp:
- source = fp.read() + "\n"
- else:
- with open(path, 'rb') as fp:
- encoding = guess_encoding(fp)
-
- with open(path, 'r', encoding=encoding) as fp:
- source = fp.read() + '\n'
-
- BOM = b'\xef\xbb\xbf'.decode('utf-8')
- if source.startswith(BOM):
- source = source[1:]
-
- exec(compile(source, path, 'exec'), globals(), globals())
-
-
-def _setup_ctypes():
- from ctypes.macholib import dyld
- import os
- frameworks = os.path.join(os.environ['RESOURCEPATH'], '..', 'Frameworks')
- dyld.DEFAULT_FRAMEWORK_FALLBACK.insert(0, frameworks)
- dyld.DEFAULT_LIBRARY_FALLBACK.insert(0, frameworks)
-
-
-_setup_ctypes()
+ site.addsitedir(base)
+ site.addsitedir(os.path.join(base, 'Python', 'site-packages'))
+ if not scripts:
+ import __main__
+ for script in scripts:
+ path = os.path.join(base, script)
+ sys.argv[0] = __file__ = path
+ execfile(path, globals(), globals())
-DEFAULT_SCRIPT='LilyPond.py'
-SCRIPT_MAP={}
-_run()
+_run('LilyPond.py')
Only in /Applications/LilyPond 2.19.app/Contents/Resources: bin
Only in /Applications/LilyPond 2.19.app/Contents/Resources: etc
Only in /Applications/LilyPond 2.19.app/Contents/Resources/include: python2.6
Only in /Users/marnen/Downloads/LilyPond.app/Contents/Resources/include: python2.7
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: charset.alias
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: ghostscript
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: gio
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libasprintf.0.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libasprintf.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libasprintf.la
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libexpat.1.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libexpat.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libexpat.la
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libffi.6.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libffi.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libffi.la
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libfontconfig.1.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libfontconfig.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libfontconfig.la
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libfreetype.6.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libfreetype.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libfreetype.la
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgcc_s.1.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgettextlib-0.15.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgettextlib.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgettextlib.la
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgettextpo.0.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgettextpo.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgettextpo.la
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgettextsrc-0.15.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgettextsrc.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgettextsrc.la
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgio-2.0.0.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgio-2.0.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgio-2.0.la
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libglib-2.0.0.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libglib-2.0.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libglib-2.0.la
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgmodule-2.0.0.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgmodule-2.0.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgmodule-2.0.la
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgmp.10.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgmp.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgmp.la
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgobject-2.0.0.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgobject-2.0.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgobject-2.0.la
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgs.9.20.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgs.9.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgs.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgthread-2.0.0.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgthread-2.0.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libgthread-2.0.la
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libguile-srfi-srfi-1-v-3.3.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libguile-srfi-srfi-1-v-3.3.so
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libguile-srfi-srfi-1-v-3.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libguile-srfi-srfi-1-v-3.la
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libguile-srfi-srfi-1-v-3.so
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libguile-srfi-srfi-13-14-v-3.3.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libguile-srfi-srfi-13-14-v-3.3.so
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libguile-srfi-srfi-13-14-v-3.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libguile-srfi-srfi-13-14-v-3.la
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libguile-srfi-srfi-13-14-v-3.so
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libguile-srfi-srfi-4-v-3.3.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libguile-srfi-srfi-4-v-3.3.so
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libguile-srfi-srfi-4-v-3.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libguile-srfi-srfi-4-v-3.la
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libguile-srfi-srfi-4-v-3.so
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libguile-srfi-srfi-60-v-2.2.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libguile-srfi-srfi-60-v-2.2.so
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libguile-srfi-srfi-60-v-2.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libguile-srfi-srfi-60-v-2.la
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libguile-srfi-srfi-60-v-2.so
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libguile.17.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libguile.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libguile.la
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libharfbuzz.0.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libharfbuzz.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libharfbuzz.la
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libintl.8.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libintl.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libintl.la
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libjpeg.62.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libjpeg.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libjpeg.la
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libltdl.7.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libltdl.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libltdl.la
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libpango-1.0.0.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libpango-1.0.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libpango-1.0.la
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libpangoft2-1.0.0.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libpangoft2-1.0.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libpangoft2-1.0.la
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libstdc++.6.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libtiff.5.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libtiff.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libtiffxx.5.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: libtiffxx.dylib
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: lilypond
Only in /Applications/LilyPond 2.19.app/Contents/Resources/lib: python2.6
Only in /Users/marnen/Downloads/LilyPond.app/Contents/Resources/lib: python2.7
Only in /Applications/LilyPond 2.19.app/Contents/Resources: license
Only in /Applications/LilyPond 2.19.app/Contents/Resources: share
diff -ur /Users/marnen/Downloads/LilyPond.app/Contents/Resources/shutil.py /Applications/LilyPond 2.19.app/Contents/Resources/shutil.py
--- /Users/marnen/Downloads/LilyPond.app/Contents/Resources/shutil.py 2020-01-08 13:19:05.000000000 -0500
+++ /Applications/LilyPond 2.19.app/Contents/Resources/shutil.py 2017-05-20 18:13:19.000000000 -0400
@@ -1,9 +1,4 @@
-# -*- coding: utf-8 -*-
-#
-# Copyright (C) 2012 The Python Software Foundation.
-# See LICENSE.txt and CONTRIBUTORS.txt.
-#
-"""Utility functions for copying and archiving files and directory trees.
+"""Utility functions for copying files and directory trees.
XXX The functions here don't copy the resource fork or other metadata on Mac.
@@ -14,51 +9,14 @@
import stat
from os.path import abspath
import fnmatch
-import collections
import errno
-from . import tarfile
-try:
- import bz2
- _BZ2_SUPPORTED = True
-except ImportError:
- _BZ2_SUPPORTED = False
-
-try:
- from pwd import getpwnam
-except ImportError:
- getpwnam = None
-
-try:
- from grp import getgrnam
-except ImportError:
- getgrnam = None
-
-__all__ = ["copyfileobj", "copyfile", "copymode", "copystat", "copy", "copy2",
- "copytree", "move", "rmtree", "Error", "SpecialFileError",
- "ExecError", "make_archive", "get_archive_formats",
- "register_archive_format", "unregister_archive_format",
- "get_unpack_formats", "register_unpack_format",
- "unregister_unpack_format", "unpack_archive", "ignore_patterns"]
+__all__ = ["copyfileobj","copyfile","copymode","copystat","copy","copy2",
+ "copytree","move","rmtree","Error"]
class Error(EnvironmentError):
pass
-class SpecialFileError(EnvironmentError):
- """Raised when trying to do a kind of operation (e.g. copying) which is
- not supported on a special file (e.g. a named pipe)"""
-
-class ExecError(EnvironmentError):
- """Raised when a command could not be executed"""
-
-class ReadError(EnvironmentError):
- """Raised when an archive cannot be read"""
-
-class RegistryError(Exception):
- """Raised when a registry operation with the archiving
- and unpacking registries fails"""
-
-
try:
WindowsError
except NameError:
@@ -74,7 +32,7 @@
def _samefile(src, dst):
# Macintosh, Unix.
- if hasattr(os.path, 'samefile'):
+ if hasattr(os.path,'samefile'):
try:
return os.path.samefile(src, dst)
except OSError:
@@ -89,17 +47,6 @@
if _samefile(src, dst):
raise Error("`%s` and `%s` are the same file" % (src, dst))
- for fn in [src, dst]:
- try:
- st = os.stat(fn)
- except OSError:
- # File most likely does not exist
- pass
- else:
- # XXX What about other special files? (sockets, devices...)
- if stat.S_ISFIFO(st.st_mode):
- raise SpecialFileError("`%s` is a named pipe" % fn)
-
with open(src, 'rb') as fsrc:
with open(dst, 'wb') as fdst:
copyfileobj(fsrc, fdst)
@@ -122,9 +69,8 @@
if hasattr(os, 'chflags') and hasattr(st, 'st_flags'):
try:
os.chflags(dst, st.st_flags)
- except OSError as why:
- if (not hasattr(errno, 'EOPNOTSUPP') or
- why.errno != errno.EOPNOTSUPP):
+ except OSError, why:
+ if not hasattr(errno, 'EOPNOTSUPP') or why.errno != errno.EOPNOTSUPP:
raise
def copy(src, dst):
@@ -161,9 +107,8 @@
return set(ignored_names)
return _ignore_patterns
-def copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2,
- ignore_dangling_symlinks=False):
- """Recursively copy a directory tree.
+def copytree(src, dst, symlinks=False, ignore=None):
+ """Recursively copy a directory tree using copy2().
The destination directory must not already exist.
If exception(s) occur, an Error is raised with a list of reasons.
@@ -171,13 +116,7 @@
If the optional symlinks flag is true, symbolic links in the
source tree result in symbolic links in the destination tree; if
it is false, the contents of the files pointed to by symbolic
- links are copied. If the file pointed by the symlink doesn't
- exist, an exception will be added in the list of errors raised in
- an Error exception at the end of the copy process.
-
- You can set the optional ignore_dangling_symlinks flag to true if you
- want to silence this exception. Notice that this has no effect on
- platforms that don't support os.symlink.
+ links are copied.
The optional ignore argument is a callable. If given, it
is called with the `src` parameter, which is the directory
@@ -191,10 +130,7 @@
list of names relative to the `src` directory that should
not be copied.
- The optional copy_function argument is a callable that will be used
- to copy each file. It will be called with the source path and the
- destination path as arguments. By default, copy2() is used, but any
- function that supports the same signature (like copy()) can be used.
+ XXX Consider this example code rather than the ultimate tool.
"""
names = os.listdir(src)
@@ -211,37 +147,30 @@
srcname = os.path.join(src, name)
dstname = os.path.join(dst, name)
try:
- if os.path.islink(srcname):
+ if symlinks and os.path.islink(srcname):
linkto = os.readlink(srcname)
- if symlinks:
- os.symlink(linkto, dstname)
- else:
- # ignore dangling symlink if the flag is on
- if not os.path.exists(linkto) and ignore_dangling_symlinks:
- continue
- # otherwise let the copy occurs. copy2 will raise an error
- copy_function(srcname, dstname)
+ os.symlink(linkto, dstname)
elif os.path.isdir(srcname):
- copytree(srcname, dstname, symlinks, ignore, copy_function)
+ copytree(srcname, dstname, symlinks, ignore)
else:
- # Will raise a SpecialFileError for unsupported file types
- copy_function(srcname, dstname)
+ copy2(srcname, dstname)
+ # XXX What about devices, sockets etc.?
+ except (IOError, os.error), why:
+ errors.append((srcname, dstname, str(why)))
# catch the Error from the recursive copytree so that we can
# continue with other files
- except Error as err:
+ except Error, err:
errors.extend(err.args[0])
- except EnvironmentError as why:
- errors.append((srcname, dstname, str(why)))
try:
copystat(src, dst)
- except OSError as why:
+ except OSError, why:
if WindowsError is not None and isinstance(why, WindowsError):
# Copying file access times may fail on Windows
pass
else:
errors.extend((src, dst, str(why)))
if errors:
- raise Error(errors)
+ raise Error, errors
def rmtree(path, ignore_errors=False, onerror=None):
"""Recursively delete a directory tree.
@@ -271,7 +200,7 @@
names = []
try:
names = os.listdir(path)
- except os.error:
+ except os.error, err:
onerror(os.listdir, path, sys.exc_info())
for name in names:
fullname = os.path.join(path, name)
@@ -284,7 +213,7 @@
else:
try:
os.remove(fullname)
- except os.error:
+ except os.error, err:
onerror(os.remove, fullname, sys.exc_info())
try:
os.rmdir(path)
@@ -316,28 +245,22 @@
"""
real_dst = dst
if os.path.isdir(dst):
- if _samefile(src, dst):
- # We might be on a case insensitive filesystem,
- # perform the rename anyway.
- os.rename(src, dst)
- return
-
real_dst = os.path.join(dst, _basename(src))
if os.path.exists(real_dst):
- raise Error("Destination path '%s' already exists" % real_dst)
+ raise Error, "Destination path '%s' already exists" % real_dst
try:
os.rename(src, real_dst)
except OSError:
if os.path.isdir(src):
- if _destinsrc(src, dst):
- raise Error("Cannot move a directory '%s' into itself '%s'." % (src, dst))
+ if destinsrc(src, dst):
+ raise Error, "Cannot move a directory '%s' into itself '%s'." % (src, dst)
copytree(src, real_dst, symlinks=True)
rmtree(src)
else:
copy2(src, real_dst)
os.unlink(src)
-def _destinsrc(src, dst):
+def destinsrc(src, dst):
src = abspath(src)
dst = abspath(dst)
if not src.endswith(os.path.sep):
@@ -345,417 +268,3 @@
if not dst.endswith(os.path.sep):
dst += os.path.sep
return dst.startswith(src)
-
-def _get_gid(name):
- """Returns a gid, given a group name."""
- if getgrnam is None or name is None:
- return None
- try:
- result = getgrnam(name)
- except KeyError:
- result = None
- if result is not None:
- return result[2]
- return None
-
-def _get_uid(name):
- """Returns an uid, given a user name."""
- if getpwnam is None or name is None:
- return None
- try:
- result = getpwnam(name)
- except KeyError:
- result = None
- if result is not None:
- return result[2]
- return None
-
-def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0,
- owner=None, group=None, logger=None):
- """Create a (possibly compressed) tar file from all the files under
- 'base_dir'.
-
- 'compress' must be "gzip" (the default), "bzip2", or None.
-
- 'owner' and 'group' can be used to define an owner and a group for the
- archive that is being built. If not provided, the current owner and group
- will be used.
-
- The output tar file will be named 'base_name' + ".tar", possibly plus
- the appropriate compression extension (".gz", or ".bz2").
-
- Returns the output filename.
- """
- tar_compression = {'gzip': 'gz', None: ''}
- compress_ext = {'gzip': '.gz'}
-
- if _BZ2_SUPPORTED:
- tar_compression['bzip2'] = 'bz2'
- compress_ext['bzip2'] = '.bz2'
-
- # flags for compression program, each element of list will be an argument
- if compress is not None and compress not in compress_ext:
- raise ValueError("bad value for 'compress', or compression format not "
- "supported : {0}".format(compress))
-
- archive_name = base_name + '.tar' + compress_ext.get(compress, '')
- archive_dir = os.path.dirname(archive_name)
-
- if not os.path.exists(archive_dir):
- if logger is not None:
- logger.info("creating %s", archive_dir)
- if not dry_run:
- os.makedirs(archive_dir)
-
- # creating the tarball
- if logger is not None:
- logger.info('Creating tar archive')
-
- uid = _get_uid(owner)
- gid = _get_gid(group)
-
- def _set_uid_gid(tarinfo):
- if gid is not None:
- tarinfo.gid = gid
- tarinfo.gname = group
- if uid is not None:
- tarinfo.uid = uid
- tarinfo.uname = owner
- return tarinfo
-
- if not dry_run:
- tar = tarfile.open(archive_name, 'w|%s' % tar_compression[compress])
- try:
- tar.add(base_dir, filter=_set_uid_gid)
- finally:
- tar.close()
-
- return archive_name
-
-def _call_external_zip(base_dir, zip_filename, verbose=False, dry_run=False):
- # XXX see if we want to keep an external call here
- if verbose:
- zipoptions = "-r"
- else:
- zipoptions = "-rq"
- from distutils.errors import DistutilsExecError
- from distutils.spawn import spawn
- try:
- spawn(["zip", zipoptions, zip_filename, base_dir], dry_run=dry_run)
- except DistutilsExecError:
- # XXX really should distinguish between "couldn't find
- # external 'zip' command" and "zip failed".
- raise ExecError("unable to create zip file '%s': "
- "could neither import the 'zipfile' module nor "
- "find a standalone zip utility") % zip_filename
-
-def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None):
- """Create a zip file from all the files under 'base_dir'.
-
- The output zip file will be named 'base_name' + ".zip". Uses either the
- "zipfile" Python module (if available) or the InfoZIP "zip" utility
- (if installed and found on the default search path). If neither tool is
- available, raises ExecError. Returns the name of the output zip
- file.
- """
- zip_filename = base_name + ".zip"
- archive_dir = os.path.dirname(base_name)
-
- if not os.path.exists(archive_dir):
- if logger is not None:
- logger.info("creating %s", archive_dir)
- if not dry_run:
- os.makedirs(archive_dir)
-
- # If zipfile module is not available, try spawning an external 'zip'
- # command.
- try:
- import zipfile
- except ImportError:
- zipfile = None
-
- if zipfile is None:
- _call_external_zip(base_dir, zip_filename, verbose, dry_run)
- else:
- if logger is not None:
- logger.info("creating '%s' and adding '%s' to it",
- zip_filename, base_dir)
-
- if not dry_run:
- zip = zipfile.ZipFile(zip_filename, "w",
- compression=zipfile.ZIP_DEFLATED)
-
- for dirpath, dirnames, filenames in os.walk(base_dir):
- for name in filenames:
- path = os.path.normpath(os.path.join(dirpath, name))
- if os.path.isfile(path):
- zip.write(path, path)
- if logger is not None:
- logger.info("adding '%s'", path)
- zip.close()
-
- return zip_filename
-
-_ARCHIVE_FORMATS = {
- 'gztar': (_make_tarball, [('compress', 'gzip')], "gzip'ed tar-file"),
- 'bztar': (_make_tarball, [('compress', 'bzip2')], "bzip2'ed tar-file"),
- 'tar': (_make_tarball, [('compress', None)], "uncompressed tar file"),
- 'zip': (_make_zipfile, [], "ZIP file"),
- }
-
-if _BZ2_SUPPORTED:
- _ARCHIVE_FORMATS['bztar'] = (_make_tarball, [('compress', 'bzip2')],
- "bzip2'ed tar-file")
-
-def get_archive_formats():
- """Returns a list of supported formats for archiving and unarchiving.
-
- Each element of the returned sequence is a tuple (name, description)
- """
- formats = [(name, registry[2]) for name, registry in
- _ARCHIVE_FORMATS.items()]
- formats.sort()
- return formats
-
-def register_archive_format(name, function, extra_args=None, description=''):
- """Registers an archive format.
-
- name is the name of the format. function is the callable that will be
- used to create archives. If provided, extra_args is a sequence of
- (name, value) tuples that will be passed as arguments to the callable.
- description can be provided to describe the format, and will be returned
- by the get_archive_formats() function.
- """
- if extra_args is None:
- extra_args = []
- if not isinstance(function, collections.Callable):
- raise TypeError('The %s object is not callable' % function)
- if not isinstance(extra_args, (tuple, list)):
- raise TypeError('extra_args needs to be a sequence')
- for element in extra_args:
- if not isinstance(element, (tuple, list)) or len(element) !=2:
- raise TypeError('extra_args elements are : (arg_name, value)')
-
- _ARCHIVE_FORMATS[name] = (function, extra_args, description)
-
-def unregister_archive_format(name):
- del _ARCHIVE_FORMATS[name]
-
-def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0,
- dry_run=0, owner=None, group=None, logger=None):
- """Create an archive file (eg. zip or tar).
-
- 'base_name' is the name of the file to create, minus any format-specific
- extension; 'format' is the archive format: one of "zip", "tar", "bztar"
- or "gztar".
-
- 'root_dir' is a directory that will be the root directory of the
- archive; ie. we typically chdir into 'root_dir' before creating the
- archive. 'base_dir' is the directory where we start archiving from;
- ie. 'base_dir' will be the common prefix of all files and
- directories in the archive. 'root_dir' and 'base_dir' both default
- to the current directory. Returns the name of the archive file.
-
- 'owner' and 'group' are used when creating a tar archive. By default,
- uses the current owner and group.
- """
- save_cwd = os.getcwd()
- if root_dir is not None:
- if logger is not None:
- logger.debug("changing into '%s'", root_dir)
- base_name = os.path.abspath(base_name)
- if not dry_run:
- os.chdir(root_dir)
-
- if base_dir is None:
- base_dir = os.curdir
-
- kwargs = {'dry_run': dry_run, 'logger': logger}
-
- try:
- format_info = _ARCHIVE_FORMATS[format]
- except KeyError:
- raise ValueError("unknown archive format '%s'" % format)
-
- func = format_info[0]
- for arg, val in format_info[1]:
- kwargs[arg] = val
-
- if format != 'zip':
- kwargs['owner'] = owner
- kwargs['group'] = group
-
- try:
- filename = func(base_name, base_dir, **kwargs)
- finally:
- if root_dir is not None:
- if logger is not None:
- logger.debug("changing back to '%s'", save_cwd)
- os.chdir(save_cwd)
-
- return filename
-
-
-def get_unpack_formats():
- """Returns a list of supported formats for unpacking.
-
- Each element of the returned sequence is a tuple
- (name, extensions, description)
- """
- formats = [(name, info[0], info[3]) for name, info in
- _UNPACK_FORMATS.items()]
- formats.sort()
- return formats
-
-def _check_unpack_options(extensions, function, extra_args):
- """Checks what gets registered as an unpacker."""
- # first make sure no other unpacker is registered for this extension
- existing_extensions = {}
- for name, info in _UNPACK_FORMATS.items():
- for ext in info[0]:
- existing_extensions[ext] = name
-
- for extension in extensions:
- if extension in existing_extensions:
- msg = '%s is already registered for "%s"'
- raise RegistryError(msg % (extension,
- existing_extensions[extension]))
-
- if not isinstance(function, collections.Callable):
- raise TypeError('The registered function must be a callable')
-
-
-def register_unpack_format(name, extensions, function, extra_args=None,
- description=''):
- """Registers an unpack format.
-
- `name` is the name of the format. `extensions` is a list of extensions
- corresponding to the format.
-
- `function` is the callable that will be
- used to unpack archives. The callable will receive archives to unpack.
- If it's unable to handle an archive, it needs to raise a ReadError
- exception.
-
- If provided, `extra_args` is a sequence of
- (name, value) tuples that will be passed as arguments to the callable.
- description can be provided to describe the format, and will be returned
- by the get_unpack_formats() function.
- """
- if extra_args is None:
- extra_args = []
- _check_unpack_options(extensions, function, extra_args)
- _UNPACK_FORMATS[name] = extensions, function, extra_args, description
-
-def unregister_unpack_format(name):
- """Removes the pack format from the registry."""
- del _UNPACK_FORMATS[name]
-
-def _ensure_directory(path):
- """Ensure that the parent directory of `path` exists"""
- dirname = os.path.dirname(path)
- if not os.path.isdir(dirname):
- os.makedirs(dirname)
-
-def _unpack_zipfile(filename, extract_dir):
- """Unpack zip `filename` to `extract_dir`
- """
- try:
- import zipfile
- except ImportError:
- raise ReadError('zlib not supported, cannot unpack this archive.')
-
- if not zipfile.is_zipfile(filename):
- raise ReadError("%s is not a zip file" % filename)
-
- zip = zipfile.ZipFile(filename)
- try:
- for info in zip.infolist():
- name = info.filename
-
- # don't extract absolute paths or ones with .. in them
- if name.startswith('/') or '..' in name:
- continue
-
- target = os.path.join(extract_dir, *name.split('/'))
- if not target:
- continue
-
- _ensure_directory(target)
- if not name.endswith('/'):
- # file
- data = zip.read(info.filename)
- f = open(target, 'wb')
- try:
- f.write(data)
- finally:
- f.close()
- del data
- finally:
- zip.close()
-
-def _unpack_tarfile(filename, extract_dir):
- """Unpack tar/tar.gz/tar.bz2 `filename` to `extract_dir`
- """
- try:
- tarobj = tarfile.open(filename)
- except tarfile.TarError:
- raise ReadError(
- "%s is not a compressed or uncompressed tar file" % filename)
- try:
- tarobj.extractall(extract_dir)
- finally:
- tarobj.close()
-
-_UNPACK_FORMATS = {
- 'gztar': (['.tar.gz', '.tgz'], _unpack_tarfile, [], "gzip'ed tar-file"),
- 'tar': (['.tar'], _unpack_tarfile, [], "uncompressed tar file"),
- 'zip': (['.zip'], _unpack_zipfile, [], "ZIP file")
- }
-
-if _BZ2_SUPPORTED:
- _UNPACK_FORMATS['bztar'] = (['.bz2'], _unpack_tarfile, [],
- "bzip2'ed tar-file")
-
-def _find_unpack_format(filename):
- for name, info in _UNPACK_FORMATS.items():
- for extension in info[0]:
- if filename.endswith(extension):
- return name
- return None
-
-def unpack_archive(filename, extract_dir=None, format=None):
- """Unpack an archive.
-
- `filename` is the name of the archive.
-
- `extract_dir` is the name of the target directory, where the archive
- is unpacked. If not provided, the current working directory is used.
-
- `format` is the archive format: one of "zip", "tar", or "gztar". Or any
- other registered format. If not provided, unpack_archive will use the
- filename extension and see if an unpacker was registered for that
- extension.
-
- In case none is found, a ValueError is raised.
- """
- if extract_dir is None:
- extract_dir = os.getcwd()
-
- if format is not None:
- try:
- format_info = _UNPACK_FORMATS[format]
- except KeyError:
- raise ValueError("Unknown unpack format '{0}'".format(format))
-
- func = format_info[1]
- func(filename, extract_dir, **dict(format_info[2]))
- else:
- # we need to look at the registered unpackers supported extensions
- format = _find_unpack_format(filename)
- if format is None:
- raise ReadError("Unknown archive format '{0}'".format(filename))
-
- func = _UNPACK_FORMATS[format][1]
- kwargs = dict(_UNPACK_FORMATS[format][2])
- func(filename, extract_dir, **kwargs)
Only in /Applications/LilyPond 2.19.app/Contents/Resources: site.py
Binary files /Users/marnen/Downloads/LilyPond.app/Contents/Resources/site.pyc and /Applications/LilyPond 2.19.app/Contents/Resources/site.pyc differ
Only in /Applications/LilyPond 2.19.app/Contents/Resources: var

Build notes for LilyPad

I'm mostly following the build process in the README, but with Python 2.7.

Pip

First we need pip. I'm following the instructions at http://johnlaudun.org/20150512-installing-and-setting-pip-with-macports/ and using the py27-pip MacPorts package.

sudo port install py27-pip

For some reason this is reinstalling python27; perhaps there was an upgrade to the MacPorts package...

sudo port select --set python python27
sudo port select --set pip pip27

Now we have pip working.

Virtualenv

I'm installing virtualenv so that we don't have to mess with our Python global setup. Looks like it's available through MacPorts.

sudo port install py27-virtualenv
sudo port select --set virtualenv virtualenv27

Now we can set up a virtualenv: virtualenv venv

And activate it: source venv/bin/activate

Get pyobjc

For the moment, setup.py requires pyobjc==2.3.1, which isn't in PyPI. The README advises getting it from SVN (!): svn co http://svn.red-bean.com/pyobjc/tags/pyobjc-2.3.1/

But pip now has the ability to install a package from a repo, and Pyobjc now has a Mercurial repo: pip install 'hg+https://bitbucket.org/ronaldoussoren/pyobjc@pyobjc-2.3.1#egg=pyobjc'

This required installing Mercurial (which I did with the MacPorts mercurial package, but any method should work).

Unfortunately, it still didn't work because pip install expects a setup.py file in the module that wasn't actually there. So I'm reluctantly going with the method in the README, modified as follows for the current Python installation and current sed regex syntax:

svn co http://svn.red-bean.com/pyobjc/tags/pyobjc-2.3.1/
cd pyobjc-2.3.1
sed -E -i .bak -e 's*(/usr/bin/)?python2.5*python*' 02-develop-all.sh
./02-develop-all.sh # detached while this was in progress: compilation takes forever, or maybe it just hung
cd pyobjc
python setup.py develop

...except that that didn't work: pyobjc 2.3.1 hung on compilation (testFunctions (PyObjCTest.test_abaddressbookc.TestABAddressBookC) ...). So I'm trying the latest version. That worked, but created an app bundle that (on Mojave) gives an uninformative "LilyPond error" when opened. Following the advice at https://stackoverflow.com/questions/53524071/py2app-app-not-launching-just-asks-if-i-want-to-terminate-the-app-or-open-consol led me to see that I was getting a BadPrototypeError on many methods. Since those methods are only called from Python, not Obj-C, robertklep/quotefixformac#75 suggests that annotating them as @objc.python_method might be useful.

That did indeed work, and I committed that code. So really all I needed to do was MACOSX_DEPLOYMENT_TARGET=10.5 python setup.py --verbose py2app --icon=lilypond.icns, although it might help to do it outside the venv...

Installing LilyPond binaries into the bundle

There appears to be no automated way to figure out which Lilypond binaries are supposed to be in the bundle; even the README file just suggests copying them from an existing bundle. So I'm looking at the existing app bundle to find a list. More info is at https://gist.github.com/marnen/137b056d95b1c8400af8f823dced54f0.

Basically, within Contents/Resources, bin, etc, license, share, var, and possibly site.py need to be copied. There are also a bunch of files in lib that need to be copied, but I suspect dylibbundler will do that.

I'm putting a list of filenames to copy into extra-files; paths are relative to Contents/Resources. Then we'll have to figure out how to get these into the bundle.

bin

Most of these should be able to be copied from the MacPorts installation directory where I built Lilypond. Then we'll have to use file to figure out which ones are wrapper scripts (for example, MacPorts lilypond is a wrapper script for libexec/lilypond-bin, whereas the bundle expects the real binary). The downloaded bundle is in ~/32-bit-app so we can compare.

Some of the binaries come from the fondu port, which I had to install separately (port install fondu).

Once I installed Fondu and copied the MacPorts binaries over, here's what I used to run the diff on filetypes: diff -y --suppress-common-lines <(xargs <extra-files/bin echo 'cd ~/32-bit-app/LilyPond.app/Contents/Resources/bin && file' | sh) <(xargs <extra-files/bin echo 'cd dist/LilyPond.app/Contents/Resources/bin && file' | sh)

The significant parts of the diff (that is, removing lines where the difference is meaningless) are as follows:

gapplication:           Mach-O executable i386              |    gapplication:           cannot open `gapplication' (No such f
glib-genmarshal:        Mach-O executable i386              |    glib-genmarshal:        a /usr/bin/python script text executa
gs:                     Mach-O executable i386              |    gs:                     broken symbolic link to gsc
guile:                  Mach-O executable i386              |    guile:                  cannot open `guile' (No such file or
guile-snarf:            POSIX shell script text executable    |    guile-snarf:            cannot open `guile-snarf' (No such fi
guile-tools:            POSIX shell script text executable    |    guile-tools:            cannot open `guile-tools' (No such fi
lilypond:               Mach-O executable i386              |    lilypond:               POSIX shell script text executable

So:

  • gs is a symlink to gsc. We could either copy gsc as is or rename it so that no symlink is necessary.
  • lilypond is a wrapper script around ~/lilypond-bundle/libexec/lilypond-bin. It just sets some environment variables, so we were just replacing it with the bin itself. However, we need those environment variables set, so we need to keep the script. I tried @executable_path, but that won't work in a Unix script, so I'm using a solution based on https://stackoverflow.com/a/18443300.
  • gapplication doesn't exist and I'm not sure where we get it from.
  • glib-genmarshal is a Python script rather than a native executable, but seems to be complete in itself. I hope.
  • guile* is guile18* because of our MacPorts installation. We can copy them in with the new names.

These modifications are reflected in the script below.

etc and license

These are all text files, so we should just be able to copy them over from the official bundle for now. I'd like to find an authoritative source for them, though.

share

All text files and some .pyc. The .pyc are for Python 2.4, and we're using 2.7, but they should be automatically rebuilt as necessary, so I think we can just copy them over.

However, it looks like the naming of the files (at least as relates to Guile, which MacPorts calls guile18) isn't quite right, so we'll need to take the same approach we did with bin: list all the stuff in the bundle and copy it in from MacPorts.

var

Empty except for cache directories. We may need to create it, but probably not even that.

lib

Mostly dylibs, which can be populated by using https://github.com/auriamg/macdylibbundler to move all the executables' dependencies in here. I'm installing 0.4.4 through MacPorts.

But also, there seem to be some necessary Guile libraries that don't get copied that way (perhaps because Scheme is interpreted, not compiled and linked), so we have to move those in manually. Except that we can't seem to get those to get picked up, except possibly by setting environment variables, and that is suboptimal since we want to be able to call the LilyPond binary without going through the GUI app if necessary...but it turns out that LilyPond sets INSTALLER_PREFIX to its own directory, so that works. The remaining problem with finding them: according to https://lists.gnu.org/archive/html/bug-guile/2010-02/msg00000.html, it seems like they might need an .so extension.

It seems that @executable_path refers to the path of whichever executable is linking to the library, not necessarily the .app bundle's main file.

Script to populate files

# from macosx directory
export MACPORTS_ROOT=~/lilypond-bundle
export APP_BUNDLE=dist/LilyPond.app
export RESOURCES=${APP_BUNDLE}/Contents/Resources

for dir in bin share; do
  mkdir ${RESOURCES}/${dir}
  xargs -I% <extra-files/${dir} cp -av ${MACPORTS_ROOT}/${dir}/% ${RESOURCES}/${dir}/%
done

cp -av extra-files/lilypond ${RESOURCES}/bin
mv -v ${RESOURCES}/bin/gsc ${RESOURCES}/bin/gs

mkdir ${RESOURCES}/libexec
cp -av ${MACPORTS_ROOT}/libexec/lilypond-bin ${RESOURCES}/libexec
for file in ${RESOURCES}/bin/guile18*; do mv -v $file ${file/guile18/guile}; done
# TODO: not sure what to do about gapplication

export OLD_BUNDLE=~/32-bit-app/LilyPond.app
export OLD_RESOURCES=${OLD_BUNDLE}/Contents/Resources
for dir in etc license; do cp -av ${OLD_RESOURCES}/${dir} ${RESOURCES}/${dir}; done

# extra config for Ghostscript; see below
cp -av extra-files/gs.reloc "${RESOURCES}/etc/relocate"

mkdir ${RESOURCES}/lib
cp -av ${MACPORTS_ROOT}/lib/guile18 ${RESOURCES}/lib
cp -av ${MACPORTS_ROOT}/lib/libguile* ${RESOURCES}/lib

for dir in $(find "${MACPORTS_ROOT}/lib" -type d -maxdepth 1); do
  export DYLD_LIBRARY_PATH="${dir}:${DYLD_LIBRARY_PATH}"
done

for dir in lib bin libexec; do
  for l in $(find ${RESOURCES}/${dir}); do
    dylibbundler -cd -of -b -x $l -d ${RESOURCES}/lib/ -p @executable_path/../lib/
  done
done

# for some reason some of these need an extra pass; maybe a bug in dylibbundler?
for l in $(find ${RESOURCES}/lib); do
  if [ -n "$(otool -L "$l" | grep "${MACPORTS_ROOT}")" ]; then
     dylibbundler -cd -of -b -x $l -d ${RESOURCES}/lib/ -p @executable_path/../lib/
  fi
done

Ghostscript configuration

The above instructions produce a working app bundle, but LilyPond still won't run properly (at least for PDF output) because Ghostscript isn't properly configured:

Relocation file: /Users/marnen/Downloads/LilyPond.app/Contents/Resources/bin/../libexec/../etc/relocate//gs.reloc
warning: no such directory: /Users/marnen/Downloads/LilyPond.app/Contents/Resources/bin/../libexec/../share/ghostscript/9.21/fonts for GS_FONTPATH
warning: no such directory: /Users/marnen/Downloads/LilyPond.app/Contents/Resources/bin/../libexec/../share/gs/fonts for GS_FONTPATH
warning: no such directory: /Users/marnen/Downloads/LilyPond.app/Contents/Resources/bin/../libexec/../share/ghostscript/9.21/Resource for GS_LIB
warning: no such directory: /Users/marnen/Downloads/LilyPond.app/Contents/Resources/bin/../libexec/../share/ghostscript/9.21/Resource/Init for GS_LIB

It looks like what's going on is that we built this bundle with GS 9.50, so the path names are a bit different. So we just need to replace the gs.reloc file.

TODO

Going forward we should probably use pipenv and a Pipfile to manage the dependencies.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment