3

我正在从事一个 autotools 项目,并且是 autotools 世界的新手。出于各种原因,为了完整起见,在底部进行了详细说明,我有一个 shell 脚本,我想从中获取输出以在我的 makefile 中使用。

我有类似以下的情况。AC_CONFIG_FILESAutoconf 从命令生成脚本。例如

AC_CONFIG_FILES([thescript], [chmod +x thescript])

脚本.in

#!/bin/sh
# -*- sh -*-
# @configure_input@
echo @abs_top_builddir@/bar/foo

我真正想做的是使用返回的任何内容@abs_top_builddir@/bar/foo在我的 Makefile 中使用。我想在生成时在变量中提供这个值,并能够在我的 Makefile.am 中访问它,比如$(FOOPLACE). 我怎样才能做到这一点?

我需要这个/额外信息的原因

这个问题与我以前的问题有关:

如何在 autoconf configure.ac 中获取顶级构建目录的绝对路径?

该项目需要一个具有自己的 makefile 和 configure.ac 的子项目。子项目是用于为主项目生成源文件的程序。有一个选项可以禁用此项目的构建并尝试使用已安装的版本。在这种情况下,已安装版本的位置在变量FOOPLACE(uisng AC_PATH_PROG) 中提供。当我使用本地构建的版本时,我想把它的位置放在里面FOOPLACE。然后在 Makefile.am 中将该变量用作$(FOOPLACE).

autoconf 中似乎有一个错误,这意味着 abs_top_builddir 可以访问的唯一位置是在配置AC_CONFIG_FILES时生成的配置文件中。在链接的问题中有详细说明我为什么要这样做。

4

3 回答 3

5

写的问题

在您的 Makefile.am 中,您可以执行以下操作:

foo.c: foo.in
        FOOPLACE=`./thescript`; $(FOOPLACE) -c -o $@ $<

这样做的好处是在可移植的 Makefile 代码中不需要 GNU 主义。

正确而艰难的道路

我准备了一个使用名为mkfoo. 它可以使用内部副本或主机系统上的副本。

我们先来看看configure.ac

AC_PREREQ([2.67])
AC_INIT([parent], [0], [jack@jackkelly.name])
AM_INIT_AUTOMAKE([foreign])

AC_ARG_WITH([mkfoo],
  [AS_HELP_STRING([--with-mkfoo],
    [Path to mkfoo, "external", "internal", or "check" @<:@check@:>@])],
  [MKFOO=$withval],
  [with_mkfoo=check])
AS_IF([test "$with_mkfoo" = check -o "$with_mkfoo" = external],
  [AC_PATH_PROG([MKFOO], [mkfoo], [no])])
AS_IF([test "$with_mkfoo" = external -a "$MKFOO" = no],
  [AC_MSG_ERROR([External mkfoo demanded, but not found.])])

dnl We conditionally set MKFOO in Makefile.am
AM_SUBST_NOTMAKE([MKFOO])

AM_CONDITIONAL([USE_INTERNAL_MKFOO],
  [test "$with_mkfoo" = internal -o "$MKFOO" = no])
AM_COND_IF([USE_INTERNAL_MKFOO], [AC_CONFIG_SUBDIRS([mkfoo])])

AC_CONFIG_FILES([Makefile src/Makefile])
AC_OUTPUT

这里发生了一些事情:

  1. 默认行为是“检查 mkfoo,如果不存在,则构建并使用捆绑的副本”。还要注意它支持--with-mkfoo=PATH(用户可能在一个奇怪的地方安装了一个副本),--with-mkfoo=internal(distcheck 需要,我们想要测试所有东西)和--with-mkfoo=external(对不喜欢捆绑子项目的包维护者的善意)。
  2. AM_SUBST_NOTMAKE([MKFOO])停止在中automake生成一行表格MKFOO = @MKFOO@Makefile.in我们需要有条件地完成这项任务。
  3. 我们设置了一个自动生成条件,因为我们需要为内部/外部mkfoo内部做不同的事情Makefile.am
  4. 我们mkfoo有条件地配置目录。

现在,顶层Makefile.am

if USE_INTERNAL_MKFOO
SUBDIRS = mkfoo
DIST_SUBDIRS = mkfoo
else
SUBDIRS =
DIST_SUBDIRS =
endif
SUBDIRS += src
DIST_SUBDIRS += src

## Need to make sure the internal tools work during distcheck.
DISTCHECK_CONFIGURE_FLAGS = --with-mkfoo=internal
dist-hook:
if ! USE_INTERNAL_MKFOO
        cp -fpR $(srcdir)/mkfoo $(distdir)
endif

这里发生了什么:

  1. 有条件地递归到mkfoo,并在之前做src,这需要$MKFOO
  2. 因为有次连配置mkfoo都没有,可能就没有了。这意味着我们已经坏了(并且通过扩展,)。所以我们也必须有条件地设置,如果我们没有配置,确保它的分布式成为我们的责任。Makefilemake distmake distcheckDIST_SUBDIRSmkfoo
  3. 当我们make distcheck想要使用内部副本时,因为最好使用源 tarball 中的所有内容。

现在,src/Makefile.am

if USE_INTERNAL_MKFOO
MKFOO = $(abs_top_builddir)/mkfoo/mkfoo
else
MKFOO = @MKFOO@
endif

bin_SCRIPTS = foo
CLEANFILES = foo
EXTRA_DIST = foo.in

foo: foo.in
        $(MKFOO) < $< > $@

除了 的条件赋值之外,这里没有什么令人震惊的MKFOO

src/foo.in

I am foo.in!

现在为子包。mkfoo/configure.ac

AC_PREREQ([2.67])
AC_INIT([mkfoo], [0], [jack@jackkelly.name])
AM_INIT_AUTOMAKE([foreign])
AC_PROG_CC
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

如您所见,没有什么特别的。怎么样mkfoo/Makefile.am

bin_PROGRAMS = mkfoo

mkfoo/mkfoo.c

#include <stdio.h>
int main(int argc, char *argv[]) {
  puts("Internal mkfoo.");
  return 0;
}

只是一个虚拟测试程序。

于 2013-03-05T06:06:13.430 回答
0

Makefile.am 中的以下行不适用于什么?

FOOPLACE=$(shell @abs_top_builddir@/thescript)
于 2013-03-04T17:51:13.887 回答
0

FOOPLACE似乎是由它在条件中存在于 configure.ac 中创建的,即使条件不正确(有关详细信息,请参阅链接的问题)。因此它存在,但在制造时是空的。似乎变量不能在 Makefile.am 中重新定义,但是,它们可以附加到。由于FOOPLACE是空的,因此脚本的输出可以使用以下内容添加到其中。

FOOPLACE+=$(shell $(abs_top_builddir)/thescript)
于 2013-03-04T20:22:51.750 回答