Linux下的自动编译工具——Automake (linux automake)

在Linux开发中,使用自动化编译工具能够提高开发效率和代码质量。Automake是其中一种较为流行的工具,它可以自动根据Makefile.am文件生成Makefile文件。

一、 Automake概述

Automake是GNU自由软件基金会(The GNU Project)旗下的一个开源工具,它是一个Makefile自动生成器,可以将Makefile.am文件生成Makefile文件。Automake可以根据Makefile.am文件中的规则自动推导出生成Makefile所需的规则,这个操作是自动完成的。

Automake是一个在Autoconf的基础上构建的工具,它的主要目的是帮助开发者更好地管理代码,并且能够提供统一的编译规范,自动执行依赖分析等操作,从而保证程序的正确性和可移植性。

自动化编译工具在Linux开发中扮演着重要的角色,不仅可以自动管理依赖关系,减少编译时间,还可以提高代码可维护性和可读性。

二、 Automake运行环境要求

Automake更好的运行环境是Linux和Unix,因为它们具有和自由软件遵循的GPL类似的许可证。

在使用Automake之前,需要先安装它,可以通过以下命令安装Automake:

sudo apt-get install automake

三、创建Makefile.am文件

Makefile.am是Automake的源文件,它告诉Automake工具如何生成Makefile文件。

Makefile.am文件的基本格式如下:

AUTOMAKE_OPTIONS = foreign

if BUILD_STATIC

bin_PROGRAMS = foo

else

noinst_PROGRAMS = foo

endif

foo_SOURCES = mn.c

其中,AUTOMAKE_OPTIONS = foreign是一个全局选项,表示使用非GNU的Make工具,如BSD或AT&T Unix。这是为了保证Automake生成的Makefile在不同的系统中都能够运行。

bin_PROGRAMS或noinst_PROGRAMS声明了要生成的程序名,用_SOURCES指定了源文件列表。bin_PROGRAMS是生成可执行文件,而noinst_PROGRAMS只编译不生成可执行文件。

四、使用Automaker生成Makefile

生成Makefile的命令如下:

aclocal && automake –add-missing && autoconf

aclocal是Autoconf的辅助工具,它会在configure.ac文件中引用的.m4文件中查找宏,并将它们复制到当前目录的aclocal.m4文件中。

automake –add-missing是Automake的主命令,用于自动生成Makefile。

autoconf是Autoconf的主命令,用于生成configure文件。

五、构建生成目录

使用以下命令来建立生成目录:

mkdir build

cd build

../configure

make

configure是一个由Autoconf生成的脚本,它根据系统环境的不同进行配置,然后生成Makefile文件。

make命令是通过Makefile文件来开始编译。

六、项目版本控制

版本控制是一个软件项目中非常重要的部分。版本控制可以轻松地在多个开发者之间协作,并且可以轻松地回退到之前的版本。

在Linux项目中可以使用Git和SVN等版本控制工具。

七、结论

Automake是一种非常好用的自动化编译工具,它可以大大提高开发效率和代码质量,在项目开发、版本管理和代码维护中都具有非常重要的作用。作为开发人员,我们需要掌握Automake的基本操作,以便更好地完成开发任务。

相关问题拓展阅读:

linux下的tmake命令是干什么的

tmake?这个是一个类似automake之类的makefile生成管理工具,但应该已经很过肆历烂时了。类似的有烂拆qmake。

当然现在常用裂漏的是automake/cmake

如何在linux下构建强大的build系统

大致目录构建如下:

├── uc-config.in : 用来生成配置环境信息的可橡乎乱执行程序

├── uc.pc.in : 用来生成配置环境信息的文件

├── uc.spec.in : 用来产生spec文件

├── autogen.sh : build工具

├── conf : 配置文件目录

├── config.h.in : 一些编译过程中的配置信息

├── configure : 配置工具

├── configure.ac : 形成build以及配置工具的文件

├── data : 数据目录

├── doc : 文档

├── Doxyfile.in : 生成Doxyfile的文件,主要用于doxygen的配置文件

├── include : 外部的头文件,工程内的文件不要放入

├顷肢──梁档 lib : 外部的库文件,工程内的库不要放入

├── m4 : m4文件

├── scripts : 常使用的一些script,用于运转系统

├── src : 源代码目录

│ ├── Main.cpp : 用于产生的gnome版本的源文件,含有main入口

│ ├── .h : 用于外部开发的接口

│ ├── Main.cpp:用于产生的kde版本,含有kde的main入口

│ ├── common : 普通的头文件

│ │ ├── def.h : 的一般定义

│ │ ├── rst.h : 的返回值类型定义

│ │ ├── types.h : 的类型定义

│ │ ├── common.h : 共用头文件,含有def.h、rst.h和types.h等头文件

│ ├── network : 网络通讯库

│ ├── ui : ui界面库

│ │ ├── gnome : gnome界面库,主要是gtk2的一些界面接口

│ │ ├── kde : kde界面库,主要是qt的一些界面接口

│ └── util : 常用的一些共用库

├── test : 单元测试

│ ├── dotest.cpp : 主要测试入口

│ ├── network

│ ├── template.cpp : 样例模板 cpp 文件

│ ├── template.h : 样例模板 头文件

│ ├── ui

│ │ ├── gnome

│ │ └── kde

│ └── util

└── tools : 常使用的一些工具,用于维护系统

如何编写configure.ac

configure.ac是产生configure以及automake重要文件,一般可以使用autoscan生成,这里就不太详细描述,网上可以google到很多资料。

一般开发人员只需要使用autogen.sh,这个脚本会完成所有的automake以及autoconf的操作,虽然其中m4文件定义的宏非常重要,但是不需要开发人员完全读懂,这里也不是关注的重点,等一步步的完全熟悉了,再过来了解也不迟。

这里项目中默认已经生成好了configure.ac。

如何编译Makefile.am

开发人员重点关注的是Makefile.am,Makefile.am完全和Makefile的语法一样,不过你可以写少量的信息就足够了。

如何编译源文件

这里所指的源文件一般指c/c++源文件,对于java的源文件,我们将ant放入Makefile.am,道理一样。编译源文件一般有两种方式,库文件和可执行文件,而库文件也有两种方式,静态库文件和动态库文件,一般静态库用:

lib_LIBRARIES = libcpthread.a

这种方式表示生成一个静态库,对应的源文件如何写呢?

libcpthread_a_SOURCES = thread.cpp thread.h

当然对于一般头文件可以忽略不写,不过建议写上,因为每个开发者都不是很规范,头文件不仅仅只有申明,有的头文件还会有实现。如果有多个cpp文件生成一个库文件,则全部添加;如果有多个.a文件需要生成,只需要用空格隔开.a文件,相应的源文件对应到.a文件即可,如下所示:

lib_LIBRARIES = libcpthread1.a libcpthread2.a libcpthread2.a

那么动态库该如何写呢?有人肯定会提到

lib_LIBRARIES = libcpthread.so

libcpthread_so_SOURCES = thread.cpp thread.h

不过可惜是错误的,这里顺便提到一个libtool,主要用来生成静态库和动态库的一个工具,不过在autogen.sh工具里面已经包含。正确写法如下:

lib_LTLIBRARIES = libcpthread.la

libcpthread_la_SOURCES = thread.cpp thread.h

有人看到这觉得很奇怪,为什么要生成.la这个文件呢?.la文件内容如下:

# libcpthread.la – a libtool library file

# Generated by ltmain.sh – GNU libtool 1.5.6 (1.1220.2./04/11 05:50:42)

#

# Please DO NOT delete this file!

# It is necessary for linking the library.

# The name that we can dlopen(3).

dlname=’libcpthread-1.0.0.so.1′

# Names of this library.

library_names=’libcpthread-1.0.0.so.1.0.0 libcpthread-1.0.0.so.1 libcpthread.so’

# The name of the static archive.

old_library=’libcpthread.a’

# Libraries that this one depends upon.

dependency_libs=’ -ldl /usr/lib64/libconfig++.la /usr/lib64/libconfig.la /usr/lib64/libchardet.la /usr/local/lib64/libalog.la -lz /usr/local/lib64/libanet.la -lpthread -lalog’

# Version information for libcpthread.

current=1

age=0

revision=0

# Is this an already installed library?

installed=no

# Should we warn about portability when linking against -modules?

shouldnotlink=no

# Files to dlopen/dlpreopen

dlopen=”

dlpreopen=”

# Directory that this library needs to be installed in:

libdir=’/usr/lib’

看到了吧?里面指定了关于静态库和动态库的依赖等一系列的信息,具体还可以参考项目框架设计模式中库公约的部分。

静态文件和动态文件都会在当前目录的.libs下,当然开发者也不需要关注库文件本身,了解在这个路径下即可。

可执行文件如何编译呢?

bin_PROGRAMS = threadpool

threadpool_SOURCES = threadpoolMain.cpp

此处的bin_PROGRAMS会将程序安装到${prefix}路径下,如果不想安装,可以采用:

noinst_PROGRAMS = testthreadpool

threadpool_SOURCES = threadpoolMain.cpp

同理,如果有多个cpp文件生成一个库文件,则全部添加;如果有多个.la文件或者可执行文件需要生成,只需要用空格隔开.a文件,相应的源文件对应到.a文件即可,如下所示:

lib_LTLIBRARIES = libcpthread1.la libcpthread2.la libcpthread2.la

noinst_PROGRAMS = testthreadpool1 testthreadpool2 testthreadpool3

如果库文件或者二进制文件有头文件的申明依赖或追加一些编译选项,则可以使用CFLAGS或CPPFLAGS,如下所示:

threadpool_CPPFLAGS = -I$(top_srcdir)/include/example.h

如果是java源文件,只需要遵循普通makefile写法即可,如:

all: threadpool.jar

.PHONY: threadpool.jar clean

threadpool.jar:

@ant jar

clean:

ant clean

当然,ant需要配置好build.xml哟!

如何连接库

连接库的的时候,同样也会有区分,工程外部的连接需使用LDFLAGS,如下所示:

libcpthread_la_LDFLAGS = -pthread

如果是内部库,我们就直接使用.la文件,这样在选择静态连接或者动态连接的时候,就给开发者很大的空间。值得注意的是,库文件和二进制的内部库连接宏并不相同,表现如下:

libcpthread_la_LIBADD = $(top_srcdir)/src/util/libutil.la

threadpool_LDADD = libcpthread.la

现在编译和连接是否都了解了呢?

非编译的一些开发

当创建一个脚本或配置文件的时候:

make dist

则形成一个.gz的压缩包,但刚才创建的脚本或配置文件并没有加入,于是:

EXTRA_DIST = conf/config.cfg

script/example.sh

即可将脚本或配置文件放入到压缩包中;

若在多层目录上的时候,还可以使用宏SUBDIRS指定内部编译的顺序(包括当前目录),比如:

SUBDIRS = util /

thread /

. /

log

/

common

在编译系统make的时候,会严格按照顺序进行。

提供外部开发

如果工程完成了,别人想使用上面的库文件进行二次开发,该如何做呢?

libcpthreadincludedir = $(includedir)/@PACKAGE_NAME@/util/thread

libcpthreadinclude_HEADERS= thread.h

这样在编译系统make install的时候,会将头文件安装到上面指定的目录下,别人依照上面的build系统继续下面的build了。

关于linux automake的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。


数据运维技术 » Linux下的自动编译工具——Automake (linux automake)