
linux安装 .tgz包下没有configure文件吗,只有configure.ac文件,是设置错误造成的,解决方法如下:
1、首先打开linux服务器,在不知道防火墙是否开启的情况下,执行systemctl stop firewalld开停掉防火墙,如图。
2、然后在执行systemctl mask firewalld开注销的防火墙服务,如图。
3、然后就执行yum install -y iptables 来选择自动执行安装iptables,如图。
4、执行完自动安装命令后,再执行yum install iptables-services命令,就开始自动安装了,安装完毕后执行find命令来查询iptables文件,如图。
5、然后使用cd命令行到文件夹目录下,就可以看到iptables文件了。
大致目录构建如下:├── 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 : 源代码目录
│ ├── xxxMain.cpp : 用于产生xxx的gnome版本的源文件,含有main入口
│ ├── xxx.h : 用于外部开发的xxx接口
│ ├── xxxMain.cpp:用于产生xxx的kde版本,含有kde的main入口
│ ├── common : 普通的头文件
│ │ ├── xxxdef.h : xxx的一般定义
│ │ ├── xxxrst.h : xxx的返回值类型定义
│ │ ├── xxxtypes.h : xxx的类型定义
│ │ ├── common.h : 共用头文件,含有xxxdef.h、xxxrst.h和xxxtypes.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.95 2004/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了。
autotools使用流程正如前面所言,autotools是系列工具,读者首先要确认系统是否装了以下工具(可以用which命令进行查看)。
· aclocal
· autoscan
· autoconf
· autoheader
· automake
使用autotools主要就是利用各个工具的脚本文件以生成最后的Makefile。其总体流程是这样的:
· 使用aclocal生成一个“aclocal.m4”文件,该文件主要处理本地的宏定义;
· 改写“configure.scan”文件,并将其重命名为“configure.in”,并使用autoconf文件生成configure文件。
接下来,笔者将通过一个简单的hello.c例子带领读者熟悉autotools生成makefile的过程,由于在这过程中有涉及到较多的脚本文件,为了更清楚地了解相互之间的关系,强烈建议读者实际动手 *** 作以体会其整个过程。
1.autoscan
它会在给定目录及其子目录树中检查源文件,若没有给出目录,就在当前目录及其子目录树中进行检查。它会搜索源文件以寻找一般的移植性问题并创建一个 文件“configure.scan”,该文件就是接下来autoconf要用到的“configure.in”原型。如下所示:
[root@localhost automake]# autoscan
autom4te: configure.ac: no such file or directory
autoscan: /usr/bin/autom4te failed with exit status: 1
[root@localhost automake]# ls
autoscan.log configure.scan hello.c
如上所示,autoscan首先会尝试去读入“configure.ac”(同configure.in的配置文件)文件,此时还没有创建该配置文件,于是它会自动生成一个“configure.in”的原型文件“configure.scan”。
2.autoconf
configure.in是autoconf的脚本配置文件,它的原型文件“configure.scan”如下所示:
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
#The next one is modified by sunq
#AC_INIT(FULL-PACKAGE-NAME,VERSION,BUG-REPORT-ADDRESS)
AC_INIT(hello,1.0)
# The next one is added by sunq
AM_INIT_AUTOMAKE(hello,1.0)
AC_CONFIG_SRCDIR([hello.c])
AC_CONFIG_HEADER([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_CONFIG_FILES([Makefile])
AC_OUTPUT
下面对这个脚本文件进行解释:
· 以“#”号开始的行为注释。
· AC_PREREQ宏声明本文件要求的autoconf版本,如本例使用的版本2.59。
· AC_INIT宏用来定义软件的名称和版本等信息,在本例中省略了BUG-REPORT-ADDRESS,一般为作者的e-mail。
· AM_INIT_AUTOMAKE是笔者另加的,它是automake所必备的宏,也同前面一样,PACKAGE是所要产生软件套件的名称,VERSION是版本编号。
· AC_CONFIG_SRCDIR宏用来侦测所指定的源码文件是否存在,来确定源码目录的有
效性。在此处为当前目录下的hello.c。
· AC_CONFIG_HEADER宏用于生成config.h文件,以便autoheader使用。
· AC_CONFIG_FILES宏用于生成相应的Makefile文件。
· 中间的注释间可以添加分别用户测试程序、测试函数库、测试头文件等宏定义。
接下来首先运行aclocal,生成一个“aclocal.m4”文件,该文件主要处理本地的宏定义。如下所示:
[root@localhost automake]# aclocal
再接着运行autoconf,生成“configure”可执行文件。如下所示:
[root@localhost automake]# autoconf
[root@localhost automake]# ls
aclocal.m4 autom4te.cache autoscan.log configure configure.in hello.c
3.autoheader
接着使用autoheader命令,它负责生成config.h.in文件。该工具通常会从“acconfig.h”文件中复制用户附加的符号定义,因此此处没有附加符号定义,所以不需要创建“acconfig.h”文件。如下所示:
[root@localhost automake]# autoheader
4.automake
这一步是创建Makefile很重要的一步,automake要用的脚本配置文件是Makefile.am,用户需要自己创建相应的文件。之后,automake工具转换成Makefile.in。在该例中,笔者创建的文件为Makefile.am如下所示:
AUTOMAKE_OPTIONS=foreign
bin_PROGRAMS= hello
hello_SOURCES= hello.c
下面对该脚本文件的对应项进行解释。
· 其中的AUTOMAKE_OPTIONS为设置automake的选项。由于GNU(在第1章中已经有所介绍)对自己发布的软件有严格的规范,比如必须附 带许可证声明文件COPYING等,否则automake执行时会报错。automake提供了三种软件等级:foreign、gnu和gnits,让用 户选择采用,默认等级为gnu。在本例使用foreign等级,它只检测必须的文件。
· bin_PROGRAMS定义要产生的执行文件名。如果要产生多个执行文件,每个文件名用空格隔开。
· hello_SOURCES定义“hello”这个执行程序所需要的原始文件。如果”hello”这个程序是由多个原始文件所产生的,则必须把它所用到的 所有原始文件都列出来,并用空格隔开。例如:若目标体“hello”需要“hello.c”、“sunq.c”、“hello.h”三个依赖文件,则定义 hello_SOURCES=hello.c sunq.c hello.h。要注意的是,如果要定义多个执行文件,则对每个执行程序都要定义相应的file_SOURCES。
接下来可以使用automake对其生成“configure.in”文件,在这里使用选项“—adding-missing”可以让automake自动添加有一些必需的脚本文件。如下所示:
最上层的要写明
AUTOMAKE_OPTIONS = foreign
如果这个目录没有要编译的文件,只包含了子目录,则只写个
SUBDIRS = dir1
就ok了。 例如我的工程,最上层只是包含了源码目录,于是就写了 AUTOMAKE_OPTIONS=foreign
SUBDIRS=src
如果有文件要编译,则要指明target 先。比如我的src目录底下既有文件,又有目录,而src的这层目录中的文件最后是要编译成一个
可执行文件,则src目录下的Makefile.am这么写。
bin_PROGRAMS= myprogram
SUBDIRS= sub1
myprogram_SOURCES= \ a.cpp\ b.cpp\ # 要编译的源文件。这儿的_SOURCES是关键字
EXTRA_DIST= \ a.h \ b.h
# 不用编成.o,但生成target myprogram也需要给编译器处理的头文件放这里
myprogram_LDADD = libsub1.a 这个_LDADD是关键字,
# 最后生成myprogram这个执行文件,还要link src/sub1这个目录中的内容编成的一个lib :libsub1.a,
myprogram_LDFLAGS = -lpthread -lglib-2.0 -L/usr/bin $(all_libraries)
# myprogram还要link系统中的动态so,以此类推,需要连自编译的so,也写到这个关键字 _LDFLAGS后面就好了。
AM_CXXFLAGS = -D_LINUX
# 传递给g++编译器的一些编译宏定义,选项,
INCLUDES=-IPassport -Isub1/ -I/usr/include/glib-2.0\ -I/usr/lib/glib-2.0/include $(all_includes)
# 传递给编译器的头文件路径。
下面是sub1种生成lib的Makefile.am
noinst_LIBRARIES = libprotocol.a # 不是生成可执行文件,而是静态库,target用noinst_LIBRARIES libprotocol_a_SOURCES = \ alib.cpp
EXTRA_DIST = mylib.h\ alib.h
INCLUDES= -I../ $(all_includes)
AM_CXXFLAGS = -D_LINUX -DONLY_EPOLL -D_SERVER
ok ,最后补上AC_PROG_RANLIB涵义,如果要自己生成lib,然后link到最终的可执行文件中,则要加上这个宏,否则不用。
2 一点讨论 每个目录至少都要有一个target,或者是可执行文件或者是lib,似乎对目录的划分带来点局限。比如我的目录结构如果是这样 ./Src ./Src/sub1 ./Src/sub2 而我想这样,sub1,sub2都没有target,目录划分只是为了区别代码的不同模块,然后把两个目录中编译出的中间文件一起link ,得到最后需要的 myprogram 。 似乎在Src/Makefile.am中要这么写 myprogram_SOURCES = sub1/a.cpp \ sub2/b.cpp
[root@localhost automake]# automake --add-missing
configure.in: installing ''./install-sh''
configure.in: installing ''./missing''
Makefile.am: installing ''depcomp''
[root@localhost automake]# ls
aclocal.m4 autoscan.log configure.in hello.c Makefile.am missing
autom4te.cache configure depcomp install-sh Makefile.in config.h.in
可以看到,在automake之后就可以生成configure.in文件。
5.运行configure
在这一步中,通过运行自动配置设置文件configure,把Makefile.in变成了最终的Makefile。如下所示:
[root@localhost automake]# ./configure
可以看到,在运行configure时收集了系统的信息,用户可以在configure命令中对其进行方便地配置。在./configure的自定 义参数有两种,一种是开关式(--enable-XXX或--disable-XXX),另一种是开放式,即后面要填入一串字符(--with- XXX=yyyy)参数。读者可以自行尝试其使用方法。另外,读者可以查看同一目录下的”config.log”文件,以方便调试之用。
到此为止,makefile就可以自动生成了。回忆整个步骤,用户不再需要定制不同的规则,而只需要输入简单的文件及目录名即可,这样就大大方便了用户的使用。下面的图3.9总结了上述过程:
图3.9 autotools生成Makefile流程图
使用autotools所生成的Makefile
autotools生成的Makefile除具有普通的编译功能外,还具有以下主要功能(感兴趣的读者可以查看这个简单的hello.c程序的makefile):
1.make
键入make默认执行”make all”命令,即目标体为all,其执行情况如下所示:
[root@localhost automake]# make
此时在本目录下就生成了可执行文件“hello”,运行“./hello”能出现正常结果,如下所示:
[root@localhost automake]# ./hello
Hello!Autoconf!
2.make install
此时,会把该程序安装到系统目录中去,如下所示:
[root@localhost automake]# make install
if Gcc -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE=\"hello\" -DVERSION=\"1.0\" -I. -I. -g -O2 -MT hello.o -MD -MP -MF ".deps/hello.Tpo" -c -o hello.o hello.c\
then mv -f ".deps/hello.Tpo" ".deps/hello.Po"else rm -f ".deps/hello.Tpo"exit 1fi
Gcc -g -O2 -o hello hello.o
make[1]: Entering directory ''/root/workplace/automake''
test -z "/usr/local/bin" || mkdir -p -- "/usr/local/bin"
/usr/bin/install -c ''hello'' ''/usr/local/bin/hello''
make[1]: Nothing to be done for ''install-data-am''.
make[1]: LeaVing directory ''/root/workplace/automake''
此时,若直接运行hello,也能出现正确结果,如下所示:
[root@localhost automake]# hello
Hello!Autoconf!
3.make clean
此时,make会清除之前所编译的可执行文件及目标文件(object file, *.o),如下所示:
[root@localhost automake]# make clean
test -z "hello" || rm -f hello
rm -f *.o
4.make dist
此时,make将程序和相关的文档打包为一个压缩文档以供发布,如下所示:
[root@localhost automake]# make dist
[root@localhost automake]# ls hello-1.0-tar.gz
hello-1.0-tar.gz
可见该命令生成了一个hello-1.0-tar.gz的压缩文件。
由上面的讲述读者不难看出,autotools确实是软件维护与发布的必备工具,也鉴于此,如今GUN的软件一般都是由automake来制作的。
没用过,我也是转载的
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)