6

私のCプロジェクトでは、プリプロセッサ ディレクティブを使用して一部の機能をアクティブ化/非アクティブ化しています。数日前に .xml 内で行われた変更が原因で、あまり一般的ではない構成の一部がコンパイルされなくなったことは珍しいことではありません#ifdef

スクリプトを使用して最も一般的な構成をコンパイルしますが、すべてが確実にコンパイルされるようにするためのツールを探しています (私たちの場合、テストは問題ではありません。コンパイルが停止しないことをできるだけ早く検出したいだけです)。通常、ifdefs / ifndefs は独立しているため、通常、各モジュールを 2 回だけコンパイルする必要があります (すべてのシンボルが定義され、すべて未定義)。しかし、場合によっては ifdef がネストされているため、それらのモジュールをさらに何度もコンパイルする必要があります。

すべての ifdef / ifndef (ネストされたものも含む) を検索し、コードのすべてのソース行を確実にするためにモジュールをコンパイルする必要がある回数 (それぞれで定義されるプリプロセッサ シンボルのセットを使用) を提供するツールを知っていますか?コンパイラによって解析されますか?

4

8 に答える 8

4

あなたがやりたいことをするためのツールを知りません。しかし、あなたの問題を見ると、プリプロセッサシンボルの可能なすべての組み合わせでソースをコンパイルするスクリプトだけが必要だと思います。

あなたが持っているかどうかを言うように..

#ifdef A 
    CallFnA();
#ifdef B
    CallFnB();
#endif
    CallFnC();
#endif

次の組み合わせでビルドをトリガーする必要があります

  1. A と B の両方が定義されている
  2. A が定義されておらず、 B が定義されています (ここでは意味がありませんが、モジュール全体で必要です)
  3. A が定義され、B が定義されていない
  4. A と B の両方が定義されていません

grepソースコードを作成して組み合わせを生成するスクリプトを見たいと思っています。何かのようなもの

find ./ -name '*.cpp' -exec egrep -h '^#ifdef' {} \; | awk '{ print $2}' | sort | uniq

*.cpp を検索したいファイルに置き換えます。

于 2010-01-06T11:55:40.300 に答える
2

これは、#ifdef エントリを解析し、特定のファイルで使用されているシンボルのリストを組み立てるハックな仕事をする Perl スクリプトです。次に、そのシンボルをオンまたはオフにするすべての可能な組み合わせのデカルト積を出力します。これは私の C++ プロジェクトで機能しますが、セットアップに微調整が必​​要になる場合があります。

#!/usr/bin/perl

use strict;
use warnings;

use File::Find;

my $path = $ENV{PWD};

my $symbol_map = {};
find( make_ifdef_processor( $symbol_map ), $path );

foreach my $fn ( keys %$symbol_map ) {
   my @symbols = @{ $symbol_map->{$fn} };

   my @options;
   foreach my $symbol (@symbols) {
      push @options, [
         "-D$symbol=0",
         "-D$symbol=1"
      ];
   }

   my @combinations = @{ cartesian( @options ) };
   foreach my $combination (@combinations) {
      print "compile $fn with these symbols defined:\n";
      print "\t", join ' ', ( @$combination );
      print "\n";
   }
}

sub make_ifdef_processor {
   my $map_symbols = shift;

   return sub {
      my $fn = $_;

      if ( $fn =~ /svn-base/ ) {
         return;
      }

      open FILE, "<$fn" or die "Error opening file $fn ($!)";
      while ( my $line = <FILE> ) {
         if ( $line =~ /^\/\// ) { # skip C-style comments
            next;
         }

         if ( $line =~ /#ifdef\s+(.*)$/ ) {
            print "matched line $line\n";
            my $symbol = $1;
            push @{ $map_symbols->{$fn} }, $symbol;
         }
      }
   }
}

sub cartesian {
   my $first_set = shift @_;
   my @product = map { [ $_ ] } @$first_set;

   foreach my $set (@_) {
      my @new_product;
      foreach my $s (@$set) {
         foreach my $list (@product) {
            push @new_product, [ @$list, $s ];
         }
      }

      @product = @new_product;
   }

   return \@product;
}

これは、C スタイルの /* */ コメントでは確実に失敗します。それらを効果的に解析することを気にしなかったからです。考慮すべきもう 1 つのことは、すべてのシンボルの組み合わせをテストするのは意味がない可能性があり、それをスクリプトまたはテスト サーバーに組み込む可能性があるということです。たとえば、プラットフォームを指定するために相互に排他的なシンボルがある場合があります。

-DMAC
-DLINUX
-DWINDOWS

これらのオンとオフの組み合わせをテストすることは、実際には意味がありません。簡単な解決策の 1 つは、すべての組み合わせをコンパイルすることです。正しさのテストは、コンパイルが常に失敗し、同じ組み合わせで成功することです。

覚えておくべきもう 1 つのことは、それらの多くはネストされていないため、すべての組み合わせが有効であるとは限らないということです。コンパイルは比較的安価だと思いますが、注意しないと組み合わせの数がすぐに増えてしまいます。どのシンボルが同じ制御構造 (ネストされた #ifdefs など) にあるかをスクリプトが解析するようにすることもできますが、それを実装するのははるかに難しいため、ここでは実行しませんでした。

于 2010-01-07T08:14:39.960 に答える
1

unifdef -sを使用して、プリプロセッサ条件で使用されるすべてのプリプロセッサ シンボルのリストを取得できます。他の回答に関する議論に基づいて、これは明らかに必要な情報ではありませんが、 -d オプションも使用すると、デバッグ出力にネストレベルが含まれます。出力をフィルタリングして、必要なシンボルの組み合わせを生成するのはかなり簡単です。

于 2010-01-18T21:03:53.887 に答える
0

申し訳ありませんが、私はあなたを助けるツールを知りませんが、これを行う必要がある場合は、これを行う簡単なスクリプトを使用します: - すべてのソース ファイルを別の場所にコピーします。 - 実行中の番号を追加します (コメントで、明らかに) 各行の開始時 (最初のファイルの最初のコード行 = 1、ファイル間でリセットしないでください) - 事前定義されたすべての構成を使用して前処理し、どの行が含まれていてどの行が含まれていないかを確認します。 - チェックどの行が含まれていて、どの行が欠落しているか。

Perl や Python などを使用して実行するのに数日以上かかることはありません。必要なのは、構成を含む行を含むファイルです。これは、このスクリプトの助けを借りて行うのに十分な速さです。構成にまだ含まれていない行を確認し、すべての行が含まれるまでファイルを編集します。次に、これを時々実行して、新しいパスがないことを確認します。

あなたが望むようにソースを分析することは、はるかに複雑なスクリプトであり、それが面倒な価値があるかどうかはわかりません.

于 2010-01-07T08:15:12.637 に答える
0

もう 1 つの解決策は、すべての機能をコンパイルして、機能のランタイム構成テストを行うことです。構成ファイルに値を設定するだけで、マーケティングがさまざまな構成を販売し、エンジニアリングの時間を節約できるため、これは優れた「トリック」です。

それ以外の場合は、すべての構成を構築するためのスクリプト言語をお勧めします。

于 2010-01-07T00:28:11.203 に答える
-2

マトリックス プロジェクトでHudsonを使用できます。(Hudson は単なる Java テスト ツールではなく、C/C++ プロジェクトを含むほぼすべてのものをビルドできる非常に柔軟なビルド サーバーであることに注意してください)。マトリックス プロジェクトを設定すると、1 つまたは複数のを作成するオプションが表示されます。軸ごとに、1 つ以上の値を指定できます。Hudson は、変数値のすべての可能な組み合わせを使用してビルドを実行します。たとえば、次のように指定すると

os=windows,linux,osx
wordsize=32,64

Hudson は6 つの組み合わせを作成します。各 Windows、Linux、および osx の 32 ビットおよび 64 ビット バージョン。「フリー スタイル プロジェクト」をビルドする場合 (つまり、外部ビルド スクリプトを起動する場合)、構成は環境変数を使用して指定されます。上記の例では、「os」と「windows」が環境変数として指定されます。

Hudson は、特定の無効な組み合わせの構築を避けるために、組み合わせのフィルター処理もサポートしています (たとえば、Windows 64 ビットは削除できますが、その他はすべて保持されます)。

(マトリックス プロジェクトの詳細を提供するために投稿を編集しました。)

于 2010-01-06T12:22:14.693 に答える
-2

うーん、最初はunifdefが役立つかもしれないと思っていましたが、あなたが何を求めているかをさらに調べてみると、いや、すぐには役に立ちません。

于 2010-01-06T12:00:40.203 に答える
-3

あなたはgrepが必要ですか?

于 2010-01-06T11:40:51.190 に答える