allegro5
allegro5 copied to clipboard
al_mangled_main linking issues with bundles
See https://www.allegro.cc/forums/thread/615967
My thoughts (taken from the thread linked above...)
Configuring CMake on OS X gives this warning:
CMake Warning (dev):
Policy CMP0042 is not set: MACOSX_RPATH is enabled by default. Run "cmake
--help-policy CMP0042" for policy details. Use the cmake_policy command to
set the policy and suppress this warning.
MACOSX_RPATH is not specified for the following targets:
allegro
allegro_acodec
allegro_audio
allegro_color
allegro_dialog
allegro_font
allegro_image
allegro_main
allegro_memfile
allegro_physfs
allegro_primitives
allegro_ttf
allegro_video
Using _@_rpath with these libraries should make it possible to use them in bundles just by copying them to the Frameworks subdirectory,
except allegro_main
- if this can be made into a static library it will be able to link to _al_mangled_main
in the user's code even after symbol stripping.
Further to this - the rpath stuff is already covered in #532. CMake never works the way I expect it to.
One thing I'm seeing as I try this is homebrew is naming libraries like liballegro.5.1.dylib as symlinks to liballegro5.1.12.dylib and so on... once these go into a Framework, the libraries that depend on liballegro.5.1.dylib (example, don't remember if this is one of the actual dependencies) are going to fail because in the .app/Contents/Frameworks there is only liballegro.5.1.12.dylib...
I'm sure it's possible to get this to work using install_name_tool. However, after 30 minutes of changing names I still have a lot left to change. I suggest looking at otool -l and otool -L output of libs and executables. With the example given on allegro.cc, there's a ton of missing links.
On OS X, you have to build libraries a certain way if you want to use them in bundles. Then they won't work right standalone. CMake has things like BUILD_WITH_INSTALL_RPATH and INSTALL_RPATH that help with this. I set the former to on and the latter to "@executable_path/" (you could add ../Frameworks) when I build dynamic libraries. Then, when they're linked to everything is already set to go. I don't know how you'd do it with homebrew though.
Would things be better if we generated frameworks instead of dylibs?
As an outsider looking in, I get the impression OS X is quite a bit of a moving target. This is jarring for me being a Windows developer, where I could, if I were so inclined, install MSVC 6 on Windows 10 and use it to build programs that would run happily on that OS. Say what you will about Windows, but the API and ABI stability is very much appreciated.
I don't yet have a Mac of my own, but I do intend to acquire one eventually--and I'm not looking forward to officially supporting OS X for minisphere at all. :stuck_out_tongue_closed_eyes:
I think I can fix this but I won't have time until the weekend, is that OK? I need to get up to speed with CMake more than anything.
It's not urgent, it's just something that probably should take a bit of a priority over other things. Thanks for taking a look at it!
Well, I did look at it over the weekend, I just haven't got around to replying here until now.
On the original problem, I think the best way is to always force the alleg_main
library to be static. That way the real main function in alleg_main
knows the address of the mangled main in the executable at link time, before the symbols are stripped. Otherwise it's got to resolve it at runtime which it can't if the executable has been stripped.
The alternative was as suggested by Malcolm - pass flags into the strip program to ensure it leaves the mangled main entry alone. This seems more complicated and error-prone to me.
To make alleg_main
always static is simple enough in CMake. Unfortunately there's a bit more messing about if the user wants the monolith option, which I haven't sorted out yet.
However alleg_main
is a funny sort of 'add-on', isn't it? It's actually empty for all platforms except OS X (even iOS, not sure how that can be?) So someone developing on Linux would probably forget to include it and then find it wouldn't build on the Mac. Ideally it would just hitch a ride with the allegro core library, so pkg-config --libs
would yield -lalleg_main -lalleg
.
Any thoughts on this:
- Quick fix (once I've sorted out monolith), or
- Roll it into the core?
allegro_main really isn't an add-on in the normal sense of, say, allegro_audio - it's just a shim to make things work properly on all platforms without code changes.
Personally I would be okay with allegro_main always being a separate library and static, even when compiling a dynamic monolith. It doesn't really make much sense being in the core, I don't think.
On @trentg 's comments,
It seems to me that homebrew is designed to support the Unix way of organising things, separating /bin and /lib directories for example. In addition there's the 'bundle' approach which I'd say is more Mac-like. It's certainly possible to use homebrew-provided libraries to make bundles but it's sort-of swimming against the tide a bit. If I were making a Mac app I'd go for static linking first, otherwise (embeddable) frameworks, rather than trying to work with homebrew's dylibs. I'd love to hear your input Trent you've had far more experience than me on these things. What we really need is the canonical example on how best to package an Allegro game for Mac (maybe Cosmic Protector is already it, I'm not sure)
@fatcerberus Apple do seem to deprecate things very aggressively in the SDK compared to MS - but once built, the backward compatibility is good. Anyway Allegro should shoulder all that pain for you :grin:
It doesn't really make much sense being in the core, I don't think.
Yes sorry I didn't mean make it part of the core, that would be no better than the current situation. What I meant was just make pkg-config always pull in alleg_main when asked for the allegro libs. This applies to OSX, on other platforms it could stay as it is, or it could pull in the current 'do-nothing' alleg_main.
When I mentioned homebrew, it was only because the a.cc thread was trying to use it to make bundles. That was essentially the original problem, which might not be fixed completely by making a static allegro_main. I'm Ok with that though... I don't think if you're putting any effort into your game you're going to use homebrew libraries in a bundle if only for the fact that it includes a ton of stuff you probably wouldn't even be using (third party libraries and addons.) Personally I've always used static linking.
I guess at worst this fix would ALLOW using homebrew, you just still have to mess with install_name_tool and stuff.
Is static linking considered the norm on OS X? On Linux it's practically blasphemous.
It is normal on OS X yes, very few libraries install globally. At the least embedded frameworks are also common. On Linux, things might change since Ubuntu is planning on using a type of static linking for all installed applications soon to make maintenance easier (or just create a whole different set of problems...)
So it seems like the solution would be to also build a static version of Allegro for homebrew? I could ask homebrew folks if they would be okay with it (after all, they do have to pay for the servers that build the binaries).
I don't understand the point about pkg-config. Does that even work on OSX?
I think the idea was to just build allegro_main statically - the rest can remain dynamic since they don't cause issues.
From my understanding, if you want to create a bundle, then it's easiest to link allegro_main statically. For non-bundle programs, dynamically linked allegro_main seems to work fine.
That said, Allegro builds the demos as bundles and they seem to work fine with a dynamic allegro_main as well, so I still don't quite get what is different between what is done for demos and what is done when making a bundle manually.
The original problem was that Xcode, when deploying, strips the symbols from the executable so the mangled main can't be found. In development mode it's fine, when making a 'UNIX-style' application it's fine. On Sat, 6 Feb 2016 at 22:28, SiegeLord [email protected] wrote:
From my understanding, if you want to create a bundle, then it's easiest to link allegro_main statically. For non-bundle programs, dynamically linked allegro_main seems to work fine.
That said, Allegro builds the demos as bundles and they seem to work fine with a dynamic allegro_main as well, so I still don't quite get what is different between what is done for demos and what is done when making a binary manually.
— Reply to this email directly or view it on GitHub https://github.com/liballeg/allegro5/issues/555#issuecomment-180874773.
I looked a bit closer at what Allegro does for its demo bundles. Indeed, it creates them sort of fine with dynamically linked allegro_main, but it uses absolute paths, so it's not quite ready for distribution. That said, I tried using https://github.com/auriamg/macdylibbundler which tries to automatically copy over things into the bundle and fix up the paths, and that seemed to work just fine. I think the difference is that CMake constructs the bundles manually and maybe it doesn't do the symbol stripping.
So overall, it seems like to me that it's simplest and best to just also provide the entirety of Allegro statically linked, and depending on what's easier, let the user choose whether or not to link allegro_main statically.
Hi it's Malcolm. Sorry I didn't realize the conversation was continuing here. Providing a set of static libraries would be great! Fixing the rpath on the dynamic libraries via cmake and also having a static main library is also great!
With regards to why the examples work ok, I can't remember .. But my guess is if you don't specify to use xcodebuild as the tool chain in cmake then it defaults to using gcc? and a different linker ?
Regards Malcolm
All, Here's the link to my latest effort .. which include my own instructions on how to build Allegro on OSX. Note that I stripped out all the dependencies that I don't use .. e.g. FLAC .. but its still quite complex. Thomas commented on my post that we should look at Cocoapods to automate the dependencies. Has anyone tried this before? I must say that Nuget on Windows is so simple in comparison !
Malcolm
http://www.stardot.org.uk/forums/viewtopic.php?f=44&t=9065&start=90
how is this still not fixed?
It was considered that the workaround (macdylibbundler) was good enough for now, but in fact recently I've seen people have trouble with it. The way forward is to build Allegro statically on homebrew, which requires fixing https://github.com/liballeg/allegro5/issues/773 at the very least.
@SiegeLord so i'm busy creating a dynamic library on osx which statically links to allegro5 but the problem is when you call the new dynamic lib and try and link it, it cries because there is no main. dlopen(libs/lib1-opengl/libOpenGL.so, 8): Symbol not found: __al_mangled_main Referenced from: /nfs/zfs-student-6/users/tmack/.brew/opt/allegro/lib/liballegro_main.5.2.dylib Expected in: flat namespace in /nfs/zfs-student-6/users/tmack/.brew/opt/allegro/lib/liballegro_main.5.2.dylib
and if I take out the linking of the allegro main function no window shows but the program logic works, because it detects the snake crashing into a wall?
all my code and suff is here, under lib/lib1-opengl https://github.com/tonmanayo/nibbler
I know "+1" message are bad etiquette, but it's 2020 already.. :-(
Err... sadly I never got around to testing tonmanayo's code so my answer remains the same, use macdylibbundler
. Since then, we wrote a tutorial about how to do that, and as far as I know, that's been working okay: https://github.com/liballeg/allegro_wiki/wiki/Creating-macOS-bundles
I note that #773 has been fixed, so perhaps the static linking works okay too, but then you need to compile Allegro yourself rather than using homebrew
.
And either way, no matter what you do you never have to use allegro-main
, you can use al_run_main
directly.
Please feel free to give me specifics though, I can try to figure out what's the best solution in your case.
For anyone facing this, the getting started mentions the signature and format of the main function needed when linking allegro
https://liballeg.org/a5docs/5.2.4/getting_started.html
For the purposes of cross-platform compatibility Allegro puts some requirements on your main function. First, you must include the core header (allegro5/allegro.h) in the same file as your main function. Second, if your main function is inside a C++ file, then it must have this signature: int main(int argc, char **argv). Third, if you're using C/C++ then you need to link with the allegro_main addon when building your program.