web-dev-qa-db-ja.com

IDEを使用せずにcppファイルからヘッダーファイルを自動的に生成/更新するにはどうすればよいですか?

私はここ数年、C++開発にVIMを使用していますが、IDEまたは強力なテキストエディタを使用するかどうかについては、議論したくありません。ソフトウェア開発。これまで私は、すべてがテンプレートであるかインラインで宣言されているヘッダーのみのテンプレートライブラリに主に関与してきました。したがって、.cppファイルは主要な役割を果たしません。

最近、私は「従来の」C++開発にもっと関わり、ヘッダー/非ヘッダーファイルの同期という古い問題に直面しています。 makeターゲットで使用したり、このジョブを処理するためにVIMに統合したり、.cppファイルに基づいてヘッダーファイルを更新したりできるコマンドラインツールがあるかどうか疑問に思っています。基本的に、クラス/構造または(テンプレートおよびインライン)実装の宣言はヘッダーファイルでは無視する必要がありますが、関数宣言は.cppファイルに基づいて追加、削除、または更新する必要があります。

lzz ツールを知っていますが、実際に追加の3番目のファイル形式でコーディングし、実際にコンパイルする前に.h /.cppファイルに前処理する必要があります。

その仕事をすることができる何かが周りにありますか?他の非IDE開発者はこの問題をどのように処理しますか?

22
barbaz

私自身、最初の質問への回答に非常に興味がありますので、残念ながらここでは良いアドバイスをすることはできません。

少なくとも2番目の質問に答えるには、これは、同期していないヘッダーファイルで欠落している宣言を手動で追加したり、変更された宣言を調整したりするために使用する、やや半自動の方法です。

警告を有効にして(!)コンパイラを使用して、欠落/変更された宣言を見つけます。

宣言を調整する

関数定義のシグネチャを変更した後、gccは次のようなエラーをスローします。

  • error: conflicting types for ‘....’
    note: previous declaration of ‘....’ was here

定義への参照と対応する宣言の両方がすでにエラーメッセージに示されているため、これを修正するのは比較的簡単です。

私はemacsユーザーなので、これがviで行われる方法を説明することはできませんが、この場所に自動的にジャンプする同様に簡単な方法があると確信しています。実行する必要があるのは次のとおりです。

  • 場所にジャンプ1行をコピー

  • 場所2にジャンプし、古い行をコピーに置き換えて、末尾に;を追加します。

宣言がありません

一方、対応するヘッダーファイルにプロトタイプを追加せずに新しい関数が追加された場合、gccは次のようなものをスローします。

  • warning: implicit declaration of function ...

これを修正すると、タグテーブルが役立ちます。繰り返しますが、これがviでどのように処理されるかはわかりませんが、コンパイラの警告でその名前で指定された関数定義にすばやくジャンプする方法があると確信しています。

ここでのワークフローは次のようになります。

  • 関数にジャンプ....の定義、行をコピー

  • ヘッダーファイルに切り替え、行を貼り付けて、末尾に;を追加します

この方法は洗練されたものではありませんが、ヘッダーを調整してソースファイルと同期するのを忘れた場合に機能することがわかりました。これは、数回のキーストロークで実行できます。

壊れた例

ここで例を挙げてそのアプリケーションを示すために、ヘッダーを修正する必要がある最小限のプログラムを示します。

/* main.c */
#include "add.h"

int main (int argc, char *argv[]) {
  int a=0, b=0;

  add (a, b);
  sub (a, b);

  return 0;
}

関数addsubはどちらも、以下に示すadd.cで定義されています。

/* add.c */
#include "add.h"

int add (int a, int b) {
  return a + b;
}

int sub (int a, int b) {
  return a - b;
}

犯人add.hは、関数addの署名の不一致と、関数subの宣言の欠落の両方を示しています。

/* add.h */
long add (long a, long b);

コンパイルしようとすると、次のようになります。

gcc -Wall main.c add.c
main.c: In function ‘main’:
main.c:7: warning: implicit declaration of function ‘sub’
add.c:3: error: conflicting types for ‘add’
add.h:2: note: previous declaration of ‘add’ was here

例の修正

宣言がありません

最初の問題:

  • main.c:7: warning: implicit declaration of function ‘sub’

subの宣言がadd.hにないという事実によるものです

適切な署名を見つける:

  • C-x` (次のエラー)エラーの場所にジャンプします
  • M-. (gtags-find-tag)は、検索するタグの入力を求めます
  • RET ポイントのシンボルがデフォルトであるため、subの定義にジャンプします
  • M-z{ (zap-to-char) C-y (ヤンク)署名をコピーする

ここまでは、介入が必要なかったため、キーボードマクロによってすべての手順を自動的に実行することもできました。次の部分は手作業で行う必要があります。

  • 「正しい」ヘッダーファイルを開く
  • 宣言を入力する場所に移動します

「正しい」ヘッダーファイルと「正しい」場所の選択は、これまでに行った手順とは対照的に、おそらく好みの問題であるため、ここで可能な自動化はあまりないと思います。

最後のステップは、コピーした署名を貼り付けることです。

  • C-yM-y コピーした署名を貼り付けます
  • DEL;{;に置き換える

宣言の調整

次に、adds宣言と定義の不一致を修正する必要があります。

add.c:3: error: conflicting types for ‘add’
add.h:2: note: previous declaration of ‘add’ was here

定義から新しい署名をコピーするには:

  • C-x` (次のエラー)は定義の場所にジャンプします
  • M-z{ (zap-to-char) C-y (ヤンク)署名をコピーする

宣言を置き換えるには:

  • C-x` (次のエラー)は宣言の場所にジャンプします
  • M-z; (zap-to-char)古い宣言を削除します
  • C-yM-y コピーした署名を貼り付けます
  • DEL;{;に置き換える

そしてまた戻って

2つのバッファがポップされたので:

  • M-2M-xburry-buffer 以前にアクセスしたバッファに戻る必要があります

概要

ご覧のとおり、時間のかかるプロセスではありませんが、このアプローチを使用して宣言の欠落や誤りを修正するために絶えず前後にジャンプすることは、依然としてかなり退屈な作業です。最初の実行でタイプミスまたは完全に欠落した宣言を修正するためにのみ使用します。

「正しい」宣言を手動でヘッダーに配置することは、今でも私がとる主なアプローチです。

実装する前にAPIをレイアウトすることは、私見では最悪の考えではないかもしれないので、この戦略はそれほど悪い選択であってはなりません。

6
mikyra

UNIXタイプのシステムでは、通常、IDEはこのジョブを処理しません(私の経験では)。ビルドツール(通常、Eclipse、EmacsなどのIDEにはバンドルされていません)がこの作業を行います。

最近のシステムでは、これを処理する最良の方法は、コンパイラにそれを行わせることです。結局のところ、コンパイラは最もよく知っています。 GCCおよび他のほとんどのUNIX/POSIXコンパイラには、ソースファイルのコンパイル中にmakeスタイルの依存関係宣言を発行するオプションがあります。これをmakefileに配置してから、出力ファイルをmakefileに含めるだけで、すべてが非常にうまく機能します。

たとえば、次を参照してください。 http://make.mad-scientist.net/autodep.html

次に、-MMD -MPなどのGCCオプションを確認します(これらはプリプロセッサオプションです)。

1
MadScientist