我们知道configure.ac可以生成configure文件,而Makefile.am可以生成Makefile.am,之所以这么做就是为了适应不同的环境需求
我已经写好了一个示例,目录结构如下
# tree
.
├── a.c
├── b.c
├── b.h
├── configure.ac
├── Makefile.am
└── src
├── c.c
├── c.h
├── d.c
├── d.h
└── Makefile.am
我想在src的文件夹编译一个静态库,叫libfoo.a,基于c.c、d.c、c.h、d.h生成
我想用a.c编译一个程序叫做test,并引用了上面的 libfoo.a
代码c文件代码(不是很重要)
// a.c #include#include "b.h" #include "src/c.h" void main() { fun1(); fun2(); } // b.c #include int fun1() { return 1; } // b.h #include int fun2() { return 1; } // c.c #include int fun2() { return 1; } // c.h #include int fun2(); // d.c #include int fun3() { return 1; } // d.h #include int fun3() { return 1; }
configure.ac
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
AC_INIT([myproject], [1.0.0])
AC_CONFIG_SRCDIR([a.c])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
# Checks for programs.
AC_PROG_CC
AC_PROG_CXX
AC_PROG_RANLIB
AM_PROG_AR
# Checks for libraries.
AC_CHECK_LIB([curl], [curl_easy_perform], [CURL123=-lcurl], AC_MSG_ERROR("需要安装curl库"))
AC_SUBST([CURL123])
# Checks for header files.
have_openssl=yes
AC_CHECK_HEADER(openssl/sha.h, [have_openssl=yes], [have_openssl=no])
if test "x$have_openssl" != "xyes"
then
AC_MSG_ERROR("需要安装openssl库")
else
AC_MSG_WARN("else示范")
fi
# Checks for typedefs, structures, and compiler characteristics.
# Checks for library functions.
AC_CONFIG_FILES([Makefile src/Makefile])
AC_OUTPUT
Makefile.am (外层)
AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 bin_PROGRAMS = test test_SOURCES = a.c b.c noinst_HEADERS = b.h src/c.h test_LDADD = @CURL123@ src/libfoo.a SUBDIRS = src/ #AM_CFLAGS = -L/usr/include
src/Makefile.am
lib_LIBRARIES = libfoo.a libfoo_a_SOURCES = c.c d.c include_HEADERS = c.h d.h前提
假设大家已经安装了 automake make gcc 等软件
正文 configure.ac先来说是configure.ac文件
configure.ac 文件可以由 autoscan命令生成,autoscan会生成一个log文件(不用管)和一个configure.scan,修改configure.scan的名称为configure.ac
configure.scan内容如下
# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS]) AC_CONFIG_SRCDIR([a.c]) AC_CONFIG_HEADERS([config.h]) # Checks for programs. AC_PROG_CC # Checks for libraries. # Checks for header files. # Checks for typedefs, structures, and compiler characteristics. # Checks for library functions. AC_OUTPUT
然后看到我修改后的文件(configure.ac 见文章开头,后面的Makefile.am也是如此)
按照先后顺序,讲讲上面的宏,不建议跳着看,宏和左括号之间不要有空格,容易发生意想不到的错误
AC_PREREQautoconf的版本号,基本不用修改
AC_INIT可以带三个参数,分别是项目名称,版本号,邮箱,可以不填邮箱
AC_CONFIG_HEADERS([config.h])先说这个,这个文件里面包含了上面写的版本号,项目名称等信息,以及某些头文件是否存在的宏定义,小工程可能用不上这些,大的开源项目需要包含这个文件,做一些宏的判断操作
AC_CONFIG_SRCDIR检测文件是否存在,一般检测的是主文件,但个人感觉没啥用,这个宏如果定义了,后面的文件一定要存在,不然可能报错
configure: error: cannot find install-sh, install.sh, or shtool in ".." "../.." "../../.."AM_INIT_AUTOMAKE([-Wall -Werror foreign])
automake的编译选项,一般没啥变化
AC_PROG_CCgcc编译器,后面可以加编译器名称,用于其他平台编译
AC_PROG_CXXg++编译器,不加编译不了cpp
AC_PROG_RANLIB AM_PROG_AR这两个宏用于编译库文件,这次的示例有编译静态库用到
AC_CHECK_LIB检查库文件是否存在 (可选宏)
AC_CHECK_LIB([curl], [curl_easy_perform], [CURL123=-lcurl], AC_MSG_ERROR("需要安装curl库"))
这个表示,我要检查curl库是否存在,我将尝试curl_easy_perform(curl库的函数),如果存在我设置一个宏 CURL123 (后面Makefile.am用到),CURL123即 -lcurl,如果不存在则弹出报错提示 "需要安装curl库"
AC_SUBST跟上面的CURL123宏配合使用,用于Makefile.am
AC_MSG_ERROR报错并中断编译,宏后面可以接上报错提示
AC_MSG_WARN报错但不中断编译,宏后面可以接上报错提示
AC_CHECK_HEADER(可选宏)第一个参数检查头文件是否存在,后面两个参数(可选)分别是,如果头文件存在则做什么(可以不填东西,比如 , , 代替),如果头文件不存在做什么
AC_CONFIG_FILES一般指定Makefile.am的位置
AC_OUTPUTconfigure.ac结束标志
Makefile.am 文件 Makefile.am (外层) AUTOMAKE_OPTIONS ACLOCAL_AMFLAGS
这两个宏貌似加不加都不影响编译
bin_PROGRAMS指定编译的程序名称,比如我指定程序叫做test,影响我后面选项的构成,后面跟test名称相关,基本都是我这里指定的,可以指定多个
test_SOURCES严格来说这个不算一个标准宏 是 程序名称加下划线SOURCES,主要是指定你的程序依赖的 .c 文件,可以指定多个,可以带路径,如果我们c文件过多,我们可以使用 ls *.c 快速过滤文件
noinst_HEADERSnoinst代表不需要安装,我做的示例不是给别人用的开发库,没必要安装到系统目录下。
可以指定多个头文件,可以带路径,一般不用带路径,如果你想引用上层目录的commom文件夹的xxx.h文件,只需要在当前目录的头文件写 #include "commom/xxx.h",子模块这么写include是表示上一级目录,父模块这么写表示下一级目录
test_LDADD指定程序依赖的库可以直接写如 -lcurl,而我这里跟前面configure.ac联动,动态指定 -lcurl
SUBDIRS子目录,优先编译子目录的内容,比如我那个 .a 库,再编译当前内容
AM_CFLAGSgcc编译选项(我加#号注释了),Makefile直接指定CFLAGS,而Makefile.am指定编译选项需要加个AM_前缀
AM_CXXFLAGSg++编译选项,g++的选项加在 AM_CFLAGS 则无效,如 -std=c++11
src/Makefile.am lib_LIBRARIES编译的库名,记住要用lib作为库名开头,不然会报错说你不是标准名称,我这里指定叫做 libfoo.a,同样影响后面
libfoo_a_SOURCES像点这种特殊符号就用下划线代填
include_HEADERS包含的头文件路径,可以用 noinst_HEADERS 代填,这里主要是用于示范,应该会安装
编译库这里踩过一个大坑,我看到有的教程把 lib_LIBRARIES 写成 lib_LTLIBRARIES,然后我疯狂报错
src/Makefile.am:1: error: Libtool library used but 'LIBTOOL' is undefined src/Makefile.am:1: The usual way to define 'LIBTOOL' is to add 'LT_INIT' src/Makefile.am:1: to 'configure.ac' and run 'aclocal' and 'autoconf' again. src/Makefile.am:1: If 'LT_INIT' is in 'configure.ac', make sure src/Makefile.am:1: its definition is in aclocal's search path.
像这种不存在的宏,它不会识别,直接认为Makefile.am是一个空文件,说我没写 configure.ac 服了
文件都写好了就开始正式编译了,编译命令如下,教程结束
# 下面这四步可以生成configure文件,不深究为啥是这样 aclocal autoheader autoconf automake --add-missing # 下面是正常的编译流程 ./configure make clean make参考资料
总览
configure.ac和Makefile.am的格式解析概述 - never715 - 博客园
【Linux】自动生成makefile(ubuntu)_棱角为零的博客-CSDN博客_自动生成makefile
configure.ac
编写configure.ac_john_crash的博客-CSDN博客_ac_config_srcdir
Makefile.am
编写Makefile.am_john_crash的博客-CSDN博客
Makefile.am 解释_iteye_15968的博客-CSDN博客
暑期编程PK赛 得CSDN机械键盘等精美礼品!


