如何使用autotools设置项目,以便生成的可执行文件可以查看所需的二进制文件?

时间:2015-03-14 11:51:18

标签: c autotools autoconf automake allegro

我正在使用c来处理一些针对allegro和使用的代码 autotools来处理构建系统。麻烦是代码正在尝试 拉入位图,我不知道如何正确处理这个问题 使用autotools。

我的项目布局:

allegro-learning/
    Makefile.am
    README
    configure.ac
    src/
        stargate.c
        stargate.bmp

stargate.c中的代码用以下内容拉入位图:

stargate = load_bitmap("stargate.bmp", NULL);

allegro-learning / configure.ac的内容:

AC_PREREQ([2.69])
AC_INIT([allegro-learning], [1.0], [itsjustme@gmail.com])
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

allegro-learning / Makefile.am的内容:

SUBDIRS = src
dist_doc_DATA = README

allegro-learning / src / Makefile.am的内容:

bin_PROGRAMS = stargate

stargate_SOURCES = stargate.c
stargate_CFLAGS = $(ALLEGRO_CFLAGS) 
stargate_LDFLAGS = $(ALLEGRO_LIBS) 

当我使用autotools构建和安装时:

# autoreconf --install
# ./configure --prefix=$HOME/usr
# make
# make install

并运行生成的stargate可执行文件所有段错误。破解它 用GDB打开显示失败就在我上面强调的那一行(来自stargate.c),它引入了stargate.bmp。

然而,当我只是去allegro-learning / src并且只是构建 直接没有使用autotools:

# cd allegro-learning/src
# gcc `pkg-config allegro --cflags --libs` -o stargate stargate.c

runnig可执行文件正常。这让我相信我没有使用autotools正确设置项目来安装位图,因此可执行文件可以在安装后找到它们。

这样做的正确方法是什么?

我咨询了Autotools,看起来在使用autotools和java时安装jar是一个类似的问题,你必须安装.jar文件,并且可以让执行代码看到。但是他的例子嵌入了一个让我感到困惑的更大的项目中。

我也看过Data Files With Automake,但我仍然不确定如何修改我的项目,以便生成的可执行文件可以找到位图。事实是,我不确定stargate.bmp是否有资格作为autotools Universe中的“数据文件”。或许有一种不同的方式来处理这种情况?

关于如何处理这种情况的任何具体指导都是 非常感谢。

2 个答案:

答案 0 :(得分:2)

在这里回答我自己的问题。在automake mailing lists上进行了一些互动后,我找到了问题的解决方案并进行了以下调整:

到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) 

到stargate.c我添加了以下内容:

#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;
}

现在我替换原来的

stargate = load_bitmap("stargate.bmp", NULL);

用,

stargate = load_bitmap(addImageBaseDir("stargate.bmp"), NULL)

使用autotools构建现在可以正常工作。

答案 1 :(得分:0)

这不是您问题的直接答案,但作为设置数据的已知位置的替代方法,您可能需要考虑将数据简单地编译到可执行文件中,以便不需要查找外部文件

您可以使用objcopy -I binary -O elf64-x86-64 -B i386 stargate.bmp stargate.o来生成包含stargate.bmp数据的目标文件(当然,如果您想要可移植性,则必须适当调整输出架构)。然后,如果将这些对象文件链接到可执行文件中,则可以使用符号_binary_stargate_bmp_start_binary_stargate_bmp_end来指出数据的开头和结尾,可以传递给图像加载函数。例如,您可以使用以下数据生成FILE *

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");