Hi there,
I am trying to statically link Allegro 5 using pkg-config in Ubuntu. I have been using the following example program as a test:
Here is the command I use to compile it (not statically):
g++ -Wall -o example example.cpp $(pkg-config --libs allegro-5 allegro_image-5 allegro_primitives-5)
du -h example returns 16K as the file size. Now when I try to compile it with static libraries:
g++ -Wall -o example example.cpp $(pkg-config --libs --static allegro-5 allegro_image-5 allegro_primitives-5)
And du -h example still returns 16K as the file size! Shouldn't the file size be considerably larger when statically compiled? Because the file size doesn't change, this leads me to believe that something isn't right. Is there something I'm supposed to do when making Allegro to make sure I can link it statically?
Thanks in advance!
The static libraries are all named *-static-5, so try for example:
$(pkg-config --libs --static allegro-static-5 allegro_image-static-5 allegro_primitives-static-5)
The static libraries are all named *-static-5
Wow, I feel like an idiot... Sure enough, that did the trick. Thanks, Elias!
Well, ideally we could tell pkg-config to either not require the --static when you use a static library, or automatically pick the -static version when you use --static. However it seems there is no way around requiring both (and if you forget one or the other things fail in non-obvious ways).
That would be nice, but the way it currently works will suffice.
Someone please tell me, what good is it to use pkg-config when you have to type more to use it, and not less?
Someone please tell me, what good is it to use pkg-config when you have to type more to use it, and not less?
I don't know your definition of "more", but...
$ pkg-config --libs --static allegro -lalleg -lm -lpthread -lrt -lSM -lICE -lX11 -lXext -lXcursor -lXpm -lXxf86vm -ldl
You guys were making it look like you had to type every addon library out by hand. Can you still use the monolith on Linux?
You can use the monolith, yes. But even with the single ones some of them may have extra dependencies which you don't have to remember that way. There is also --cflags in addition to --libs and some addons may require extra flags, for example if you compiled with a dependency with a non-standard include path. Basically all compiler and linker flags are handled by pkg-config instead of yourself.
I'd much rather output pkg-config into an environment variable and then specify that instead. So much work!
Using pkg-config is the only way I know to link Allegro in Linux. How would you do it without pkg-config, and what would be the benefits of doing so (aside from less typing, as you suggested, Edgar)?
Linux is just gcc (most the time) so it's as simple as typing out the commands that pkg-config spits out. Notably, pkg-config fails to output '-static' despite gcc preferring dynamic libraries over static ones, even when you specify a static library.
I'm going to give this a try as well. Eric, which cmake option did you use to generate the allegro-static libraries in the first place?
edit:
I figure it should be
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DWANT_STATIC_RUNTIME=on
I pretty much followed the standard procedures, but used ccmake to turned shared to off. Here's the gist of it:
Update everything:
sudo apt-get install updates
Install required dependencies:
sudo apt-get install build-essential git cmake cmake-curses-gui xorg-dev libgl1-mesa-dev libglu-dev -y
Install additional/optional dependencies:
sudo apt-get install libpng-dev libcurl4-openssl-dev libfreetype6-dev libjpeg-dev libvorbis-dev libopenal-dev libphysfs-dev libgtk2.0-dev libasound-dev libpulse-dev libflac-dev libdumb1-dev - y
Install documentation dependencies, too, if you plan on building docs:
apt-get install exuberant-ctags dvi2ps dvipdfmx latex2html pandoc
Clone Allegro 5:
git clone https://github.com/liballeg/allegro5 && cd allegro5
Make a build directory and navigate to it:
mkdir build && cd build
Use ccmake:
ccmake -DCMAKE_INSTALL_PREFIX=/usr ..
In the above, create and generate, then turned shared to "OFF" (just follow the prompts).
Make and install Allegro:
make && sudo make install && sudo ldconfig
Now everything should be good to go. When compiling, use something like this:
g++ -o example example.cpp $(pkg-config --libs --static allegro-static-5 allegro_image-static-5)
So don't forget the allegro*-static-5 and --static parts.
Doing all of the above resulted in an executable that worked on a fresh installation of Ubuntu 16.04. On that fresh install, I had to install libdumb1 and libopenal1 before running the game though. Maybe those could be statically packaged in as well, but I'm too lazy for that.
So should I use
cmake -DWANT_STATIC_RUNTIME=on
or
cmake -DSHARED=off
or both?
And didn't you also have to compile with a symbol, i.e. something like gcc .... -DALLEGRO_STATICLINK=1
After running ccmake, I went straight into make. I followed a combination of wiki articles and some general screwing around to get it to work. I used pkg-config, so I didn't do anything special beyond what I already mentioned.
[EDIT]
Here is the official README_pkgconfig.txt, in case you go that route.
I've tried it using Eric's guidelines, but it seems hardly worth the effort. When I run ldd on the resulting binaries, only the allegro libraries themselves are statically included. But all of allegro's dependencies are still as shared libraries. Meaning that the binary isn't portable to systems that don't have all these dependencies installed. I had expected dependencies such as libogg, libvorbis etc. to be statically linked as well.
Here is the full output of ldd on my krampushack entry:
ldd build/release/game (Without static linking): 88 lines
ldd build/static/game (83 lines)
edit: I can get it to include ldumb the following way.
Starting from the line
$(pkg-config --libs --static $(ALLEGRO_LIBS))
which for me expands to:
-L/usr/local/lib -lallegro_primitives-static -lallegro_main-static -lallegro_dialog-static -lgtk-x11-2.0 -lgdk-x11-2.0 -lpangocairo-1.0 -latk-1.0 -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lpangoft2-1.0 -lpango-1.0 -lgobject-2.0 -lglib-2.0 -lfontconfig -lfreetype -lgthread-2.0 -lglib-2.0 -lallegro_image-static -lpng -lz -ljpeg -lallegro_acodec-static -lFLAC -logg -ldumb -lvorbisfile -lvorbis -logg -lallegro_audio-static -lpulse-simple -lpulse -lasound -lopenal -lallegro_ttf-static -lfreetype -lz -lallegro_font-static -lallegro-static -lm -lpthread -lSM -lICE -lX11 -lXext -lXcursor -lXi -lXinerama -lXrandr -lGLU -lGL
I changed that around like so:
-L/usr/local/lib -Wl,-Bstatic -lallegro_primitives-static -lallegro_main-static -lallegro_dialog-static -lallegro_image-static -lallegro_audio-static -lallegro_ttf-static -lallegro_font-static -lallegro_acodec-static -lallegro-static -ldumb -Wl,-Bdynamic -lgtk-x11-2.0 -lgdk-x11-2.0 -lpangocairo-1.0 -latk-1.0 -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lpangoft2-1.0 -lpango-1.0 -lgobject-2.0 -lglib-2.0 -lfontconfig -lfreetype -lgthread-2.0 -lglib-2.0 -lpng -lz -ljpeg -logg -lFLAC -lvorbisfile -lvorbis -lpulse-simple -lpulse -lasound -lopenal -lfreetype -lz -lm -lpthread -lSM -lICE -lX11 -lXext -lXcursor -lXi -lXinerama -lXrandr -lGLU -lGL
Now libdumb is also statically linked. Downside is that you can no longer use pkg-config, you have to manually run it and add the result to your makefile.
WANT_STATIC_RUNTIME does nothing in Linux I think, but in Windows it allows you to also link libc itself statically (I don't think that would make sense in Linux due to the kernel dependencies of libc).
One easy way to static link dumb is to rename the static library (libdumb_s.a instead of libdumb.a for example), then in cmake (I use cmake-gui) change the dumb library to libdumb_s.a. This way when cmake outputs -ldumb_s it is forced to static link it.
You have to mix -static and -shared into the command line, otherwise gcc defaults to shared libraries when linking.