Вот сценарий Perl, который выполняет хакерскую работу по разбору записей #ifdef и собирает список символов, используемых в конкретном файле. Затем он выводит Декартово произведение всех возможных комбинаций включения или выключения этого символа. Это работает для моего проекта 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, так как я не удосужился их эффективно проанализировать. Еще одна вещь, о которой следует подумать, это то, что тестирование всех комбинаций символов может не иметь смысла, и вы можете встроить это в скрипт или свой тестовый сервер. Например, у вас могут быть взаимоисключающие символы для указания платформы:
-DMAC
-DLINUX
-DWINDOWS
Тестирование комбинаций их включения и выключения на самом деле не имеет смысла. Одним из быстрых решений является просто скомпилировать все комбинации и быть уверенным, что некоторые из них не сработают. Ваш тест на правильность тогда может заключаться в том, что компиляция всегда завершается неудачно и успешно с одними и теми же комбинациями.
Еще одна вещь, которую следует помнить, это то, что не все комбинации допустимы, потому что многие из них не являются вложенными. Я думаю, что компиляция относительно дешева, но количество комбинаций может очень быстро вырасти, если вы не будете осторожны. Вы можете заставить скрипт анализировать, какие символы находятся в одной и той же управляющей структуре (например, вложенные #ifdefs), но это намного сложнее реализовать, и я этого здесь не делал.
person
James Thompson
schedule
07.01.2010