这里有一个Perl脚本,它可以粗略地解析#ifdef条目,并组装出特定文件中使用的符号列表。然后,它打印出所有可能的组合,包括该符号开启或关闭的
笛卡尔积。这适用于我的C++项目,但可能需要对您的设置进行微调。
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 =~ /^\/\// ) {
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
测试这些组合开启和关闭的效果并没有实际意义。一种快速解决方案是编译所有组合,并且对于一些将会失败的组合保持警惕。你的正确性测试可以是编译总是失败和成功相同的组合。
另一个需要记住的事情是并非所有组合都有效,因为其中许多并不是嵌套的。我认为编译相对便宜,但是如果您不小心,组合数量可能会迅速增长。您可以使脚本解析哪些符号位于同一控制结构中(例如嵌套的#ifdef),但这更难实现,我在这里没有这样做。