|
al_mangled_main() issue OSX while creating a standalone bundle |
Malcolm Harrow
Member #15,833
December 2014
|
I'm running Xcode 7.2 on OSX El Capitan 10.11.1 I installed Allegro 5.1.12 using homebrew: I copied a simple program from the net, added in the include and lib directories from /usr/local, added to Build Phases the libraries and frameworks. Press the run button, the program compiled and ran perfectly ! See attached screenshots. Now I want to run the application standalone. I added the libraries to Copy Bundle Resources. I archive the application and run the standalone bundle. I get the dreaded message: Application Specific Information: dyld: launch, loading dependent libraries Dyld Error Message: Symbol not found: __al_mangled_main Referenced from: /usr/local/opt/allegro/lib/liballegro_main.5.1.dylib Expected in: flat namespace in /usr/local/opt/allegro/lib/liballegro_main.5.1.dylib Anyone any ideas how to fix this ? The declaration of main() looks ok, its: Project file and source code attached. Regards Edit: The output is attached. The error is now: i.e. its now referencing the dylib in the bundle correctly .. but still can't find al_mangled_main(). |
Bruce Pascoe
Member #15,931
April 2015
|
Did you link to allegro_main? This is required on OS X, unlike literally every other platform.
|
SiegeLord
Member #7,827
October 2006
|
I don't know of a solution just yet (it is super puzzling that it worked fine before you started creating a bundle, that shouldn't make a bit of difference!), but if you're stuck on this, you can always implementing the 'magic main' functionality yourself: #define ALLEGRO_NO_MAGIC_MAIN #include <allegro/allegro5.h> int real_main(int argc, char **argv) { al_init(); // ... } int main(int argc, char **argv) { return al_run_main(argc, argv, real_main); } Make sure not to link allegro_main addon in that case. That code will work cross platform. Ideally we'd fix your issue though... the whole point of the main addon is to make the above code unnecessary. EDIT: That said, I do wonder if this is somehow related to rpath stuff. Like I wonder if you do install_name_tool -add_rpath "@executable_path" liballegro_main.5.1.12.dylib or something along those lines, that it might fix itself? I.e. you're explaining to the main addon where it should look for your program? It doesn't really make sense to me, but maybe there's something to this. EDIT2: Also, perhaps try something along the lines of this: http://stackoverflow.com/questions/3954137/mac-how-to-export-symbols-from-an-executable/3963639#3963639 ? "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
Bruce Pascoe
Member #15,931
April 2015
|
Incidentally, why is magic main required on OS X anyway?
|
Elias
Member #358
May 2000
|
On OSX all API calls must be made on the main thread. When the very first version of the OSX port was written, either there was no way in objective C yet to call something on the main thread (today there is), or the person writing the port did not know how to do that. So instead they opted to create a new thread and run the user main there while doing all of Allegro's OSX API calls directly from the main thread. The magic main therefore is required to span the thread where the main() function is then run on. -- |
Peter Hull
Member #1,136
March 2001
|
I can reproduce this exactly. Is this something to do with stripping symbols? The loader will load up the A3 executable, then its dependent libraries including allegro_main. The main function is in allegro_main, which then has to find _al_mangled_main somewhere. It's in A3, of course, but in release mode the symbolic information has been taken out so it can't be found. This is conjecture, but it does explain why it works from within XCode because the symbols haven't been stripped. If you use the libraries from Homebrew, it's really geared towards Unix-style executables in /usr/local/bin and so on. For 'native' app bundles I'd recommend building Allegro yourself with CMake and using the static monolith library (or is there a download available?) Anyway, providing allegro_main as a dynamic library doesn't seem quite right to me. Finally to add to Elias's comment, the point is that Cocoa applications want to drop into a run loop on the main thread, which never returns (see typical 'non-allegro' main below) - so your code has to run in a second thread. It's the job of the main in allegro_main to start that second thread, and then start the event loop. If you ran allegro code in the main thread there's no guarantee it would process events properly (this was especially true of Allegro 4) and you'd get the beachball of death. // Typical main for a cocoa app int main(int argc, char *argv[]) { return NSApplicationMain(argc, (const char **) argv); }
|
SiegeLord
Member #7,827
October 2006
|
Peter Hull said: Anyway, providing allegro_main as a dynamic library doesn't seem quite right to me. What makes you say that? Do you think it's just poor form, or would it not work? In principle, back when I made my iOS app, I used the non-framework Allegro builds, as I found them a little easier to work with for whatever reason. I don't recall having too much trouble. In terms of homebrew, we can probably do whatever is best, but I sort of mirrored what the existing allegro script did. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
Peter Hull
Member #1,136
March 2001
|
SiegeLord said: What makes you say that? Mostly it's just the uneasy feeling that I don't quite understand the inner workings of dyld ... the thought of having main in a dynamically loaded module... . Also, what's in allegro_main should be just the equivalent of a couple of lines of code, so it makes more sense to me to have it statically linked, 'as if' you'd typed it into your main source code. So, no real reason, really. Unless Malcolm's linker problem is indeed caused by symbol stripping - in which case there's a good technical reason to have a statically linked allegro_main. Does that make sense?
|
Malcolm Harrow
Member #15,833
December 2014
|
Interactive build
Malcolms-iMac:MacOS malcolm$ pwd Release Build
Malcolms-iMac:MacOS malcolm$ cd ~/Desktop/A3\ 2016-01-03\ 11-35-50/A3.app/Contents/MacOS/ Something has removed the definition of __al_mangled_main from the executable. So next steps .. I should build allegro_main.a and static link that in the build process and see if that makes a difference ? Regards PS - I'm live in Singapore, 13h ahead NYC, so expect a delay in replies.:D. I'm so grateful for the responses .. thank you !! |
Peter Hull
Member #1,136
March 2001
|
Malcolm, [edit]
|
Bruce Pascoe
Member #15,931
April 2015
|
Now the question is, why does the linker think it's okay to strip out the mangled main in the first place?
|
Peter Hull
Member #1,136
March 2001
|
I suppose it strips all symbols from the executable because it 'knows' they won't be used. Or there may be another explanation I haven't thought of. [edit] What I mean is, it's normal to strip out symbols after linking, and al_mangled_main is not special to the linker in any way.
|
Malcolm Harrow
Member #15,833
December 2014
|
A way around the issue is to add an additional strip flag to keep the __al_mangled_main symbol. To do this use "-s filename" and create a file that contains a list of line separated symbols you want to keep. See attached screenshot. The file /Users/malcolm/test contains one line "__al_mangled_main". I wanted to see if the same thing happens on Linux. I installed a new copy of Ubuntu 14.0.3 on a new VirtualBox VM on my Mac. I installed the Ubuntu ppas as per the instructions. I compiled the simple program: 1#include <allegro5/allegro.h>
2#include <allegro5/allegro_color.h>
3#include <allegro5/allegro_font.h>
4#include <allegro5/allegro_ttf.h>
5
6int main(int argc, char **argv) {
7 al_init();
8 al_init_font_addon();
9 al_init_ttf_addon();
10
11 ALLEGRO_DISPLAY* display = al_create_display(640, 480);
12 //ALLEGRO_FONT* font = al_load_font("/Library/Fonts/Futura.ttc", 40, 0);
13 ALLEGRO_FONT* font = al_load_ttf_font("/usr/share/fonts/truetype/freefont/FreeSans.ttf", 40, 0);
14
15 al_clear_to_color(al_color_html("#FF9900"));
16 al_draw_text(font, al_color_html("#EFEFEF"), 320, 200, ALLEGRO_ALIGN_CENTER, "LOOK AT THIS!");
17 al_flip_display();
18 al_rest(5.0);
19
20 al_destroy_font(font);
21 al_destroy_display(display);
22
23 return 0;
24}
Compiled with: It runs fine. Result of "nm ./A3Linux": .. no al_mangled_main .. the program runs fine. If I strip the executable ("strip ./A3Linux") then all the symbols get stripped, the executable still works fine. Is the al_mangled_main() construct only used on OSX ? Regards |
Bruce Pascoe
Member #15,931
April 2015
|
Yes, the 'magic main' is apparently only needed on OS X due to threading requirements.
|
Peter Hull
Member #1,136
March 2001
|
My first thought on these types of issue is usually - what does SDL do? They do indeed have a libSDL2main.a, but, although it does something on Windows it doesn't do anything on OS X. SDL programs instead rely on SDL_PumpEvents being called (explicitly or implicity as by calling SDL_PollEvent) on a regular basis to handle system events. In other words they use their own run loop, which my (possibly faulty) memory tells me Apple recommended against.
|
SiegeLord
Member #7,827
October 2006
|
I feel like we should have just kept END_OF_MAIN() I'll play around with this at some point. In terms of symbols being stripped, we do have that __attribute__ ((visibility("default"))) for _al_mangled_main. Perhaps it's not cutting it anymore? "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
Bruce Pascoe
Member #15,931
April 2015
|
Maybe it has to be marked dllexport? (or whatever the gcc/clang equivalent is) That would prevent the linker from stripping it.
|
SiegeLord
Member #7,827
October 2006
|
I've submitted an issue so this doesn't get forgotten: https://github.com/liballeg/allegro5/issues/555 I'll look into it myself sometime this weekend. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
|