Hi,
I'm writing a cross-platform game browser tool, one of the platforms being DOS, and as such, am using Allegro 4.2 for the graphics handling on that platform (others being SDL for Linux, GEM/VDI for Atari ST, etc).
When I'm linking my code using liballeg.a I get loads of multiple definition errors:
I've got a couple of object files that do a #include <allegro/gfx.h> or #include <allegro/keyboard.h>, but why does this cause multiple definition errors?
Anyone else still using Allegro with more modern compilers for DOS? I've tried both GCC 5.5.0 and 7.2.0 as per (https://github.com/andrewwutw/build-djgpp/releases), but there's no difference in behaviour.
Allegro 4.2.2 is built for DOS from (https://github.com/msikma/allegro-4.2.2-xc).
It's years and years since I did any dabbling with Allegro - is the intention to only include any allegro headers only once, and in one place?
John
Try defining ALLEGRO_STATICLINK before including allegro 4 or link to the dynamic library and see if it goes away.
Thanks for the suggestion, unfortunately it doesn't appear to make any difference; both passing -DALLEGRO_STATICLINK to GCC, and also setting it manually around the include blocks for allegro.h:
#ifdef USE_ALLEGRO
#define ALLEGRO_STATICLINK
#include <allegro.h>
#endif
No joy.
I think the problem stems from having code in those allegro 4 header files, both in the inline headers in allegro/inline/*, but also in things like allegro/system.h (e.g. install_allegro is a function rather than just a prototype).
This makes me think I can't really use any part of Allegro unless it's in one, singular object file, am I right?
No, thankfully that's not how allegro works.
This is besides the point but you need to include the header for toupper, otherwise that function links to nothing. #include <ctype.h>
C will bite you like that.
When compiling statically, you also need to link to the following libraries :
-lkernel32
-luser32
-lgdi32
-lcomdlg32
-lole32
-ldinput
-lddraw
-ldxguid
-lwinmm
-ldsound
-static-libstdc++
-static-libgcc
But that won't get rid of the redefinition errors.
First, STATICLINK=1 is a flag passed to make when building allegro. If you're linking to liballeg.a, that is the dynamic allegro library, the static one would be liballeg_s.a, which you would link to with -lalleg_s. Since you're not doing that, don't define ALLEGRO_STATICLINK either. The problem is something else.
I'm trying to think what it is.
You might want to spend some time reading docs\build\mingw32.txt for some steps of the build process. They apply to DOS as well. You can get a .chm doc for 4.2.2 here :
https://download.tuxfamily.org/allegro/allegro-manual//4.2.2/allegro-manual-4.2.2.en.chm
Those are the latest docs for the 4.2.2 build process, which was abandoned in favor of cmake for Allegro 4.4 and also when DOS support was dropped. But you probably know that, so...
EDIT
From this : https://www.allegro.cc/forums/thread/599393/797084#target it seems it might have something to do with the C standard being used by your compiler. Try -std=c89 and see if that fixes it.
Thanks for the tips, however, unless I'm completely mistaken when building the DOS target for liballegro the only option is a static library (unless I've missed something); DOS doesn't have a dynamic loader like Unix or Windows, so a .a file is the only thing you can create that makes any sense. Certainly the .a file I've got is a plain old ar archive, not a shared library.
In terms of link options for my code, it's a pure DOS allegro library and my cross compiler (i586-pc-msdosdjgpp) targets pure DOS as well (via either 5.5.0 or 7.2.0 djgpp version of GCC), it's not wingw32 or anything like that, so there's no linking with Windows dll's, for now that's just libc.a and liballeg.a:
I must be missing something obvious here - I'm going to go right back to the version of GCC that Allegro was bundled with back in the days of DOS; I think it hung around v2.95 number for a very long time. Maybe something has broken with the modern binutils stuff?
---
Edit: Your link to that old post was a good one - although changing the C dialect looked at first to be disastrous (adding -std=c89 basically caused everything else to error out - I have examples of the later dynamic malloc calls, c++ style commenting, etc. etc.), it helped greatly in tracking down the actual cause; the inline functions in the headers.
One of the original commenters mentioned about a change in extern inline handling in c99, and sure enough, it's detailed here:
https://gcc.gnu.org/onlinedocs/gcc/Inline.html
The short version is that if compiling against Allegro 4.x on something more modern than GCC 2.x (which, if you're doing any DOS work these days, you'd be nuts for using so old a version of GCC), you need to pass the option -fgnu89-inline.
Otherwise, it will never work due to the inline functions in the headers.
I don't know how well this plays with other libraries, so your mileage may vary in that regard.
Here's the output:
... /usr/i586-pc-msdosdjgpp/bin/i586-pc-msdosdjgpp-gcc -Wall -Wno-unused-function -Wno-unused-variable -march=i386 -mtune=i386 -mfpmath=387 -fgnu89-inline -O3 -I/usr/i586-pc-msdosdjgpp/i586-pc-msdosdjgpp/sys-include -DDOS -DALLEGRO_STATICLINK -DUSE_ALLEGRO -DDIR_SEP=\"\" -DGAMEDIR=\"C:\GAMES\" -DCSV_FILE=\"MENU.CSV\" -DALLEGRO_NO_COMPATIBILITY -DSTATICLINK=1 -DUSE_LOGGING -DLOGGING -c -o src/gamedata.o src/gamedata.c ... Linking.... /usr/i586-pc-msdosdjgpp/bin/i586-pc-msdosdjgpp-gcc -Wall -Wno-unused-function -DUSE_LOGGING -DLOGGING -g -o bin/menu_dos.exe src/menu.o src/logging.o src/input.o src/image.o src/qdbmp.o src/gfx.o src/bmp2text.o src/csvlib.o src/gamedata.o -L/usr/i586-pc-msdosdjgpp/i586-pc-msdosdjgpp/lib -lalleg $ ls -l bin/menu_dos.exe -rwxr-xr-x 1 megatron users 433952 Feb 18 20:13 menu_dos.exe $ file bin/menu_dos.exe bin/menu_dos.exe: MS-DOS executable, COFF for MS-DOS, DJGPP go32 DOS extender
I'm sorry, that was really more mingw advice, which I guess doesn't apply to DOS. I never really actually compiled anything for DOS, except for my very first programs with allegro. Glad you figured it out though.