LeavaTailの日記

LeavaTailの日記

Linuxエンジニアを目指した技術者の備忘録

AutotoolsでMakefileを自動生成する

はじめに

Autotoolsはソフトウェアパッケージ開発ツールの一つである。 www.gnu.org 開発者は、configure.acMakefile.amに必要な情報を記載することで、configureと呼ばれるビルドに必要なライブラリのチェックやビルドに必要なファイルを自動生成するスクリプトファイルを生成することができる。

しかし、記述方式や生成方法が少々トリッキーなところもあり、一からautotoolsに必要なファイルを用意するとなると手間がかかる。 *1 幸いにも、Autotoolsを採用しているパッケージは多く存在するので、それらを参考にすることでとりあえず動作させることはできる。

本記事では、備忘録としてAutotoolsを使用するにあたって参考となるサイトの紹介と必要最低限度の手順を紹介する。

準備

今回は小規模ソフトウェアパッケージを想定として、Autotoolsの使い方をおさらいする。 説明を簡単にするために、対象を下記のようなディレクトリ構成から成るソフトウェアを対象とする。

f:id:LeavaTail:20200626233641p:plain
Autotools導入予定のプロジェクトのディレクトリツリー

上記のソフトウェアはGitHub上に公開してあるのでそちらを参照すると理解しやすいと思う。 (Autotoolsを導入するまでの手順とコミットを対応させて説明しているため)

github.com

このソフトウェアは、「プログラムソースコード」と「マニュアルページ」と「多言語翻訳リソース」の三つから構成される。

  • プログラムソースコード: includesrcの配下にCプログラムファイルとヘッダファイルを管理する。 main.cがプログラムのメイン部分となっており、ここからsub.cにある関数を呼び出す。
  • マニュアルページ: manの配下にマニュアルページを管理する。
  • 多言語翻訳リソース: poの配下に翻訳可能な文字列と日本語の対応関係を管理する。 gettextを利用してローカライズする。

本記事では、このソフトウェアが下記の三つの要件を達成することを目標とする。

  1. ソースコードがビルドするためのMakefileを生成できること
  2. マニュアルページをインストールできるMakefileを生成できること
  3. gettextでローカライズが可能なMakefileを生成できること

また、今回は下記ツールのバージョンで確認している。

  • GNU automake 1.16.1
  • GNU gettext-tools 0.19.8.1

手順

CプログラムのソースコードをビルドできるMakefileの生成

github.com

  1. パッケージのトップディレクトリにMakefile.amを作成する。

     bin_PROGRAMS = test
     test_SOURCES = src/main.c src/sub.c
     AM_CPPFLAGS = -I$(top_srcdir)/include -DLOCALEDIR='"$(localedir)"' -DPACKAGE='"test"'
    

    bin_PROGRAMS = ターゲット: コンパイルによって生成されるバイナリファイルを指定する。
    ターゲット_SOURCE = ソースファイル: ターゲットを生成するために必要なファイルを指定する。 AM_CPPFLAGS = オプション: コンパイラに渡すオプションを指定する。

  2. autoscanコマンドを実行して、configure.scanファイルを生成する。

     $ autoscan
    
  3. configure.scanファイルをconfigure.acにリネームする。

     $  mv configure.scan configure.ac
    
  4. configure.acファイルを必要最低限の修正する。(末尾に「★」を付けた行が対象)

     #                                               -*- Autoconf -*-
     # Process this file with autoconf to produce a configure script.
    
     AC_PREREQ([2.69])
     AC_INIT([test], [1.0], [starbow.duster@gmail.com])    ★ パッケージ名, バージョン, バグレポート用アドレスを記入
     AM_INIT_AUTOMAKE([foreign subdir-objects])            ★ 不要ファイルの自動生成を防ぐforeignとサブディレクトリに対応するためのsubdir-objectsを追加
     AC_CONFIG_SRCDIR([config.h.in])                       ★ ソースコードのディレクトリをconfig.h.inに変更しておくとrenameされた場合にも対応できる
     AC_CONFIG_HEADERS([config.h])
    
     # Checks for programs.
     AC_PROG_CC
    
     # Checks for libraries.
    
     # Checks for header files.
     AC_CHECK_HEADERS([libintl.h locale.h])
    
     # Checks for typedefs, structures, and compiler characteristics.
    
     # Checks for library functions.
     AC_CHECK_FUNCS([setlocale])
    
     AC_CONFIG_FILES([Makefile])
     AC_OUTPUT    
    
  5. プリプロセッサ用のヘッダファイルの生成する。

     $ autoheader
    
  6. automake用のm4ファイルを生成する。

     $ aclocal
    
  7. Makefile.inを生成する。

     $ automake --add-missing
    
  8. configureスクリプトを生成する。

     $ autoconf
    
  9. Makefileの生成・ソフトウェアのビルド・パッケージのインストールできることを確認する。

     $ ./configure
     $ make
     $ make install
    

マニュアルページをインストールできるMakefileを生成

github.com

「CプログラムのソースコードをビルドできるMakefileの生成」との差分のみ説明する。

  1. Makefile.amファイルに以下を追記する。

     man_MANS = man/test.1
    

    man_MANS = ターゲット: マニュアルページのパスを指定する。

gettextでローカライズが可能なMakefileを生成

github.com

「CプログラムのソースコードをビルドできるMakefileの生成」との差分のみ説明する。

  1. configure.acファイルを修正する。(末尾に「★」を付けた行が対象)

    #                                               -*- Autoconf -*-
    # Process this file with autoconf to produce a configure script.
    
    AC_PREREQ([2.69])
    AC_INIT([test], [1.0], [starbow.duster@gmail.com])    
    AM_INIT_AUTOMAKE([foreign subdir-objects])            
    AC_CONFIG_SRCDIR([config.h.in])
    AC_CONFIG_HEADERS([config.h])
    AM_GNU_GETTEXT([external])                                ★ 出力ファイルを自動生成する
    AM_GNU_GETTEXT_VERSION(0.19)                              ★ gettextのバージョンを指定する
    
    # Checks for programs.
    AC_PROG_CC
    
    # Checks for libraries.
    
    # Checks for header files.
    AC_CHECK_HEADERS([libintl.h locale.h])
    
    # Checks for typedefs, structures, and compiler characteristics.
    
    # Checks for library functions.
    AC_CHECK_FUNCS([setlocale])
    
    AC_CONFIG_FILES([po/Makefile.in Makefile])               ★ po/Makefile.inも生成する
    AC_OUTPUT    
    
  2. gettextの基礎となるファイルを生成する。

     $ autopoint
    
  3. Makevars.templateをコピーしてMakevarsを作成する。

     $ cp po/Makevars.template po/Makevars
    
  4. 利用可能な言語を記述するファイルpo/LINGUASを作成する。

     # Set of available languages
     ja
    
  5. 翻訳が必要なファイルを記述するファイルpo/POTFILES.inを作成する。

     # List of source files which contain translatable strings.
     src/main.c
    
  6. 翻訳が必要なファイルを記述するファイルMakefile.amを作成する。

     SUBDIRS = po             ★ 対象としてpo以下も適応する
     bin_PROGRAMS = test
     man_MANS = man/test.1
     test_SOURCES = src/main.c src/sub.c include/func.h
     AM_CPPFLAGS = -I$(top_srcdir)/include
    
  7. 下記のコマンドを実行して、Makefileファイルを生成する。

     $ autoheader
     $ aclocal
     $ automake --add-missing
     $ autoconf
     $ ./configure
    
  8. 多言語翻訳用テンプレートのpo/test.potを生成する。(testの部分はバイナリ名と一致する)

     $ make
    
  9. 多言語翻訳用テンプレートのpo/test.potから日本語翻訳ファイルja.poを新規作成する。

     $ cp po/test.pot po/ja.po
    
  10. 日本語翻訳ファイルja.poを修正する。(末尾に「★」を付けた行が対象)

    # SOME DESCRIPTIVE TITLE.
    # Copyright (C) YEAR Free Software Foundation, Inc.
    # This file is distributed under the same license as the test package.
    # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
    #
    #, fuzzy
    msgid ""
    msgstr ""
    "Project-Id-Version: test 1.0\n"
    "Report-Msgid-Bugs-To: starbow.duster@gmail.com\n"
    "POT-Creation-Date: 2020-06-27 01:09+0900\n"
    "PO-Revision-Date: 2020-06-27 01:10+0900\n"                      ★ このファイルの更新日時を記入する
    "Last-Translator: LeavaTail <starbow.duster@gmail.com>\n"        ★ このファイルを編集した人を記入する
    "Language-Team: ja\n"                                            ★ 翻訳後の言語担当チームを指定する
    "Language: ja\n"                                                 ★ 翻訳後の言語を指定する
    "MIME-Version: 1.0\n" 
    "Content-Type: text/plain; charset=UTF-8\n"                      ★ 文字コード(UTF-8が妥当)を指定する
    "Content-Transfer-Encoding: 8bit\n"
    
    #: src/main.c:14
    msgid "Hello,World!\n"
    msgstr "こんにちは、世界!\n"                                      ★ 日本語翻訳を記述する
    
  11. 多言語翻訳リソースの更新とコンパイル

    $  make -C po/ update-po
    

注意: make installでパッケージのインストールまでしないと、ローカライズされない。

補足

手順の効率化

autoreconfを使う

ここまで手順を紹介してきたが、その中でたくさんのコマンドが登場してきた。 configure.acMakefile.amからconfigureを生成するのに下記の4つのコマンドが必要になる。

  1. autoheader: configure.acからプリプロセッサ用のヘッダファイルの生成する。
  2. aclocal: configure.acからautomake用のm4を生成する。
  3. automake: Makefile.amなどからMakefile.inを生成する。
  4. autoconf: configure.acなどからconfigureを生成する。

autoreconfはこれらの処理を自動的に実行してくれるコマンドである。

OSSライセンスについて

OSS利用者にとって一番気を付けなければいけないことがOSSライセンスである。

  • GNU automakeはGPLv2+
  • GNU AutoconfはGPLv3
  • GNU gettext-toolsはGPLv3+

調べてみると、このあたりを言及している記事はいくつか見つけることができた。
それらによると、GNU automakeとGNU Autoconfを利用することに関しては、強制的にGPLライセンスにされることはないらしい。

どういうことかというと、autotoolsによって生成されるのは全てテキスト(スクリプト)ファイルであり、そこにはライセンス条項がきちんと記載されている。そう、例のGPL文が載っている…のに続いて、As a special exception...というパラグラフがある。

As a special exception to the GNU General Public License, if you distribute this file as part of a program that contains a configuration script generated by Autoconf, you may include it under the same distribution terms that you use for the rest of that program.

趣旨としては、autoconfで自動生成された*1ものであり、かつ、配布物の一部として含まれる場合は、ライセンスはGPLにしなくてもいいよということみたいだ。これなら、会社とかプロプラな組織でも安心してautotoolsが使えるね!

一方でgettext-toolsを利用することに関しては、強制的にGPLライセンスにされると思われる。
以下のようなGPL違反の問題があげられている。

各国語対応のため,gettextパッケージ(GPL-2ライセンス)のソースコードの一部(libintl)を利用したにもかかわらず,該当の配布物(ライセンスを明確にしていないソースコード・非GPLソースコード,およびバイナリのみ公開のライブラリを含む)がGPLでの配布ではなかった

注意: あくまでどちらも私の理解を記述しているだけなので、利用時にはライセンス表記やライセンサーに問い合わせることを推奨する。

おわりに

本記事では、小規模ソフトウェアパッケージを想定として、Autotoolsの手順を紹介した。

今回は、「ソースコードがビルドできる」「マニュアルページをインストールできる」「gettextでローカライズが可能」を目的としたため、最小限のconfigure.acMakefile.amのパラメータを変更した。 しかし、これらのファイルには多数のパラメータが存在しており、さまざまな状況下でも対応することができる。

実際に中/大規模のプロジェクトでAutotoolsを利用するときには、automakeの公式ページや他プロジェクトを確認しておくとよいだろう。

参考

Automake関連

Gettext関連

OSSライセンス関連

*1:cmakeやMesonなど別のツールに乗り換えるのも手ではあるが