如何在制作时将Shell脚本输出到Makefile.am中?

cro*_*bar 3 automake autoconf autotools

我正在从事一个自动工具项目,并且是自动工具领域的新手。由于种种原因,为了完整起见,在底部进行了详细说明,我有一个Shell脚本,我想从中获取输出以用于我的makefile。

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

AC_CONFIG_FILES([thescript], [chmod +x thescript])
Run Code Online (Sandbox Code Playgroud)

主题

#!/bin/sh
# -*- sh -*-
# @configure_input@
echo @abs_top_builddir@/bar/foo
Run Code Online (Sandbox Code Playgroud)

我真正想要做的是使用@abs_top_builddir@/bar/fooMakefile中返回的任何内容。我想在make时使该值在变量中可用,并且能够在我的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。在链接的问题中有我为什么要这样做的详细信息。

Jac*_*lly 5

书面问题

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

foo.c: foo.in
        FOOPLACE=`./thescript`; $(FOOPLACE) -c -o $@ $<
Run Code Online (Sandbox Code Playgroud)

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

正确而艰难的方法

我准备了一个使用名为的工具的虚拟包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
Run Code Online (Sandbox Code Playgroud)

这里发生了一些事情:

  1. 默认行为是“检查mkfoo,如果不存在,请构建并使用捆绑的副本”。还请注意,它支持--with-mkfoo=PATH(用户可能在一个奇怪的地方安装了副本),--with-mkfoo=internal(需要distcheck,我们要在其中进行所有测试)和--with-mkfoo=external(对不喜欢捆绑子项目的软件包维护者的一种好感)。
  2. AM_SUBST_NOTMAKE([MKFOO])停止automake从生成线的形式的MKFOO = @MKFOO@Makefile.in。我们需要有条件地进行该分配。
  3. 我们设置有条件的自动make,因为我们需要对内部/外部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
Run Code Online (Sandbox Code Playgroud)

这里发生了什么:

  1. 有条件地递归mkfoo并在src需要之前进行$MKFOO
  2. 因为有次mkfoo甚至没有配置,也可能没有Makefile。这意味着我们已经破产了make dist(并扩展为make distcheck)。因此,我们还必须DIST_SUBDIRS有条件地进行设置,如果没有进行mkfoo配置,请确保将其分发成为我们的责任。
  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) < $< > $@
Run Code Online (Sandbox Code Playgroud)

除了的条件赋值外,这里没有其他令人震惊的地方MKFOO

src/foo.in

I am foo.in!
Run Code Online (Sandbox Code Playgroud)

现在为子包。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
Run Code Online (Sandbox Code Playgroud)

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

bin_PROGRAMS = mkfoo
Run Code Online (Sandbox Code Playgroud)

mkfoo/mkfoo.c

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

只是一个虚拟测试程序。