zoukankan      html  css  js  c++  java
  • (6)autotools工具的使用

       autotools是专门用来生成Makefile的一系列工具,包括autoscan、aclocal、autoheader、autoconf、automake等。

        (1)autotools解决了什么问题

    在大型项目中,使用手写Makefile时,可能会很复杂并难以维护;
    在不同的编译环境,由于参数不同,需要手写不同的Makefile,增加了工作量;
    由于Makefile有一些复杂的参数,手写Makefil可能会不符合规范;

       autotools工具能够帮助开发人员简单而快捷地生成Makefile,完成各种复杂工程地编译和链接。

        (2)autotools生成Makefile的流程

     

    1. 源码根目录调用autoscan脚本,生成configure.scan文件,然后将此文件重命名为configure.ac(或configure.in,早期使用.in后缀);
    2. 修改【configure.ac】,利用autoconf提供的各种M4宏,配置项目需要的各种自动化探测项目;
    3. 编写【自定义宏】,建议每个宏一个单独的*.m4文件;
    4. 调用aclocal收集configure.ac中用到的各种非Autoconf的宏,包括自定义宏;
    5. 调用autoheader,扫描configure.ac(configure.in)、acconfig.h(如果存在),生成config.h.in宏定义文件,里面主要是根据configure.ac中
    某些特定宏(如AC_DEFINE)生成的#define和#undefine宏,configure在将根据实际的探测结果决定这些宏是否定义(具体见后面例子)。
    6. 按照automake规定的规则和项目的目录结构,编写一个或多个【Makefile.am】(Makefile.am数目和存放位置和源码目录结构相关),Makefile.am主要写的
    就是编译的目标及其源码组成。
    7. 调用automake,将每个Makefile.am转化成Makefile.in,同时生成满足GNU编码规范的一系列文件(带-a选项自动添加缺少的文件,但有几个仍需要自己添加,
    在执行automake前需执行
    touch NEWS README AUTHORS ChangeLog)。如果configure.ac配置了使用libtool(定义了AC_PROG_LIBTOOL宏(老版本)或
    LT_INIT宏),需要在此步骤前先在项目根目录执行
    libtoolize --automake --copy --force,以生成ltmain.sh,供automake和config.status调用。 8. 调用autoconf,利用M4解析configure.ac,生成shell脚本configure。以上几步完成后,开发者的工作就算完成了,后面的定制就由开源软件的用户根
    据需要给configure输入不同的参数来完成。
    9. 用户调用configure,生成Makefile,然后make && make install。

        autotools系列工具简单操作示例如下:

        现有test文件夹存在如下文件:

    //test
    calc_test.h
    calc_test.cpp
    make_test.h
    make_test.cpp
    main.cpp

        步骤一:在test目录同级目录下执行autoscan test 或者 在test目录下执行autoscan

         步骤二:更改生成的configure.scan 为configure.ac,编辑并修改为以下内容(标粗的是新添加或者修改的内容)

    #                                               -*- Autoconf -*-
    # Process this file with autoconf to produce a configure script.
    
    AC_PREREQ([2.69])
    AC_INIT([autotest], [1.0], [BUG-REPORT-ADDRESS])
    AM_INIT_AUTOMAKE([foreign -Wall -Werror])
    AC_CONFIG_SRCDIR([calc_test.cpp])
    AC_CONFIG_HEADERS([config.h])
    
    # Checks for programs.
    AC_PROG_CXX
    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

         步骤三:依此执行aclocal命令、autoheader、autoconf命令,生成configure文件

         步骤四:新建Makefile.am命令

    bin_PROGRAMS = autotest
    autotest_SOURCES =  calc_test.h   
                        calc_test.cpp 
                        make_test.cpp 
                        main.cpp
    autotest_LDADD =
    autotest_LDFLAGS =
    autotest_CFLAGS = -g

        步骤五:执行automake --add-missing

        步骤六:执行./configure命令生成Makefile

     

        (3)autotool参数详解

        1)configure.scan的参数

    标签名  说明
    AC_PREREQ 声明autoconf要求的版本号
    AC_INIT 定义软件名称、版本号、联系方式
    AM_INIT_AUTOMAKE 必须要的,指定编译参数
    AC_CONFIG_SRCDIR 用来侦测所指定的源码文件是否存在, 来确定源码目录的有效性
    AC_CONFIG_HEADER 指定产生的配置文件名称(一般是config.h),用于生成config.h文件,以便 autoheader 命令使用
    AC_PROG_CC 用以探测当前系统的C编译器
    AC_PROG_RANLIB 用于生成静态库
    AC_PROG_LIBTOOL 用于生成动态库
    AM_PROG_AR 生成静态库时使用,用于指定打包工具,一般指ar
    AC_CONFIG_FILES 告知autoconf本工程生成哪些相应的Makefile文件,不同文件夹下的Makefile通过空格分隔
    AC_OUTPUT 最后一个必须的宏,用以输出需要产生的文件
    AC_PROG_CXX 用于探测系统的c++编译器
    AC_CHECK_LIB 探测工程中出现的库文件及库文件中的方法

      2)Makefile.am的参数

    include_HEADERS 标明哪些头文件将在执行make install命令之后被安装到系统include目录下
    bin_PROGRAMS 生成的目标库文件名,如果有多个,用空格隔开,与configure.ac中AC_INIT对应库名对应
    XXX_SOURLDADDCES 编译XXX库需要哪些源文件,使用相对路径
    XXX_LDADD 指定要链接的静态库名称
    LIBS 
    指定要链接的动态库名称
    INCLUDE 一般指定要使用的头文件所在路径
    AUTOMAKE_OPTIONS

    设置automake的选项automake提供了三种软件等级:foreign、gnu和gnits,当当前库文件编译所需源文件不在当前目录时要设置参数subdir-objects

    XXX_CPPFLAGS 预处理器选项,编译选项,一般用来指定所需要头文件目录
    noinst_LIBRARIES 指定生成的静态库名称,当前目录下源码及头文件最终生成的目标文件名
    AM_V_AR 指定把目标打包成静态库,使用ar命令
    RANLIB 指定为静态库创建索引,使用ranlib

        (4)autotools使用范例

        1)单个Makefile.am生成多个库文件

        现test文件夹下有如下文件

    //用于生成 make_test 动态库
    calc_test.h
    calc_test.cpp
    make_test.h
    make_test.cpp
    main.cpp
    //用于生成 tiny_test 动态库
    tinyxml2_main.cpp
    tinyxml2.h //在/usr/include/tinyxml2路径下
    tinyxml2.cpp //在/usr/include/tinyxml2路径下

       使用autoscan生成configure.in,并改名为configure.ac,修改添加参数后如下:

    #                                               -*- Autoconf -*-
    # Process this file with autoconf to produce a configure script.
    
    AC_PREREQ([2.69])
    AC_INIT([make_test tiny_test], [1.0 1.0], [1577429698@qq.com])
    AC_CONFIG_SRCDIR([calc_test.cpp])
    AC_CONFIG_SRCDIR([../../../usr/include/tinyxml2/tinyxml2.cpp])
    AM_INIT_AUTOMAKE([foreign -Wall -Werror])
    AC_CONFIG_HEADERS([config.h])
    
    # Checks for programs.
    AC_PROG_CXX
    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

        Makefile.am书写如下:

    #include_HEADERS = /usr/include/tinyxml2/tinyxml2.h 
    bin_PROGRAMS = make_test tiny_test
    AUTOMAKE_OPTIONS = subdir-objects
    #INCLUDE = -l/usr/include/tinyxml2/
    make_test_SOURCES = calc_test.h    
                        calc_test.cpp  
                        make_test.cpp  
                        main.cpp
    tiny_test_SOURCES = tinyxml2_main.cpp 
                        tinyxml2.h        
                        ../../../usr/include/tinyxml2/tinyxml2.cpp
    make_test_LDADD = 
    make_test_LDFLAGS =
    make_test_CFLAGS = -g #-I/usr/include/tinyxml2/  

         2)多级源码路径多个Makefile.am生成多个库文件(包含动态库及静态库使用)

        参考https://blog.csdn.net/zhengqijun_/article/details/70105077

        在test目录下,make_test子目录将单独生成一个动态库make_test,tinyxml子目录单独生成一个静态库tinyxml2,test本身目录引用tinyxml目录生成的静态库和自身文件再生成一个动态库tiny_test;

        make_test及tinyxml子目录下各自有的configure.ac文件和Makefile.am文件配合在一起单独使用,生成相应库;make_test及tinyxml目录下Makefile.am文件和test根目录下Makefile.am及总configure.ac文件配合在一起也可组合生成三个库。

        1.文件树状图:

      

        2.文件内容:

        2.1 tinyxml2_main.cpp

    #include <iostream>
    //必须写相对路径
    #include "tinyxml/tinyxml2.h"
    using namespace std;
    using namespace tinyxml2;
    
    int main(int argv,char *argc[])
    {
      XMLDocument xmlDoc;
      xmlDoc.LoadFile("test.xml");
      int errorID = xmlDoc.ErrorID();
      if(errorID)
      {
        cout<<"Load xml test.xml fail!"<<endl;
        return -1;
      }
      cout<<"Load xml test.xml success!"<<endl;
      XMLElement *pRootElement = xmlDoc.RootElement();
      const char * name = pRootElement->FirstChildElement("name")->GetText();
      cout<<"name = "<<name<<endl;
      return 0;
    }

        2.2 configure.ac

    #                                               -*- Autoconf -*-
    # Process this file with autoconf to produce a configure script.
    
    AC_PREREQ([2.69])
    AC_INIT([tiny_test], [1.0], [1577429698@qq.com])
    AC_CONFIG_SRCDIR([tinyxml2_main.cpp])
    AC_CONFIG_SRCDIR([make_test/calc_test.cpp])
    AC_CONFIG_SRCDIR([tinyxml/tinyxml2.cpp])
    AM_INIT_AUTOMAKE([foreign -Wall -Werror])
    
    AC_CONFIG_HEADERS([config.h])
    
    # Checks for programs.
    AC_PROG_CXX
    AC_PROG_CC
    AC_PROG_RANLIB
    AM_PROG_AR([ar])
    # Checks for libraries.
    
    # Checks for header files.
    AC_CHECK_HEADERS([limits.h stddef.h stdint.h stdlib.h string.h])
    
    # Checks for typedefs, structures, and compiler characteristics.
    AC_CHECK_HEADER_STDBOOL
    AC_C_INLINE
    AC_TYPE_INT64_T
    AC_TYPE_SIZE_T
    AC_CHECK_TYPES([ptrdiff_t])
    
    # Checks for library functions.
    AC_CHECK_FUNCS([memset strchr])
    
    AC_CONFIG_FILES([Makefile
                     make_test/Makefile
                     tinyxml/Makefile])
    AC_CONFIG_SUBDIRS([make_test
                       tinyxml])

        2.3 Makefile.am

    AUTOMAKE_OPTIONS = foreign
    SUBDIRS = tinyxml make_test
    bin_PROGRAMS = tiny_test
    tiny_test_SOURCES = tinyxml2_main.cpp
    #INCLUDE = -I ./tinyxml
    #静态库连接
    #tiny_tes_CFLAGS = -I ./tinyxml
    tiny_test_LDADD = tinyxml/libtinyxml2.a
    
    #动态库连接

        2.4 make_test/Makefile.am

    bin_PROGRAMS = make_test
    make_test_SOURCES = calc_test.h    
                        calc_test.cpp  
                        make_test.h    
                        make_test.cpp  
                        main.cpp
    make_test_LDADD =
    make_test_LDFLAGS =
    make_test_CFLAGS = -g

        2.5 make_test/configure.ac

    #                                               -*- Autoconf -*-
    # Process this file with autoconf to produce a configure script.
    
    AC_PREREQ([2.69])
    AC_INIT([make_test], [1.0], [1577429698@qq.com])
    AM_INIT_AUTOMAKE([foreign -Wall -Werror])
    AC_CONFIG_SRCDIR([calc_test.cpp])
    AC_CONFIG_HEADERS([config.h])
    
    # Checks for programs.
    AC_PROG_CXX
    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

        2.6 make_test/calc_test.h

    #ifndef _CALC_TEST_H_
    #define _CALC_TEST_H_
    namespace test
    {
    
      int add(int a,int b);
    
    }
    #endif

        2.7 make_test/clac_test.cpp

    #include "calc_test.h"
    namespace test
    {
      int add(int a,int b)
      {
        return a + b ;
      }
    }

        2.8 make_test/make_test.h

    #ifndef _MAKE_TEST_
    #define _MAKE_TEST_
    #include <iostream>
    namespace test
    {
      class MakeTest
      {
        public:
          void run();
      };
    }

        2.9 make_test/make_test.cpp

    #include "make_test.h"
    #include "calc_test.h"
    namespace test
    {
      void MakeTest::run()
      {
        int a = 10;
        int b = 10;
        std::cout<<test::add(a,b)<<std::endl;
      }
    }

        2.10 make_test/main.cpp

    #include <iostream>
    #include "string.h"
    #include "make_test.h"
    
    using namespace std;
    
    int main()
    {
      test::MakeTest makeTest;// = new MakeTest();
      makeTest.run();
      return 0;
    }

        2.11 tinyxml/Makefile.am

    noinst_LIBRARIES = libtinyxml2.a
    libtinyxml2_a_SOURCES = tinyxml2.h tinyxml2.cpp
    #AM_V_AR = ar
    RANLIB = ranlib

        2.12 tinyxml/configure.ac

    #                                               -*- Autoconf -*-
    # Process this file with autoconf to produce a configure script.
    
    AC_PREREQ([2.69])
    AC_INIT([tinyxml2], [1.0], [1577429698])
    AM_INIT_AUTOMAKE([foreign -Wall -Werror])
    AC_CONFIG_SRCDIR([tinyxml2.cpp])
    AC_CONFIG_HEADERS([config.h])
    
    # Checks for programs.
    AC_PROG_CXX
    AC_PROG_CC
    AC_PROG_RANLIB
    AM_PROG_AR([ar])
    
    # Checks for libraries.
    
    # Checks for header files.
    AC_CHECK_HEADERS([limits.h stddef.h stdint.h stdlib.h string.h])
    
    # Checks for typedefs, structures, and compiler characteristics.
    AC_CHECK_HEADER_STDBOOL
    AC_C_INLINE
    AC_TYPE_INT64_T
    AC_TYPE_SIZE_T
    AC_CHECK_TYPES([ptrdiff_t])
    
    # Checks for library functions.
    AC_CHECK_FUNCS([memset strchr])
    
    AC_CONFIG_FILES([Makefile])
    AC_OUTPUT

        configure.ac文件均是由autoscan命令生成的configure.scan修改改名而来;在前面文件创建、均被完毕之后,执行以下命令:

    aclocal
    autoconf
    autoheader
    automake --add-missing
    ./configure
    make

         结果如下:

  • 相关阅读:
    gitlab搭建
    java数组
    安裝nextcloud
    Spring的定时任务@Scheduled(cron = "0 0 1 * * *")
    java内存结构(下)
    java内存结构(上)
    多线程的三个特性
    @RequestBody用法
    SwaggerAPI注解详解(转载)
    在jpanel中添加jbutton并自由设置按钮大小和位置
  • 原文地址:https://www.cnblogs.com/MenAngel/p/11592104.html
Copyright © 2011-2022 走看看