Reputation: 445
I'm using c to work on some code building against allegro and using autotools to handle the build system. Trouble is the code is trying to pull in a bitmap and I'm not sure how to handle this properly when using autotools.
The layout of my project:
allegro-learning/
Makefile.am
README
configure.ac
src/
stargate.c
stargate.bmp
The code in stargate.c pulls in the bitmap with:
stargate = load_bitmap("stargate.bmp", NULL);
Contents of allegro-learning/configure.ac:
AC_PREREQ([2.69])
AC_INIT([allegro-learning], [1.0], [[email protected]])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AC_CONFIG_SRCDIR([config.h.in])
AC_CONFIG_HEADERS([config.h])
AC_PROG_CC
AM_PROG_CC_C_O
PKG_CHECK_MODULES([ALLEGRO], [allegro >= 4.2.3])
AC_CHECK_HEADERS([stdio.h])
AC_CONFIG_FILES([Makefile
src/Makefile])
AC_OUTPUT
Contents of allegro-learning/Makefile.am:
SUBDIRS = src
dist_doc_DATA = README
Contents of allegro-learning/src/Makefile.am:
bin_PROGRAMS = stargate
stargate_SOURCES = stargate.c
stargate_CFLAGS = $(ALLEGRO_CFLAGS)
stargate_LDFLAGS = $(ALLEGRO_LIBS)
When I use autotools to build and install:
# autoreconf --install
# ./configure --prefix=$HOME/usr
# make
# make install
and run the resulting stargate executable everything segfaults. Cracking it open with GDB shows the failure is on the line I've highlighted above (from stargate.c) that pulls in stargate.bmp.
However, when I just go to allegro-learning/src and just build directly w/o using autotools:
# cd allegro-learning/src
# gcc `pkg-config allegro --cflags --libs` -o stargate stargate.c
runnig the executable works fine. That leads me to believe I haven't setup the project properly with autotools to install the bitmaps so the executable can find them post-install.
What is the right way to do this?
I have consulted Autotools and it looks like installation of jars when using autotools with java is a similar problem where you have .jar files that must also get installed and be available for the executing code to see. But his example is embedded in a much larger project that is confusing to me.
I've also looked at Data Files With Automake but I'm still unsure as to how I should modify my project so the resulting executable can find the bitmap. Truth is I'm not sure if stargate.bmp qualifies as a 'data file' in the autotools universe. Perhaps there is an all together different way to handle such situations?
Any specific guidance on how to handle situations like this would be most appreciated.
Upvotes: 1
Views: 406
Reputation: 25855
This is not a direct answer to your question, but as an alternative to setting up known locations for data, you may want to consider simply compiling the data into your executable, so that there are no external files that it needs to find.
You can do this using objcopy -I binary -O elf64-x86-64 -B i386 stargate.bmp stargate.o
to produce an object file containing the data of stargate.bmp
(you'd have to adjust the output architecture appropriately if you want portability, of course). Then, if you link those objects file into the executable, the symbols _binary_stargate_bmp_start
and _binary_stargate_bmp_end
will be available to point out the start and end of the data, available to be passed to your image loading functions. For example, you could produce a FILE *
with the data like this:
extern char _binary_stargate_bmp_start, _binary_stargate_bmp_end;
FILE *imgstream = fmemopen(&_binary_stargate_bmp_start, &_binary_stargate_bmp_end - &_binary_stargate_bmp_start, "r");
Upvotes: 1
Reputation: 445
Answering my own question here. After some interactions on the automake mailing lists I found a solution to my question and made the following adjustments:
To allegro-learning/src/Makefile.am:
stargatedir = $(datadir)/stargate
stargate_DATA = stargate.bmp
stargate_SOURCES = stargate.c
stargate_CFLAGS = $(ALLEGRO_CFLAGS) -DPKGDATADIR=\"$(stargatedir)\"
stargate_LDFLAGS = $(ALLEGRO_LIBS)
To stargate.c I added the following:
#include <stdio.h>
// for nice string concatenation:
#define Sasprintf(write_to, ...) { \
char *tmp_string_for_extend = (write_to); \
asprintf(&(write_to), __VA_ARGS__); \
free(tmp_string_for_extend); \
}
char* addImageBaseDir(char* filename) {
char *abspath = NULL;
Sasprintf(abspath, PKGDATADIR);
Sasprintf(abspath, "%s%s%s", abspath, "/", "stargate.bmp");
return abspath;
}
and now I replace the original,
stargate = load_bitmap("stargate.bmp", NULL);
with,
stargate = load_bitmap(addImageBaseDir("stargate.bmp"), NULL)
and building with autotools now works just fine.
Upvotes: 2