{"id":67,"date":"2009-02-15T15:25:32","date_gmt":"2009-02-15T15:25:32","guid":{"rendered":"http:\/\/blog.danplanet.com\/wordpress\/?p=67"},"modified":"2012-02-09T16:17:08","modified_gmt":"2012-02-09T16:17:08","slug":"using-py2app-with-gtk","status":"publish","type":"post","link":"https:\/\/www.danplanet.com\/blog\/2009\/02\/15\/using-py2app-with-gtk\/","title":{"rendered":"Using Py2App with GTK"},"content":{"rendered":"<p>In order to present <a href=\"http:\/\/www.d-rats.com\">D-RATS<\/a> as a nice and neat App package on MacOS X, I have been using <a href=\"http:\/\/svn.pythonmac.org\/py2app\/py2app\/trunk\/doc\/index.html\">Py2App<\/a>.\u00a0 When it works, this utility generates a App package that contains everything D-RATS needs aside from the base operating system to run.\u00a0 To do this, I install <a href=\"http:\/\/www.macports.org\">MacPorts<\/a> and then build a full Python 2.5 stack with things like pygtk, libxml2, libxslt, etc.\u00a0 When I run Py2App, it captures all of the necessary libraries and support files from the MacPorts installation and relocates them into the App package to form a nice, neat, and easy-to-run package for Mac users.<\/p>\n<p>Each time I set out to create this environment, I was presented with the same problem.\u00a0 Since it took me several attempts spanning many months to figure out the proper way to solve it, I decided to document it here so that there would be a single place that explained how to get out of this particular jam.<\/p>\n<p>The problem was that when running Py2App, I would inevitably get the following error message:<\/p>\n<blockquote>\n<p><font face=\"courier new,courier\">ValueError: New Mach-O header is too large to relocate<\/font><\/p>\n<\/blockquote>\n<p>In order to figure out what it was complaining about, I would type <font face=\"courier new,courier\">print self<\/font> in the debugger, which would show me the path of the library it was trying to relocate.\u00a0 I think that the first one I would aways hit with this problem was\u00a0 <font face=\"courier new,courier\">libpangoxft-1.0.0.dylib<\/font>.\u00a0 After hacking up a solution, I believe there were a couple more in the stack that I needed that would present the same problem.<\/p>\n<p>It turns out that the problem is one of space.\u00a0 When the dynamic libraries for MacPorts are created, they encode the full path of the library into the header, which is something like <font face=\"courier new,courier\">\/opt\/local\/lib\/libpangoxft-1.0.0.2203.1.dylib<\/font>.\u00a0 When Py2App goes to relocate the library into the package, it needs to change this to a relative path which points to its location in the package relative to some other object.\u00a0\u00a0 It would appear that if the length of the original string is shorter than the one it needs to become in the package, the relocation logic used by Py2App is stuck and thus dies with the above error message.<\/p>\n<p>The Py2App author <a href=\"http:\/\/markmail.org\/message\/rd3aoohc4pqhqnnb?q=macholib+header+too+large+to+relocate&#038;page=1&#038;refer=nf4facs4zhgyciel\">indicates<\/a> that the only solution to the problem is to re-link the library with an option that will instruct the linker to create the maximum amount of space for the library name in the header, despite what is requires at link time.\u00a0 This ensures that the relocated library path name will fit in the space allocated.\u00a0 It turns out that in addition to the prescribed option, the <font face=\"courier new,courier\">-Xlinker<\/font> option is also required to make some component in the chain obey the request to pad the header.\u00a0 This bit took me quite a while to figure out.<\/p>\n<p>I figured that the safest (and easiest to reproduce) option would be to convince MacPorts to build everything with this option instead of trying to insert it into the build environment of only the affected libraries.\u00a0 To do this, I modified the port command&#8217;s library file where the default configure options are held.\u00a0 For me, this was <font face=\"courier new,courier\">\/opt\/local\/share\/macports\/Tcl\/port1.0\/portconfigure.tcl<\/font>.\u00a0 I edited the line starting with <font face=\"courier new,courier\">default configure.ldflags<\/font> to look like this:<\/p>\n<blockquote>\n<pre><font face=\"courier new,courier\" style=\"font-size: larger\">default configure.ldflags   {\"-L${prefix}\/lib -Xlinker -headerpad_max_install_names\"}<\/font><\/pre>\n<\/blockquote>\n<p>After doing that on a fresh install of  MacPorts, I proceeded to build the required stack.\u00a0 In the end, Py2App agreed to relocate everything into the app package and it worked well. <\/p>\n<p>Since I&#8217;ve got this going, I will point out an additional issue that I ran into in the whole process, which took some actual work to figure out.<\/p>\n<p>The problem was with the pango configuration files.\u00a0 These normally live in <font face=\"courier new,courier\">\/etc\/pango<\/font>, or <font face=\"courier new,courier\">\/opt\/local\/etc\/pango<\/font> in the MacPorts installation.\u00a0 These must be in place in the App package or the pango library will not properly render fonts.\u00a0 Moreover, the configuration files must properly point to the relocated objects within the package.<\/p>\n<p>In order to capture the act of copying and modifying the pango configuration scripts, I wrote the following script which can be run after the App build is complete:<\/p>\n<blockquote><p><font face=\"courier new,courier\">#!\/bin\/bash<\/font><\/p>\n<p><font face=\"courier new,courier\">make_pango_modules() {<\/font><br \/><font face=\"courier new,courier\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 local src=$1<\/font><br \/><font face=\"courier new,courier\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 local dst=$2<\/font><br \/><font face=\"courier new,courier\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 local sf=${src}\/etc\/pango\/pango.modules<\/font><br \/><font face=\"courier new,courier\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 local df=${dst}\/etc\/pango\/pango.modules<\/font><\/p>\n<p><font face=\"courier new,courier\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 cat $sf | sed &#8216;s\/\/opt\/.*\/lib\/..\/Resources\/&#8217; &gt; $df<\/font><br \/><font face=\"courier new,courier\">}<\/font><\/p>\n<p><font face=\"courier new,courier\">make_pango_rc() {<\/font><br \/><font face=\"courier new,courier\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 local src=$1<\/font><br \/><font face=\"courier new,courier\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 local dst=$2<\/font><br \/><font face=\"courier new,courier\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 local sf=${src}\/etc\/pango\/pangorc<\/font><br \/><font face=\"courier new,courier\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 local df=${dst}\/etc\/pango\/pangorc<\/font><\/p>\n<p><font face=\"courier new,courier\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 cat $sf | sed &#8216;s\/\/opt\/.*\/etc\/.\/etc\/&#8217; &gt; $df<\/font><br \/><font face=\"courier new,courier\">}<\/font><\/p>\n<p><font face=\"courier new,courier\">make_pangox_aliases() {<\/font><br \/><font face=\"courier new,courier\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 local src=$1<\/font><br \/><font face=\"courier new,courier\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 local dst=$2<\/font><\/p>\n<p><font face=\"courier new,courier\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 cp ${src}\/etc\/pango\/pangox.aliases ${dst}\/etc\/pango<\/font><br \/><font face=\"courier new,courier\">}<\/font><\/p>\n<p><font face=\"courier new,courier\">usage() {<\/font><br \/><font face=\"courier new,courier\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 echo &#8216;Usage: make_pango.sh [PATH_TO_MACPORTS] [PATH_TO_APP]&#8217;<\/font><br \/><font face=\"courier new,courier\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 echo &#8216;Example:&#8217;<\/font><br \/><font face=\"courier new,courier\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 echo &#8216;\u00a0 make_pango.sh \/opt\/local dist\/d-rats.app&#8217;<\/font><br \/><font face=\"courier new,courier\">}<\/font><\/p>\n<p><font face=\"courier new,courier\">if [ -z &#8220;$1&#8221; ]; then<\/font><br \/><font face=\"courier new,courier\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 usage<\/font><br \/><font face=\"courier new,courier\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 exit 1<\/font><br \/><font face=\"courier new,courier\">fi<\/font><\/p>\n<p><font face=\"courier new,courier\">if [ -z &#8220;$2&#8221; ]; then<\/font><br \/><font face=\"courier new,courier\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 usage<\/font><br \/><font face=\"courier new,courier\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 exit 1<\/font><br \/><font face=\"courier new,courier\">fi<\/font><\/p>\n<p><font face=\"courier new,courier\">base=$1<\/font><br \/><font face=\"courier new,courier\">app=&#8221;$2\/Contents\/Resources&#8221;<\/font><\/p>\n<p><font face=\"courier new,courier\">mkdir -p ${app}\/etc\/pango<\/font><\/p>\n<p><font face=\"courier new,courier\">make_pango_modules $base $app<\/font><br \/><font face=\"courier new,courier\">make_pango_rc $base $app<\/font><br \/><font face=\"courier new,courier\">make_pangox_aliases $base $app<\/font><\/p><\/blockquote>\n<p>By running this script with something like:<\/p>\n<blockquote>\n<p><font face=\"courier new,courier\">.\/make_pango.sh \/opt\/local dist\/myprogram.app<\/font><\/p>\n<\/blockquote>\n<p>You&#8217;ll get a properly configured pango environment. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>In order to present D-RATS as a nice and neat App package on MacOS X, I have been using Py2App.\u00a0 When it works, this utility generates a App package that contains everything D-RATS needs aside from the base operating system &hellip; <a href=\"https:\/\/www.danplanet.com\/blog\/2009\/02\/15\/using-py2app-with-gtk\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12],"tags":[48],"class_list":["post-67","post","type-post","status-publish","format-standard","hentry","category-codemonkeying","tag-python"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.6 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Using Py2App with GTK - Right Angles<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.danplanet.com\/blog\/2009\/02\/15\/using-py2app-with-gtk\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Using Py2App with GTK - Right Angles\" \/>\n<meta property=\"og:description\" content=\"In order to present D-RATS as a nice and neat App package on MacOS X, I have been using Py2App.\u00a0 When it works, this utility generates a App package that contains everything D-RATS needs aside from the base operating system &hellip; Continue reading &rarr;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.danplanet.com\/blog\/2009\/02\/15\/using-py2app-with-gtk\/\" \/>\n<meta property=\"og:site_name\" content=\"Right Angles\" \/>\n<meta property=\"article:published_time\" content=\"2009-02-15T15:25:32+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2012-02-09T16:17:08+00:00\" \/>\n<meta name=\"author\" content=\"Dan\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Dan\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.danplanet.com\/blog\/2009\/02\/15\/using-py2app-with-gtk\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.danplanet.com\/blog\/2009\/02\/15\/using-py2app-with-gtk\/\"},\"author\":{\"name\":\"Dan\",\"@id\":\"https:\/\/www.danplanet.com\/blog\/#\/schema\/person\/0f6920aa6d63cae437bf8b122200287c\"},\"headline\":\"Using Py2App with GTK\",\"datePublished\":\"2009-02-15T15:25:32+00:00\",\"dateModified\":\"2012-02-09T16:17:08+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.danplanet.com\/blog\/2009\/02\/15\/using-py2app-with-gtk\/\"},\"wordCount\":854,\"publisher\":{\"@id\":\"https:\/\/www.danplanet.com\/blog\/#\/schema\/person\/0f6920aa6d63cae437bf8b122200287c\"},\"keywords\":[\"python\"],\"articleSection\":[\"Codemonkeying\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.danplanet.com\/blog\/2009\/02\/15\/using-py2app-with-gtk\/\",\"url\":\"https:\/\/www.danplanet.com\/blog\/2009\/02\/15\/using-py2app-with-gtk\/\",\"name\":\"Using Py2App with GTK - Right Angles\",\"isPartOf\":{\"@id\":\"https:\/\/www.danplanet.com\/blog\/#website\"},\"datePublished\":\"2009-02-15T15:25:32+00:00\",\"dateModified\":\"2012-02-09T16:17:08+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.danplanet.com\/blog\/2009\/02\/15\/using-py2app-with-gtk\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.danplanet.com\/blog\/2009\/02\/15\/using-py2app-with-gtk\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.danplanet.com\/blog\/2009\/02\/15\/using-py2app-with-gtk\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.danplanet.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Using Py2App with GTK\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.danplanet.com\/blog\/#website\",\"url\":\"https:\/\/www.danplanet.com\/blog\/\",\"name\":\"Right Angles\",\"description\":\"If they&#039;re not right...they&#039;re wrong\",\"publisher\":{\"@id\":\"https:\/\/www.danplanet.com\/blog\/#\/schema\/person\/0f6920aa6d63cae437bf8b122200287c\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.danplanet.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/www.danplanet.com\/blog\/#\/schema\/person\/0f6920aa6d63cae437bf8b122200287c\",\"name\":\"Dan\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.danplanet.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/9b73782704be64dd8c030087af2d1ae0c1dc488cad69093ff0366dbaad2de673?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/9b73782704be64dd8c030087af2d1ae0c1dc488cad69093ff0366dbaad2de673?s=96&d=mm&r=g\",\"caption\":\"Dan\"},\"logo\":{\"@id\":\"https:\/\/www.danplanet.com\/blog\/#\/schema\/person\/image\/\"},\"url\":\"https:\/\/www.danplanet.com\/blog\/author\/dan\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Using Py2App with GTK - Right Angles","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.danplanet.com\/blog\/2009\/02\/15\/using-py2app-with-gtk\/","og_locale":"en_US","og_type":"article","og_title":"Using Py2App with GTK - Right Angles","og_description":"In order to present D-RATS as a nice and neat App package on MacOS X, I have been using Py2App.\u00a0 When it works, this utility generates a App package that contains everything D-RATS needs aside from the base operating system &hellip; Continue reading &rarr;","og_url":"https:\/\/www.danplanet.com\/blog\/2009\/02\/15\/using-py2app-with-gtk\/","og_site_name":"Right Angles","article_published_time":"2009-02-15T15:25:32+00:00","article_modified_time":"2012-02-09T16:17:08+00:00","author":"Dan","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Dan","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.danplanet.com\/blog\/2009\/02\/15\/using-py2app-with-gtk\/#article","isPartOf":{"@id":"https:\/\/www.danplanet.com\/blog\/2009\/02\/15\/using-py2app-with-gtk\/"},"author":{"name":"Dan","@id":"https:\/\/www.danplanet.com\/blog\/#\/schema\/person\/0f6920aa6d63cae437bf8b122200287c"},"headline":"Using Py2App with GTK","datePublished":"2009-02-15T15:25:32+00:00","dateModified":"2012-02-09T16:17:08+00:00","mainEntityOfPage":{"@id":"https:\/\/www.danplanet.com\/blog\/2009\/02\/15\/using-py2app-with-gtk\/"},"wordCount":854,"publisher":{"@id":"https:\/\/www.danplanet.com\/blog\/#\/schema\/person\/0f6920aa6d63cae437bf8b122200287c"},"keywords":["python"],"articleSection":["Codemonkeying"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.danplanet.com\/blog\/2009\/02\/15\/using-py2app-with-gtk\/","url":"https:\/\/www.danplanet.com\/blog\/2009\/02\/15\/using-py2app-with-gtk\/","name":"Using Py2App with GTK - Right Angles","isPartOf":{"@id":"https:\/\/www.danplanet.com\/blog\/#website"},"datePublished":"2009-02-15T15:25:32+00:00","dateModified":"2012-02-09T16:17:08+00:00","breadcrumb":{"@id":"https:\/\/www.danplanet.com\/blog\/2009\/02\/15\/using-py2app-with-gtk\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.danplanet.com\/blog\/2009\/02\/15\/using-py2app-with-gtk\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.danplanet.com\/blog\/2009\/02\/15\/using-py2app-with-gtk\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.danplanet.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Using Py2App with GTK"}]},{"@type":"WebSite","@id":"https:\/\/www.danplanet.com\/blog\/#website","url":"https:\/\/www.danplanet.com\/blog\/","name":"Right Angles","description":"If they&#039;re not right...they&#039;re wrong","publisher":{"@id":"https:\/\/www.danplanet.com\/blog\/#\/schema\/person\/0f6920aa6d63cae437bf8b122200287c"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.danplanet.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.danplanet.com\/blog\/#\/schema\/person\/0f6920aa6d63cae437bf8b122200287c","name":"Dan","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.danplanet.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/9b73782704be64dd8c030087af2d1ae0c1dc488cad69093ff0366dbaad2de673?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/9b73782704be64dd8c030087af2d1ae0c1dc488cad69093ff0366dbaad2de673?s=96&d=mm&r=g","caption":"Dan"},"logo":{"@id":"https:\/\/www.danplanet.com\/blog\/#\/schema\/person\/image\/"},"url":"https:\/\/www.danplanet.com\/blog\/author\/dan\/"}]}},"_links":{"self":[{"href":"https:\/\/www.danplanet.com\/blog\/wp-json\/wp\/v2\/posts\/67","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.danplanet.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.danplanet.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.danplanet.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.danplanet.com\/blog\/wp-json\/wp\/v2\/comments?post=67"}],"version-history":[{"count":1,"href":"https:\/\/www.danplanet.com\/blog\/wp-json\/wp\/v2\/posts\/67\/revisions"}],"predecessor-version":[{"id":233,"href":"https:\/\/www.danplanet.com\/blog\/wp-json\/wp\/v2\/posts\/67\/revisions\/233"}],"wp:attachment":[{"href":"https:\/\/www.danplanet.com\/blog\/wp-json\/wp\/v2\/media?parent=67"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.danplanet.com\/blog\/wp-json\/wp\/v2\/categories?post=67"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.danplanet.com\/blog\/wp-json\/wp\/v2\/tags?post=67"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}