GNOME Bugzilla – Bug 776295
The bundler should place binaries into Contents/Frameworks because of signing
Last modified: 2019-02-22 05:07:21 UTC
I was having some trouble with signatures generated using the "official" gtk-mac-bundler method (setting APPLICATION_CERT env. variable) on some OS X versions (10.10.5 specifically), see https://github.com/geany/geany/issues/1335 I've played with the signing a bit and realized one can use something like codesign -s "my certificate" --deep --force ./MyApp.app which seems to work fine. However, I've noticed that the binaries aren't signed "properly" (there should be a signature for every page of code so the binary can be verified lazily as it loads when there are page faults) but instead there's just a single signature for the whole file like resources (I don't know what consequences it has but this probably means that all the libraries have to be verified first before anything gets executed). To sign code, codesign expects binaries to be at the standard locations https://developer.apple.com/library/content/technotes/tn2206/_index.html#//apple_ref/doc/uid/DTS40007919-CH1-TNTAG201 so for dylibs probably the best location is Contents/Frameworks. Would it be a problem to change the bundler (and the launcher script) to place binaries there? Or is there anything that complicates things? (By the way for now having a launcher script running a binary seems to pass validation when signed even though there shouldn't be any scripts inside Contents.)
>I was having some trouble with signatures generated using the "official" > gtk-mac-bundler method Me, too, but I haven't encountered the failure for a bad signature on a dylib, I've seen only Gatekeeper failures. > By the way for now having a launcher script running a binary seems to pass > validation when signed even though there shouldn't be any scripts inside Contents.) That actually depends on the binary. Python programs need to have a script-free Contents/MacOS directory. See https://wiki.gnome.org/Projects/GTK%2B/OSX/Bundling#Code_Signing. As it says there the best option is to not use a launcher script, but that generally means that the program itself has to be modified to set up its environment after startup, so I haven't changed the example behavior. Hmm, maybe a generic wrapper program that reads a data file to set up the environment then exec()s the application. As for moving dylib locations to Contents/Frameworks, it should work. I hadn't considered that before. Obviously the rpath rewrite will have to change as will the DYLD_LIBRARY_PATH and (especially) LTDL_LIBRARY_PATH environment variables passed to the application. Python applications might be a problem as python kind of requires mixing scripts and loadable modules in its site-packages directory so that might have to stay in Resources/lib.
I've created an experimental branch that does this: https://github.com/jralls/gtk-mac-bundler/tree/new-layout. I put some instructions about it in examples/gtk-demo.bundle. If your program dopens (or worse dlopens) anything you may have to jump through some hoops to get that working with the new layout. It still builds a hierarchy of directories in Frameworks and Plugins. I'll try flattening it out, but so far it doesn't seem to have any effect at all on either the amount of time needed to sign or the verification time.
The new-layout branch now makes a fully-compliant bundle. That doesn't produce any speed up in verification time on older versions (I tested on 10.10), nor is the bundle size significantly different. Worse, Gtk insists that its plugin modules (input-method, printer backends, etc.) *must* be in somewhere/gtk-version/modules. You can set an environment variable with a bunch of :-separated somewheres, but the rest is hard-coded in Gtk. That's probably OK for some packages, but most will need to at least print and some users might want im even though im-quartz breaks a few things (mostly search in GtkTreeViews). I'll leave the branch there for you to play with if you want, but I don't think there's any gain to this so I'm closing the bug "won't fix".