利用autotool工具编译和安装

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用autotool工具编译和安装相关的知识,希望对你有一定的参考价值。

参考技术A 平时自己写的程序多是直接写Makefile,大型的开源C代码,多是通过autotool工具来生成,需要学习下。为了具备通用性,用工作中实际程序来测试。

步骤很简单,解压程序后,在源码目录运行autoscan就会生成configure.scan 如下:

说明:

下面需要修改configure.scan 为configure.ac 且修改内容如下:

1)主要是修改AC_INIT 三个中括号里面内容依次是软件名,版本名,bug报告地址; 2)添加AM_INIT_AUTOMAKE(软件名,版本) 这个宏是必须的,它描述了我们将要生成的软件包的名字及其版本号:PACKAGE是软件包的名字,VERSION是版本号。当你使用make dist命令时,它会给你生成一个类似helloworld-1.0.tar.gz的软件发行包,其中就有对应的软件包的名字和版本号。 3) 输出文件名也修改:AC_OUTPUT(Makefile)

运行以下命令生成m4宏定义,比如我们使用的AM_INIT_AUTOMAKE,就是用aclocal生成的m4文件里面的:

如下:

运行命令autoconf来生成configure文件:

运行configure文件,报错,缺少Makefile.in无法生成Makefile

编写为生成Makefile需要的Makefile.am 文件如下:

说明:

在Makefile.am 文件中 INCLUDES根据提示用AM_CPPFLAGS替换下。 正常生成Makefile.in之后,用configure 来结合Makefile.in 生成Makefile文件

生成了Makefile文件。

刚才默认的安装是安装到/usr/local/下面的,我现在有两个需求: 一是指定安装路径,且不在bin下面,直接在那个目录下面; 二是需要把配置文件拷贝过去,安装后的目录如下;

原来我们只有一个Makefile,由于配置我们也需要安装,所以增加了配置目录的etc/Makefile的输出。

更改根目录的Makefile.am 设置下安装目录bindir,且要设置递归调用Makefile子目录SUBDIRS,整体如下:

在配置文件目录etc下新建Makefile.am内容如下:

重新生成和编译安装:

结果顺利完成编译和安装。

以前画的图:

Autotools 交叉编译和生成源

【中文标题】Autotools 交叉编译和生成源【英文标题】:Autotools cross compilation and generated sources 【发布时间】:2014-08-03 18:33:54 【问题描述】:

我正在尝试使用 autotools(autoconf、automake、libtool)作为构建系统来创建一个库。该库必须是可交叉编译的,但构建它的步骤之一是在整个过程中通过从源构建的可执行文件生成源。

问题是我不能使用 automake 的系统来构建中间二进制文件,因为当它交叉编译时,它不会在“--build”上运行来生成源代码。

解决这个问题的一种方法是创建单独的 autools 项目来构建中间二进制文件,但我想避免它,因为中间可执行文件和最终库有很多头文件和其他“数据”文件,所以我想保留它一个地方,除了那些中间二进制文件应该是“noinst”。

有没有其他方法可以让它正常工作并保持可移植性?我尝试使用ax_prog_cxx_for_build,但在交叉编译时找不到--build的EXEEXT。

这是一个问题示例,只是为了说明我的问题:

配置.ac

#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.68])
AC_INIT([libfoobar], [0.1.0], [<NOBUGS>])
AM_INIT_AUTOMAKE([foreign])
LT_INIT

AC_CONFIG_SRCDIR([src/bar.cpp])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_FILES([Makefile
                 src/Makefile])

# Checks for programs.
AC_PROG_CXX

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

AC_OUTPUT

Makefile.am

ACLOCAL_AMFLAGS = -I m4

SUBDIRS = src

src/Makefile.am

bin_PROGRAMS = bar
lib_LTLIBRARIES = libfoo.la

noinst_bar_SOURCES = bar.cpp

libfoo_la_SOURCES = foo.cpp
nodist_libfoo_la_SOURCES = foobar.h

BUILT_SOURCES: foobar.h

foobar.h: bar$(EXEEXT) Makefile
    ./$< >$@
CLEANFILES = foobar.h

src/foo.cpp

#include "foobar.h"

extern "C" int foo() 
    return foobar_value;

src/bar.cpp

#include <iostream>

int main() 
    std::cout << "#ifndef FOOBAR_H" << std::endl;
    std::cout << "#define FOOBAR_H" << std::endl;
    std::cout << std::endl;
    std::cout << "static const int foobar_value = 0xdeadbeef;" << std::endl;
    std::cout << std::endl;
    std::cout << "#endif" << std::endl;

【问题讨论】:

【参考方案1】:

如果您使用的是AX_PROG_CXX_FOR_BUILD,那么您应该使用的EXEEXTBUILD_EXEEXT,它在宏AX_PROG_CC_FOR_BUILD 中定义(AX_PROG_CXX_FOR_BUILD 需要)。将EXEEXT 用于CXX_FOR_BUILD 构建的东西将是一个错误,因为这是主机工具链的扩展。所以在这种情况下,你需要更多类似的东西:

configure.ac

#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.68])
AC_INIT([libfoobar], [0.1.0], [<NOBUGS>])
AM_INIT_AUTOMAKE([foreign])
LT_INIT
AC_CANONICAL_BUILD
AC_CANONICAL_HOST

AC_CONFIG_SRCDIR([src/bar.cpp])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_FILES([Makefile
                 src/Makefile])

# Checks for programs.
AC_PROG_CXX
AX_PROG_CXX_FOR_BUILD

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

AC_OUTPUT

src/Makefile.am

noinst_PROGRAMS = bar
lib_LTLIBRARIES = libfoo.la

bar_SOURCES = bar.cpp

LINK_FOR_BUILD.cpp = $(CXX_FOR_BUILD) $(CXXFLAGS_FOR_BUILD) $(CPPFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) $(TARGET_ARCH_FOR_BUILD)

bar$(BUILD_EXEEXT) : $(bar_OBJECTS)
            $(LINK_FOR_BUILD.cpp) $^ $(LOADLIBES_FOR_BUILD) $(LDLIBS_FOR_BUILD) -o $@

$(bar_OBJECTS) : CC=$(CC_FOR_BUILD)
$(bar_OBJECTS) : CXXFLAGS=$(CXXFLAGS_FOR_BUILD)
$(bar_OBJECTS) : CPPFLAGS=$(CPPFLAGS_FOR_BUILD)

libfoo_la_SOURCES = foo.cpp
nodist_libfoo_la_SOURCES = foobar.h

BUILT_SOURCES: foobar.h

foobar.h: bar$(BUILD_EXEEXT) Makefile
    ./$< >$@
CLEANFILES = foobar.h

【讨论】:

【参考方案2】:

这会有所帮助。 Autotools 仍然将 --host 的 $(EXEEXT) 后缀为 _PROGRAMS,所以在交叉编译期间我无论如何都无法使用 autotools 功能。

我找到了另一个解决方案。这真的很肮脏,但有效。我在适当的来源创建了 autotools 子项目,并在文件的最底部链接并添加到我的 configure.ac 中:

if [[ "x$cross_compiling" != "xyes" ]]; then
  AC_CONFIG_SUBDIRS(src/tools)
fi

AC_OUTPUT

if [[ "x$cross_compiling" = "xyes" ]]; then
  mkdir -p src/tools
  cd src/tools && ../../"$srcdir"/src/tools/configure --cache-file=/dev/null --host=$build --target=$host
fi

在 Makefile.am 中,我直接引用工具目录中的二进制文件:

SUBDIRS = tools

foobar.h: tools/gencpu$(BUILD_EXEEXT)
    ./$< >$@

BUILT_SOURCES: foobar.h

CLEANFILES = foobar.h

除非我找到更好、更“优雅”的解决方案,否则我会坚持下去。

【讨论】:

以上是关于利用autotool工具编译和安装的主要内容,如果未能解决你的问题,请参考以下文章

automake - 使用 autotools 工具集

automake:autotools 工具集使用速成

GNU autotools自动生成Makefile 介绍

Autotools:将 -D 与变量一起使用适用于除一个编译之外的所有编译(C 编程)

java 编程基础:注解(Annotation Processing Tool)注解处理器 利用注解解读类属性生成XML文件

如何制作一个makefile文件