【问题标题】:How to include macro with common Autoconf macros?如何在常见的 Autoconf 宏中包含宏?
【发布时间】:2019-02-04 00:14:24
【问题描述】:

TL;DR

  • 为什么AC_DEFUN 会尝试扩展AC_PROG_CC
  • 为什么m4_define 定义的宏似乎没有展开?
  • 为什么在 configure.ac 中定义的宏与在另一个文件中定义并包含在内的宏的行为不同?

背景

我负责为大约六个不同的板子构建固件和库,这些板子都使用相同的嵌入式处理器。因为所有板卡都使用相同的处理器,所以有重要的通用配置(CCCXXCPPFLAGSCFLAGSCXXFLAGSLDFLAGS 等)和配方。对于固件,我使用自定义生成文件,其中包含一个通用配置文件,该文件定义了所有通用配置和配方。为了简化在开发人员的计算机上安装库和头文件,我使用 GNU Autotools 来安装这些库。但是,自定义 makefile 和 GNU Autotools 文件之间存在大量重复配置,因此我正在将固件迁移到 GNU Autotools。

目标

我希望尽可能少的样板。板的configure.ac 可能如下所示:

AC_INIT([mppt], [0.1.0])
AM_INIT_AUTOMAKE([foreign subdir-objects -Wall -Werror])
: ${CC='arm-none-eabi-gcc -specs=nosys.specs'}
AC_PROG_CC
AM_PROG_CC_C_O
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

库的configure.ac 可能如下所示:

AC_INIT([gcc-arm-none-eabi-samples], [4.7+])
AM_INIT_AUTOMAKE([foreign subdir-objects -Wall -Werror])
: ${CXX='arm-none-eabi-g++ -specs=nosys.specs'}
AC_PROG_CXX
: ${CC='arm-none-eabi-gcc -specs=nosys.specs'}
AM_PROG_AS
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
AC_PROG_RANLIB
AC_PROG_CXX_C_O
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

这些文件之间有很多共同的配置。我想在本地 include 目录中有一个文件,该文件定义了一个带有常见 Autoconf 宏的宏:

AC_DEFUN([TIVASDK],
[AM_INIT_AUTOMAKE([foreign subdir-objects -Wall -Werror])
: ${CC='arm-none-eabi-gcc -specs=nosys.specs'}
AC_PROG_CC
: ${CXX='arm-none-eabi-g++ -specs=nosys.specs'}
AC_PROG_CXX
AM_PROG_AS
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
AC_PROG_RANLIB
AM_PROG_CC_C_O
AC_PROG_CXX_C_O
AC_CONFIG_FILES([Makefile])])

然后,我希望能够将第一个示例简化为以下内容:

AC_INIT([mppt], [0.1.0])
TIVASDK
AC_OUTPUT

除了简单之外,它还有许多优点。例如,如果 MPPT 开发人员要将 C++ 引入目前完全用 C 编写的固件,那么他们或我就不必更新他们的configure.ac。如果我要对工具链进行更改,我只需将更新推送到一个存储库,而不是将近十个。

问题

Autoconf 并不像我期望的那样理解宏。有几种不同的故障机制。

expanded before it was required

this answer

我有一个用于测试的框架项目。很简单的Makefile.am指定ACLOCAL_AMFLAGS

ACLOCAL_AMFLAGS = -I "$TIVASDK_HOME"/include

noinst_PROGRAMS = skel.axf

skel_axf_SOURCES = \
    src/main.cpp \
    src/abort.cpp

TIVASDK_HOME~/.profile 中定义。

this question。它的configure.ac 使用宏:

AC_INIT([skel], [0.1.0])
m4_define([TIVASDK_HOME], [esyscmd([printf "$TIVASDK_HOME"])])
AC_CONFIG_MACRO_DIR(TIVASDK_HOME[/include])
TIVASDK
AC_OUTPUT

它的autogen.shbuild 中构建树外:

#!/bin/sh

autoreconf -vfi .. && \
  ../configure --prefix="$TIVASDK_HOME" --host=arm-none-eabi

运行 autogen.sh 会产生以下结果:

$ ./autogen.sh 
autoreconf: Entering directory `..'
autoreconf: configure.ac: not using Gettext
autoreconf: running: aclocal --force -I /home/matthew/github.gatech.edu/GTSR/tiva-sdk/include
configure.ac:4: warning: AC_REQUIRE: `AC_PROG_CC' was expanded before it was required
configure.ac:4: http://www.gnu.org/software/autoconf/manual/autoconf.html#Expanded-Before-Required
/home/matthew/github.gatech.edu/GTSR/tiva-sdk/include/tivasdk.m4:1: TIVASDK is expanded from...
configure.ac:4: the top level
configure.ac:4: warning: AC_REQUIRE: `AC_PROG_CC' was expanded before it was required
configure.ac:4: http://www.gnu.org/software/autoconf/manual/autoconf.html#Expanded-Before-Required
/home/matthew/github.gatech.edu/GTSR/tiva-sdk/include/tivasdk.m4:1: TIVASDK is expanded from...
configure.ac:4: the top level
autoreconf: configure.ac: tracing
configure.ac:4: warning: AC_REQUIRE: `AC_PROG_CC' was expanded before it was required
configure.ac:4: http://www.gnu.org/software/autoconf/manual/autoconf.html#Expanded-Before-Required
aclocal.m4:1173: TIVASDK is expanded from...
configure.ac:4: the top level
autoreconf: configure.ac: not using Libtool
autoreconf: running: /usr/bin/autoconf --force
configure.ac:4: warning: AC_REQUIRE: `AC_PROG_CC' was expanded before it was required
configure.ac:4: http://www.gnu.org/software/autoconf/manual/autoconf.html#Expanded-Before-Required
aclocal.m4:1173: TIVASDK is expanded from...
configure.ac:4: the top level
autoreconf: configure.ac: not using Autoheader
autoreconf: running: automake --add-missing --copy --force-missing
configure.ac:4: warning: AC_REQUIRE: `AC_PROG_CC' was expanded before it was required
configure.ac:4: http://www.gnu.org/software/autoconf/manual/autoconf.html#Expanded-Before-Required
aclocal.m4:1173: TIVASDK is expanded from...
configure.ac:4: the top level
configure.ac:4: installing './compile'
configure.ac:4: installing './install-sh'
configure.ac:4: installing './missing'
Makefile.am: installing './depcomp'
autoreconf: Leaving directory `..'
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for arm-none-eabi-strip... arm-none-eabi-strip
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking for style of include used by make... GNU
checking for arm-none-eabi-gcc... arm-none-eabi-gcc
checking whether we are using the GNU C compiler... no
checking whether arm-none-eabi-gcc accepts -g... no
checking for arm-none-eabi-gcc option to accept ISO C89... unsupported
checking whether arm-none-eabi-gcc understands -c and -o together... yes
checking dependency style of arm-none-eabi-gcc... gcc3
checking for arm-none-eabi-gcc... (cached) arm-none-eabi-gcc
checking whether the C compiler works... no
configure: error: in `/home/matthew/gatech.edu/sp2019/vip4602/tmp/skel/build':
configure: error: C compiler cannot create executables
See `config.log' for more details

command not found

我有一种预感,AC_DEFUN 出于某种原因扩展了一些 Autoconf 宏。我用m4_define替换了AC_DEFUN

m4_define([TIVASDK],
[AM_INIT_AUTOMAKE([foreign subdir-objects -Wall -Werror])
: ${CC='arm-none-eabi-gcc -specs=nosys.specs'}
AC_PROG_CC
: ${CXX='arm-none-eabi-g++ -specs=nosys.specs'}
AC_PROG_CXX
AM_PROG_AS
AM_PROG_CC_C_O
AC_PROG_CXX_C_O
AC_CONFIG_FILES([Makefile])])

运行 autogen.sh 会产生以下结果:

$ ./autogen.sh 
autoreconf: Entering directory `..'
autoreconf: configure.ac: not using Gettext
autoreconf: running: aclocal --force -I /home/matthew/github.gatech.edu/GTSR/tiva-sdk/include
autoreconf: configure.ac: tracing
autoreconf: configure.ac: not using Libtool
autoreconf: running: /usr/bin/autoconf --force
autoreconf: configure.ac: not using Autoheader
autoreconf: configure.ac: not using Automake
autoreconf: Leaving directory `..'
../configure: line 1678: TIVASDK: command not found
configure: creating ./config.status

TIVASDK 似乎根本没有扩展。我尝试用define 替换m4_define 无济于事。

最小的工作示例

只需将宏定义放在configure.ac 中即可解决问题:

m4_define([TIVASDK],
[AM_INIT_AUTOMAKE([foreign subdir-objects -Wall -Werror])
: ${CC='arm-none-eabi-gcc -specs=nosys.specs'}
AC_PROG_CC
: ${CXX='arm-none-eabi-g++ -specs=nosys.specs'}
AC_PROG_CXX
AM_PROG_AS
AM_PROG_CC_C_O
AC_PROG_CXX_C_O
AC_CONFIG_FILES([Makefile])])
AC_INIT([skel], [0.1.0])
TIVASDK
AC_OUTPUT

运行 autogen.sh 会产生以下结果:

$ ./autogen.sh 
autoreconf: Entering directory `..'
autoreconf: configure.ac: not using Gettext
autoreconf: running: aclocal --force -I /home/matthew/github.gatech.edu/GTSR/tiva-sdk/include
autoreconf: configure.ac: tracing
autoreconf: configure.ac: not using Libtool
autoreconf: running: /usr/bin/autoconf --force
autoreconf: configure.ac: not using Autoheader
autoreconf: running: automake --add-missing --copy --force-missing
configure.ac:12: installing './compile'
configure.ac:12: installing './install-sh'
configure.ac:12: installing './missing'
Makefile.am: installing './depcomp'
autoreconf: Leaving directory `..'
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for arm-none-eabi-strip... arm-none-eabi-strip
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking for arm-none-eabi-gcc... arm-none-eabi-gcc -specs=nosys.specs
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables... 
checking whether we are cross compiling... yes
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether arm-none-eabi-gcc -specs=nosys.specs accepts -g... yes
checking for arm-none-eabi-gcc -specs=nosys.specs option to accept ISO C89... none needed
checking whether arm-none-eabi-gcc -specs=nosys.specs understands -c and -o together... yes
checking for style of include used by make... GNU
checking dependency style of arm-none-eabi-gcc -specs=nosys.specs... gcc3
checking whether we are using the GNU C++ compiler... yes
checking whether arm-none-eabi-g++ -specs=nosys.specs accepts -g... yes
checking dependency style of arm-none-eabi-g++ -specs=nosys.specs... gcc3
checking dependency style of arm-none-eabi-gcc -specs=nosys.specs... gcc3
checking whether arm-none-eabi-g++ -specs=nosys.specs understands -c and -o together... yes
checking that generated files are newer than configure... done
configure: creating ./config.status
config.status: creating Makefile
config.status: executing depfiles commands

【问题讨论】:

    标签: autotools autoconf


    【解决方案1】:
    • 为什么 AC_DEFUN 会尝试扩展 AC_PROG_CC?

    我无法解释您的错误的原因。我确实使用您的代码复制了它,但 没有 使用我最初尝试的类似代码。似乎涉及多种因素,其中AC_PROG_CCAC_PROG_CXX 同时存在。

    但是,从您最初的尝试开始,在“问题”标题上方的问题中提出,并根据错误消息所指的在线 Autoconf 手册页中的信息,我只需调用 @ 即可解决问题987654323@ 间接通过AC_REQUIRE 而不是直接:

    AC_DEFUN([TIVASDK], [
    AM_INIT_AUTOMAKE([foreign subdir-objects -Wall -Werror])
    : ${CC='arm-none-eabi-gcc -specs=nosys.specs'}
    
    # HERE:
    AC_REQUIRE([AC_PROG_CC])
    
    : ${CXX='arm-none-eabi-g++ -specs=nosys.specs'}
    AC_PROG_CXX
    # ...
    

    顺便说一句,我发现至少在骨架项目中没有理由定义或使用TIVASDK_HOME 宏。 Makefile.in 中定义的 ACLOCAL_AMFLAGS 显然就足够了。

    我不太喜欢使用环境变量来定义所需宏包含目录的位置,并且该示例并没有让我清楚为什么这很有用,但是如果您继续这样做,那么我鼓励你

    • 使用AC_ARG_VAR 记录该变量并使其变得珍贵,并且
    • 确实删除了同名宏。
    • 为什么 m4_define 定义的宏似乎没有展开?

    我推测这是因为外部宏文件不是直接使用的,而是由aclocal 处理以生成文件aclocal.m4,这是包含在内的。我想你会发现直接出现在任何 Autoconf 宏定义范围之外的 m4_define 并没有被复制。

    • 为什么在 configure.ac 中定义的宏与在另一个文件中定义并包含在内的宏的行为不同?

    我认为不会。但是,configure.ac 中定义的 M4 宏的行为确实与其他地方定义的且包括在内的宏有所不同。

    【讨论】:

      猜你喜欢
      • 2021-05-28
      • 2017-06-02
      • 2016-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-04
      • 2014-09-06
      相关资源
      最近更新 更多