autoconf以外の(できればacまたはc ++環境での)使用法を知っている人はいますか?m4
それは、そうでなければ(たとえば「標準」プリプロセッサで)解決するのが困難だった問題を解決するのに役立ちました。 。
スクリプトやプリプロセッサなどを使用して冗長性を削減または最小化するC++でプロジェクトを実行する方法を考えているので、これを尋ねます。
autoconf以外の(できればacまたはc ++環境での)使用法を知っている人はいますか?m4
それは、そうでなければ(たとえば「標準」プリプロセッサで)解決するのが困難だった問題を解決するのに役立ちました。 。
スクリプトやプリプロセッサなどを使用して冗長性を削減または最小化するC++でプロジェクトを実行する方法を考えているので、これを尋ねます。
私はかつてm4を使用して、Windows Visual Studioプロジェクトの単純なバージョン文字列(MAJOR.MINOR.MICRO-STATUS)とSubversionからの情報を含むテキストファイルからC++ヘッダーファイルを生成しました。
m4は、この特定の目標に簡単に埋め込んで使用できる最小のマクロエンジンでした。
それはこのように見えました:
#ifndef __VERSION_H__
#define __VERSION_H__
divert(-1)
define(`CPP_DEFINE', `#define $1 $2')
define(`VERSION', include(`version.txt'))
define(`MY_SOFTWARE_MAJOR', regexp(VERSION, `\([0-9]+\)\.[0-9]+\.[0-9]+', `\1'))
define(`MY_SOFTWARE_MINOR', regexp(VERSION, `[0-9]+\.\([0-9]\)+\.[0-9]+', `\1'))
define(`MY_SOFTWARE_MICRO', regexp(VERSION, `[0-9]+\.[0-9]+\.\([0-9]\)+', `\1'))
define(`MY_SOFTWARE_STATUS', regexp(VERSION, `\(-\w+\)', `\1'))
define(`SVN_REV', `regexp(esyscmd(svnversion -n), `[0-9]+', `\&')')
ifelse(len(SVN_REV), 0, `define(`NO_SVN')')
divert
CPP_DEFINE(MY_SOFTWARE_VERSION, format(`"%s.%s.%s"', MY_SOFTWARE_MAJOR, MY_SOFTWARE_MINOR, MY_SOFTWARE_MICRO))
CPP_DEFINE(PRODUCT_VERSION, format(`"%s.%s.%s%s"', MY_SOFTWARE_MAJOR, MY_SOFTWARE_MINOR, MY_SOFTWARE_MICRO, MY_SOFTWARE_STATUS))
CPP_DEFINE(COPYRIGHT_NOTICE, `"Copyright (C) 2008 - Me"')
ifdef(`NO_SVN', `
CPP_DEFINE(ABOUT_VERSION, format(`"My Software Version %s.%s.%s%s"', MY_SOFTWARE_MAJOR, MY_SOFTWARE_MINOR, MY_SOFTWARE_MICRO, MY_SOFTWARE_STATUS))
CPP_DEFINE(FILE_VERSION, format(`"%s.%s.%s"', MY_SOFTWARE_MAJOR, MY_SOFTWARE_MINOR, MY_SOFTWARE_MICRO))
CPP_DEFINE(INFO_VERSION, format(``%s,%s,%s,0'', MY_SOFTWARE_MAJOR, MY_SOFTWARE_MINOR, MY_SOFTWARE_MICRO))
', `
CPP_DEFINE(ABOUT_VERSION, format(`"My Software Version %s.%s.%s.%s%s"', MY_SOFTWARE_MAJOR, MY_SOFTWARE_MINOR, MY_SOFTWARE_MICRO, SVN_REV, MY_SOFTWARE_STATUS))
CPP_DEFINE(FILE_VERSION, format(`"%s.%s.%s.%s"', MY_SOFTWARE_MAJOR, MY_SOFTWARE_MINOR, MY_SOFTWARE_MICRO, SVN_REV))
CPP_DEFINE(INFO_VERSION, format(``%s,%s,%s,%s'', MY_SOFTWARE_MAJOR, MY_SOFTWARE_MINOR, MY_SOFTWARE_MICRO, SVN_REV))
')
#endif /* __VERSION_H__ */
完全に機能しましたが、これは実際には繰り返しませんでした。主な理由は、CMakeの組み込み機能を使用してそれらを直接処理し、VisualStudioプロジェクトファイルを生成することを好むためです。
GNU Bisonはこれを内部的に使用して、CまたはC++パーサーファイルを生成します。
私はかつてそれを使って、凶悪なSQLクエリの一部を生成しました。印刷すると、クエリはほぼ20ページ、つまり約1200行になりました。私はm4なしではそれを成し遂げることができなかったと確信しています、そして私は二度とそれをする必要がないことに感謝しています。
IIRC(30年前から)、クエリは原告の報告を駆り立てました。原告は、その歴史上の出来事の組み合わせによって分類されました。
SQLエンジンは、ビュー上にビューを構築できず、ユーザー定義関数をサポートしていませんでした。派生テーブル、副選択などのいくつかの長い式、
難しい部分はプログラミングではありませんでした。
最初の難しい部分は、たとえば、3つのわずかに異なるサブセレクトのどれが正しいものであるか、3つの異なるサブセレクトが本当に必要かどうか、または既存の3つと1つまたは2つ以上が本当に必要かどうかを判断することでした。(答えは最終的に「上記のすべて」であることが判明したと思います。)関連するレポートには、同じサブセレクトのいくつかが必要でした。m4+それらが同じであることを保証します。
2番目の難しい部分は、さまざまな複雑な原告の履歴すべてに直面してクエリが正しく機能していることを示すことができるテストデータを構築することでした。Joe Celkoは、ボーイングが当時使用していたいくつかの商用ソフトウェアに私を導いてくれたと思います。それは、いくつかのユーザー定義の基準を取り、すべての可能な組み合わせまたは順列に対してテストハーネスとスタブを生成しました。その名前を覚えていません。(これだと思います:Logic Gem)
私はm4
その機能を使用し、感銘を受けました。これがCプリプロセッサのはずです。私はそれを使用して、より単純なプロジェクト記述からGNUmakefileを生成しました。
Sendmailは、構成ファイルを生成するためのM4ベースのインフラストラクチャを提供します。私が使用したほとんどのsendmailインストールは、sendmailの構成の推奨方法としてこれを提供します。
m4を使用して、構造体宣言のリストを含むC /C++ファイルを生成しました。構造体がどれほど醜いかにもよりますが、正しく実行すれば、m4ファイルはC /C++ファイルよりも読みやすく編集しやすくなります。
GTK+の公式C++バインディングライブラリであるgtkmm(これまでにない最新のC++を介してGTK+ GUIのパワーとリーチにアクセスできる優れたプロジェクト)は、m4
ラッピングコードを簡単に生成するためのツールセットの一部として使用されます。
(私はどのG *プロジェクトとも提携していません。私は多くのことが好きgtkmm
で、特に特定の明白な代替案と比較して、それが可能/あるべきほどよく知られていないと感じています。また、私がm4
それを研究するまで、K&Rであるとは思いもしませんでしたこれ!きちんと。)
私はM4を使用して、SQLテーブルを定義するためのDDLスクリプト、それらにアクセスするためのC ++コードとヘッダー、およびこれをテストするためのドライバーを自動的に生成しました。また、テーブルのバックアップと再入力を同時に行うようにスクリプトを更新したと思いますが、これを行ってから15年以上が経過しています。
cppとm4の両方を使用して、ファイル内のトークンを置き換え、さまざまなターゲットプラットフォーム用のパッケージファイルを生成しました。これを行うには、rubyerbを使用します。太陽の下で、ヘッダーファイルの前処理にm4を使用しました