(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

     結果如下:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM