I just committed a bunch of changes, the status quo on OS X is now (public memo to myself):
• RubyGosu Core/"Release" builds a universal gosu.bundle against the system Ruby (as before)
• RubyGosu Core/"Release with Ruby 1.9" builds an Intel-only
gosu.bundle against Ruby 1.9.1 installed in
/usr/local, with program suffix '1.9' (i.e.
/usr/local/bin/ruby1.9), which then is linked against the system headers, as opposed to Ruby 1.9.1 from MacPorts, which is linked against MacPorts-specific libs.
I guess for a Universal, 10.4+ build I need to compile libruby1.9 on both Intel and a PPC Tiger machine, and lipo them together.
• The RubyGosu Deployment Template was renamed
RubyGosu App.app and contains a full, static, universal build of Ruby 1.9.1 (needs testing).
(For anyone trying to build this at home: You'll have to
configure/make Ruby 1.9.1 with the flags mentioned above, and then comment out the last prelude in
prelude.c), then merge this folder with the "Ruby 1.9 Source" folder in "mac" so you have the "config.h" file from SVN in your "include" folder. Whew!)
The plan for OS X is then to include all three in the gem/package. The first
gosu.bundle will be installed for the system Ruby, the other one should work with all Ruby 1.9s, even from MacPorts. (Needs testing.) The
.app wrapper should be included in the Gem too, I think :)
Now to get other Macs for testing, then I'll pre-compile Gosu against the official Ruby 1.9.1 on Windows too...
You want a universal libruby 1.9? I've got one, I can email it to you.
Edit: Incidentally, I've been thinking a bit about a script which could figure out the appropriate path for libruby 1.9 and edit gosu.bundle with install_name_tool to point appropriately. Requires developer tools to be installed, but, how would you get ruby 1.9 without dev tools anyway? (IIRC, you need Dev tools to install MacPorts, yes?)http://pastie.org/467123
That's a script that should do it; mind it only works if the two dylibs have the same interface, so different versions (or rather, incompatible versions) are not dealt with here. But it should allow one to take a gosu.bundle linked to MacPorts ruby 1.9 and hook it up to, say, one installed in /usr/local/ . Usage is, save it in a file, and edit the paths to point to gosu.bundle, then run the file with the version of ruby you want to use gosu with. I'd wager this could get incorporated into a rake task with some tweaking.
Note that I can't actually test this fully myself. I tried it on the gosu.bundle for macports 1.9 julian posted earlier, and it did re-link it, but since it was Intel only, I have no idea whether it worked, not having an intel machine handy.
That would be great! :) -> email@example.com
Thanks. (And wow, good that you are still on 10.4!)
Before I get to the gosu.bundle, I'd like to finish the RubyGosu App wrapper.
The idea is that I basically compile Ruby 1.9 completely into the app's core, with no external dependencys (RUBY_LIB etc. are all set to just '.'). Works quite well...except...I can't load any compiled C extensions (e.g. Chipmunk) because I get unresolved references during dlopen to rb_cFalseClass and all the other things that should be in libruby. (At least it seems that they all use the flat_namespace, so they don't care where the symbols come from, which already makes it lots easier.)
I tried the nebulous -export-dynamic flag that is exists exactly to export symbols from the current executable to dlopened libraries, but it seems not to work with my toolchain. I think a last resort would be to put everything into a dynamically loaded libruby that I put inside my app wrapper.
The next question would then be: how can anyone compile C extensions that would work with the wrapper, anyway? They would also need to be compiled universally and against the 10.4 SDK in order to work on all Macs. But that's just the next step.
philomory: Any ideas—did you ever run into the first issue? :)
OK, I could solve it by disabling stripping, now if I only knew why ld strips my explicitly exported symbols in the first place—probably because it's an executable, sigh.
But the progress of picking the right .rb and .so files from /usr to have a fully self-contained app bundle is a bit much for casual deployment (say Ludum Dare competitions that use more than just gosu or chipmunk). There probably is something akin to RubyScript2Exe for OS X, maybe I can borrow from them. Until then, I think I should keep the old .app wrapper online for quick packaging.
The/my problem with Crate is that it requires adding to the game's code, as far as I know. rubyscript2exe—when it's working—is just 'gem install rubyscript2exe && rubyscript2exe MyGame.rb', voila :) But if anyone manages to package a Gosu game with Crate, I'd love to add their experience to the RubyDeploymentOnOSx page.
I have just tried Ocra (on GitHub) for packaging my Ruby 1.9 game (next post). There are two bugs that I encountered, one of them leading to me including all the .rb and .so files in the package, but at least it seems to work with 1.9. I couldn't get rubyscript2exe to do anything at all with Ruby 1.9 and I think I'll give up on it now.
I downloaded the Ruby 1.9.1 package from ruby-lang.org and added an option to build against that in my MSVC project. Seems to work smoothly. Only need to figure out how to include both .so files in the gem and have it install the correct one. Test project (hackily packaged using Ocra):http://www.raschke.de/julian/temp/LD11_1.9.zip
If anyone wants to give it a try, the gosu.so file for Ruby 1.9 is included in the zip.OS X:
Didn't work on the gosu.bundle file today, but packaged an old game and it seems to have helped its performance (feel free to test the .app wrapper with your game):http://www.raschke.de/julian/temp/LD11_1.9.app.zip
Unfortunately, the game uses YAML files, so I had to include syck.bundle and stringio.bundle from my Ruby 1.9 installation, and these are not universal.
philomory: Do you also happen to have universal (and 10.4 built) versions of these files and socket.bundle? They seem to be the most commonly used C extensions :)
I don't have universal ones built atm, but I have a 10.4 Intel installation and a 10.4 PPC installation. To get libruby, I just lipoed the libruby from each together... I'm considering writing up a script to just go through a pair of ruby lib trees and lipo all the binaries together, now that you mention this. At that point, I can give you any standard lib binary extension you want.
Just a note going forward that I don't have reliable access to a 10.4 Intel machine indefinitely; I've got built 1.9.1 installation available to me right now, but I may or may not be able to compile future updates to 1.9 for Intel 10.4.
Hehe, I think I'll use this excuse to buy an old G4 series Mac again :) Just for building Ruby, of course, not that I'd ever start collecting those...!
For YAML, one workaround would be to use a pure-Ruby implementation, so I guess it's not too critical, just nice to have.
The status quo regarding arbitrary Ruby installations on OS X is that I need to call install_name_tool after installing the gem as you have pointed out. But RubyGems provides *zero* support for post-install scripts—very weird. One trick to fake it is to create an extconf.rb file which does it and generates a bogus Makefile. Unfortunately, this introduces the Xcode tools as a requirement to install the Ruby gem, as I was not able to supply a fake 'make' script. That's probably the next step if the new 1.8/1.9 bundled gems turn out to work reliably.
Well, I already gave you an XCode tools dependency, so another dependency isn't going to hurt you any further; to whit, install_name_tool is part of XCode tools.
Yep, but it only needs to be called for the Ruby 1.9 bundle, and getting Ruby 1.9 without Xcode tools is hard :) For Ruby 1.8, I was able to just 'gem install' it on friends' Macs to test things. Other than that, I guess Ruby coders have Xcode installed anyway, and wrapping up Gosu games on OS X isn't too hard.
I see; so you mean to say that rubygems can't even detect what version of ruby is being used without an extconf.rb... that's obnoxious. There's no way to run rake tasks as part of the gem install process?
From what I gathered in #ruby-lang, the old 'required_ruby_version' flag could gain more relevance soon, but I don't know if that would help with binary gems. Binary, pre-built gems aren't something the system seems to have been built for.
But I think I will go through the source before posting the next set of gems to check this. Maybe there's a new feature somewhere that can be used. I just wish their docs were up-to-date, RubyGems is not an obscure niche project :)
Okay, I noticed something really, really odd. I was just able to download the new 0.7.13.2 gem, and without using lib_name_tool, and do the following:
$ ruby-1.9 --disable-gems
And it worked. A quick check with otool confirms that it's still set to link against the macports libruby location:
$ otool -L gosu.for_1_9.bundle
/opt/local/lib/libruby1.9.dylib (compatibility version 1.9.0, current version 1.9.1)
/usr/lib/libiconv.2.dylib (compatibility version 5.0.0, current version 5.0.0)
/System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 824.47.0)
/System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices (compatibility version 1.0.0, current version 22.0.0)
/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 567.37.0)
/System/Library/Frameworks/Carbon.framework/Versions/A/Carbon (compatibility version 2.0.0, current version 128.0.0)
/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (compatibility version 1.0.0, current version 275.0.0)
/System/Library/Frameworks/OpenAL.framework/Versions/A/OpenAL (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.4.0)
/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 88.3.10)
The really interesting stuff happens when we set DYLD_PRINT_LIBRARIES_POST LAUNCH:
$ export DYLD_PRINT_LIBRARIES_POST_LAUNCH=1
$ ruby-1.9 --disable-gems
dyld: loaded: /usr/local/lib/ruby-1.9/1.9.1/powerpc-darwin8.11.0/enc/encdb.bundle
dyld: loaded: /usr/local/lib/ruby-1.9/1.9.1/powerpc-darwin8.11.0/enc/trans/transdb.bundle
dyld: loaded: /Users/name/gosu-0.7.13.2-universal-darwin/lib/gosu.for_1_9.bundle, cpu-sub-type: 0
dyld: loaded: /usr/lib/libiconv.2.dylib
dyld: loaded: /System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL
dyld: loaded: /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices
dyld: loaded: /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation
dyld: loaded: /System/Library/Frameworks/Carbon.framework/Versions/A/Carbon
dyld: loaded: /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit
dyld: loaded: /System/Library/Frameworks/OpenAL.framework/Versions/A/OpenAL
dyld: loaded: /usr/lib/libstdc++.6.dylib, cpu-sub-type: 0
dyld: loaded: /usr/lib/libgcc_s.1.dylib
dyld: loaded: /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
dyld: loaded: /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLU.dylib
dyld: loaded: /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/AE.framework/Versions/A/AE
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/ATS
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ColorSync.framework/Versions/A/ColorSync
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/CoreGraphics
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreText.framework/Versions/A/CoreText
dyld: loaded: /System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/PrintCore.framework/Versions/A/PrintCore
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/QD.framework/Versions/A/QD
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/HIServices
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/LangAnalysis.framework/Versions/A/LangAnalysis
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/FindByContent.framework/Versions/A/FindByContent
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/LaunchServices
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/SpeechSynthesis.framework/Versions/A/SpeechSynthesis
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/ImageIO
dyld: loaded: /System/Library/Frameworks/Security.framework/Versions/A/Security
dyld: loaded: /System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration
dyld: loaded: /usr/lib/libicucore.A.dylib
dyld: loaded: /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/CarbonCore
dyld: loaded: /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/OSServices.framework/Versions/A/OSServices
dyld: loaded: /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CFNetwork.framework/Versions/A/CFNetwork
dyld: loaded: /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/WebServicesCore.framework/Versions/A/WebServicesCore
dyld: loaded: /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/SearchKit.framework/Versions/A/SearchKit
dyld: loaded: /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/Metadata.framework/Versions/A/Metadata
dyld: loaded: /usr/lib/libz.1.dylib
dyld: loaded: /System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration
dyld: loaded: /usr/lib/libbsm.dylib
dyld: loaded: /usr/lib/libcrypto.0.9.7.dylib
dyld: loaded: /usr/lib/libcups.2.dylib
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libJPEG.dylib
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libJP2.dylib
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libGIF.dylib
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libRaw.dylib
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libPng.dylib
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libRadiance.dylib
dyld: loaded: /usr/lib/libxml2.2.dylib, cpu-sub-type: 0
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/Resources/libTIFF.dylib
dyld: loaded: /System/Library/Frameworks/Accelerate.framework/Versions/A/Accelerate, cpu-sub-type: 0
dyld: loaded: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vImage.framework/Versions/A/vImage, cpu-sub-type: 0
dyld: loaded: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/vecLib, cpu-sub-type: 0
dyld: loaded: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvMisc.dylib, cpu-sub-type: 0
dyld: loaded: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvDSP.dylib
dyld: loaded: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib, cpu-sub-type: 0
dyld: loaded: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLAPACK.dylib, cpu-sub-type: 0
dyld: loaded: /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox
dyld: loaded: /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/SpeechRecognition.framework/Versions/A/SpeechRecognition
dyld: loaded: /System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox
dyld: loaded: /System/Library/Frameworks/AudioUnit.framework/Versions/A/AudioUnit
dyld: loaded: /System/Library/PrivateFrameworks/DesktopServicesPriv.framework/Versions/A/DesktopServicesPriv
dyld: loaded: /System/Library/Frameworks/CoreData.framework/Versions/A/CoreData
dyld: loaded: /System/Library/Frameworks/QuartzCore.framework/Versions/A/QuartzCore
dyld: loaded: /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/CarbonSound.framework/Versions/A/CarbonSound, cpu-sub-type: 0
dyld: loaded: /System/Library/Frameworks/CoreAudio.framework/Versions/A/CoreAudio
dyld: loaded: /usr/lib/libsqlite3.0.dylib
dyld: loaded: /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLImage.dylib
dyld: loaded: /System/Library/Frameworks/CoreVideo.framework/Versions/A/CoreVideo, cpu-sub-type: 0
dyld: loaded: /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/ImageCapture.framework/Versions/A/ImageCapture
dyld: loaded: /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/SecurityHI.framework/Versions/A/SecurityHI
dyld: loaded: /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/Ink.framework/Versions/A/Ink
dyld: loaded: /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/Help.framework/Versions/A/Help
dyld: loaded: /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/OpenScripting.framework/Versions/A/OpenScripting
dyld: loaded: /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/Print.framework/Versions/A/Print
dyld: loaded: /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HTMLRendering.framework/Versions/A/HTMLRendering
dyld: loaded: /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/NavigationServices.framework/Versions/A/NavigationServices
dyld: loaded: /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/CommonPanels.framework/Versions/A/CommonPanels
dyld: loaded: /System/Library/Frameworks/vecLib.framework/Versions/A/vecLib, cpu-sub-type: 0
dyld: loaded: /System/Library/Frameworks/OpenGL.framework/Resources/GLEngine.bundle/GLEngine
dyld: loaded: /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLProgrammability.dylib
dyld: loaded: /System/Library/Extensions/ATIRadeon9700GLDriver.bundle/Contents/MacOS/ATIRadeon9700GLDriver
dyld: loaded: /System/Library/Frameworks/OpenGL.framework/Versions/A/Resources/GLDriver.bundle/GLDriver
dyld: loaded: /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLSystem.dylib
dyld: loaded: /System/Library/Frameworks/OpenGL.framework/Versions/A/Resources/GLRendererFloat.bundle/GLRendererFloat
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Resources/libCSync.A.dylib
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Resources/libRIP.A.dylib
dyld: loaded: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/Versions/A/Resources/libCGATS.A.dylib
Note with intense interest what does and does not get loaded by DYLD here. I think you may have already won. The two librubies don't even have the same suffix, let alone path, but it's working anyway, probably because running the ruby command line app already loads my installed libruby and provides its symbols.
This may or may not help you in your work on the deployment template, but it's good news for the development gem, I'd say.
EDIT: Okay, I really should have used DYLD_PRINT_LIBRARIES rather than DYLD_PRINT_LIBRARIES_POST_LAUNCH, to get the full picture of what's going on. It gives the same results, except that this occurs immediately after invoking ruby, before encdb.bundle and transdb.bundle are loaded:
dyld: loaded: /usr/local/bin/ruby-1.9
dyld: loaded: /usr/local/lib/libruby-1.9.dylib
dyld: loaded: /usr/lib/libSystem.B.dylib, cpu-sub-type: 0
dyld: loaded: /usr/lib/libobjc.A.dylib
dyld: loaded: /usr/lib/system/libmathCommon.A.dylib, cpu-sub-type: 0
dyld: loaded: /usr/lib/libauto.dylib
Edit again: To be 100% clear, my previous edit hoped to clarify what was going on, not downplay it. It's just extra info I should have included the first time.
Just for clarity, it works even when you require it using rubygems as usual?
That would be awesome news. I just deactivated Ruby 1.9 in MacPorts, and the gosu gem worked with my custom Ruby 1.9 in /usr/local. Surprisingly enough—it didn't work when I tried it the other way around (spent half a day seeing dlopen errors). I think I'll just leave it at that until it breaks…
As for stringio.bundle and syck.bundle, when I put them into my deployment template (which is a self-contained 1.9 installation now), I still have to adjust paths, but there *is* no right one in that case. Oh no! I just wish I could remove the dyld dependencies altogether. I even thought about pointing it to a completely unrelated library, but the version tags will probably ruin that. The symbols are available anyway (in the flat namespace, just not coming from a dylib).
To add to the weirdness, the Ruby .app wrapper does not run here when I use your stringio.bundle and syck.bundle, but there are no problems to run it on a machine without any Ruby 1.9 when I use the .dylibs from my Intel-only, Leopard-only installation. Duh! :)
Thanks for in-depth analysis! :)
Just tried it using rubygems, works fine that way too!
As for the app wrapper, I can't comment on it yet since I haven't tried your new one even a little bit. I might get a chance to play with that later tonight.
When you say it doesn't run, what *does* it do? Do you get anything dumped to the console, on the order of 'could not load library' or some such?
Yes, the standard dlopen error:
.../lib/open-uri.rb:2:in `require': dlopen(.../lib/stringio.bundle, 9): Library not loaded: /usr/local/lib/libruby-1.9.dylib (LoadError)
I will retry it later with my stringio/syck bundles, but with temporarily removed libruby dylibs, to see if our libraries differ in their behavior (I'm trying to understand why my bundles work on another machine without 1.9).
For what it's worth, I have built the gosu.for_1_9.bundle with -weak-lruby..., but at first I thought it didn't work; now that I think about it, that was probably an error on my side, because that flag would explain why the problem doesn't occur with this bundle.
One possibility would be to recompile ruby-1.9 after editing ext/Setup in the source tree to make all the relevant modules (syck, stringio, etc) statically linked into libruby. At least, if I'm reading the docs correctly, that's what I think would happen. I don't really have time to play with that at the moment, though. If you try it and find that it works, then I can try building the universal version for you.
The problem is, though, that only solves the issue for Standard Lib bundles, not third party C-extensions from gems, etc. This seems like it could end up being something very difficult to do correctly; I imagine these were some of the issues _why had to deal with, since in Shoes he maintains a custom fork of Ruby. A quick scan of the Shoes Adventurer's mailing list shows a lot of contortions gone through to get native extensions to build.
Hopefully the situation with gosu can be made less complex, since you haven't actually forked ruby, but I think, as things currently stand, there is a limit to how simple this approach can be made.
Remind me, what was the advantage of statically compiling libruby into the deployment package, instead of bundling the universal dylib and dynamically loading it? It seems it would be easier to get binary gems to work with the latter approach (there may be other differences which tilt the balance the other way, however; that's why I'm asking).
Here's an idea; is there some way to, when building a (native) gem, pass extra flags to the linker? Either with environment variables or the --build-options flag to gem install? I'm not sure if --build-options passes flags to the linker, or only the compiler, and the env variables might be ignored (though they shouldn't be). But if either way works, then people needing to bundle a native gem with their distributed app could be instructed to build it with 'gem install whatever --build-options -weak-lruby'. Worth a shot.
OK, so to conserve a bit of IRC, there are two problems with shipping Ruby games with C extensions (actually, most of this is true for 1.8 as well):
1. All the libraries we get from installing gems or building Ruby from source (or via MacPorts) have a dependency on some dynamic libruby. It's just a formal requirement, as all the imports are in a flat namespace that can be satisfied by any Ruby whatsoever, and there is usually one. If we can just strip the dependency from the extension, it will work in the .app container regardless of the Ruby it was built against. (Right now, everything worked because everything was built against OS X' system Ruby.)
Solution: install_name_tool lets us change the name of the required library, a trivial bit of hex editing lets us change the required version too. (As a short verification of this step, the ABI is documented at http://developer.apple.com/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html
) By just changing any libruby to libSystem and the required number to 1.0.0, the dependency is practically erased. I'll probably write a two-liner to automate that.
2. If someone wants to deploy a C extension with their game, it is inevitable to build a Universal version, at best against the OS X 10.4 SDK for Tiger compatibility. This is pretty hard because gem, extconf/mkmf etc. don't really care about this.
Right now, this is worked around by building on machines that run 10.4 and manual stitching with lipo afterwards. This was done for RMagick (kind of—on 10.5), and this is what you just provided for syck.bundle and stringio.bundle. This means that if we collect one bundle for 1.8 and 1.9 each here for the most common libraries publicaly (Chipmunk, ...), we have a workaround.
The ideal solution would be to have a tool that builds gems as well as system libraries universally and against the 10.4 SDK, and erases the dependency just in case. But since I guess it's just ~5 C extensions that have ever been used in a Gosu game, I think this would be overengineering it for now.
Phew! But I think we are just a few collected libraries, and one explanatory wiki page away from a solid base for most deployment needs.
Hey, Julian, if I wanted to download current source to try and play with getting the App package to work the way we want, what revision would you recommend checking out of SVN?
Do you mean the "new style" 1.9 package? Just follow the HEAD. The Ruby source that you have to drop into the "mac/Ruby 1.9 Source" subdirectory for it to work is the one from ruby-lang.org for 1.9.1p0, except that some files have to be overwritten by Gosu (the ones that are in SVN). Then just build the .app wrapper in the configuration "Release with 1.9", or "Release", as they both use 1.9.
What do you plan to change, introduce a faux libruby so my byte-punching will not be necessary? :)
Actually, the plan is to link the Deployment Package to libruby dynamically rather than statically, but use a tweaked libruby which is itself statically linked to the necessary parts of Standard Lib (syck, stringio, etc). Or, if I can't get that part to work, just dynamically link everything as normal, bite the bullet, tweak the entirety of the standard library with install_name_tool, and include all of it in the deployment bundle, universal-style. It can all be stuck in a separate directory inside the bundle (Contents/lib/ruby/, perhaps).
Basically I want to see which approach ultimately turns out to be the simpler one. The only way to know for sure is to try them both, since I'm sure they each will have surprises waiting for us.
Hmm, I think with 10.4 Intel and PPC boxes, or some advanced Makefile know-how available, it would be easy to just build Ruby 1.9.1 into /tmp/everything_goes_here, universalize & install_name_toolize it and put it into the .app. Admittedly, that would probably be the least trouble to stay up to date with future Ruby versions :)
philomory, I want to switch the Ruby 1.9 wrapper to work pretty much like Operation Lambda seems to work.
Operation Lambda works for me but I cannot really figure out how you install_name_tool'd the dynamic Ruby libraries to be found and how you set up the .app. Actually, the thing I don't get is how the main binary has the right paths (@executable_path.../) but the libraries themselves still have your paths in there.
Edit: Reading http://qin.laya.com/tech_coding_help/dylib_linking.html
now. Man, this whole install_path thing seems like arbitrary torture to me. :)
Powered by mwForum 2.29.7 © 1999-2015 Markus Wichitill