Statistics
| Branch: | Revision:

root / src / utils / opp_runall @ master

History | View | Annotate | Download (5.8 KB)

1
#!/usr/bin/env perl
2
#
3
# Generates a makefile that executes several simulation runs, and
4
# optionally invokes "make" as well.
5
#
6
# Author: Andras Varga
7
#
8

    
9
use Cwd;
10
use Config;
11
use IO::File; # for temp files
12
use POSIX qw(tmpnam);
13

    
14
#TODO: ha nincs -u, rakja bele
15
#TODO: ha nincs -r, talalja ki
16
#TODO: tamogassa a -r1,2 szintaxist is (space nelkul!)
17

    
18
sub makeMakefile();
19

    
20
$ARG0 = $0;
21
$originalArgs = $ARG0 . " " . join(" ", @ARGV);
22

    
23
$tempfilename = "";
24

    
25
$verbose = 0;
26
@simProg = "";
27
@simProgArgs = ();
28
$jOption = "";
29
$makefileToExport = "";
30

    
31
makeMakefile();
32
exit 0;
33

    
34

    
35
sub usage()
36
{
37
    my $prog = $ARG0;
38
    $prog =~ s|^.*[/\\]||;
39

    
40
    print <<END
41
$prog: Generate a makefile that executes several simulation runs, and
42
optionally invokes "make" as well.
43

    
44
Usage: $prog [options] <simprog> [simprog-options]
45

    
46
Should be called with the full command (simulation program with args)
47
to be executed, and the output is a Makefile that contains one target
48
per run. This program basically expands the -r option; for example, a
49
simulation command line containing -r 0..2,8,10 will generate 5 commands
50
with the -r 0, -r 1, -r 2, -r 8 and -r 10 options, respectively. It is possible
51
to take advantage of multiple CPUs or cores by using the -j make option
52
(GNU Make specific).
53

    
54
Options:
55
    -h, --help            This help text
56
    -V                    Verbose
57
    --export <filename>   Write a makefile but do not run it; recommended
58
                          name is Runfile
59
    -j<number>            Make use of multiple CPUs; this options gets passed
60
                          to the "make" program without being looked at
61
    --                    Denotes end of options (everything after that is
62
                          treated as part of the simulation command line)
63
END
64
}
65

    
66
sub makeMakefile()
67
{
68
    #
69
    # process command line args
70
    #
71
    while (@ARGV)
72
    {
73
        my $arg = shift @ARGV;
74
        if ($arg eq "-h" || $arg eq "--help") {
75
            usage();
76
            exit(1);
77
        }
78
        elsif ($arg eq "-V") {
79
            $verbose = 1;
80
        }
81
        elsif ($arg =~ "^-j") {
82
            $jOption = $arg;
83
        }
84
        elsif ($arg eq "--export") {
85
            $makefileToExport = shift @ARGV;
86
        }
87
        elsif ($arg eq "--") {
88
            $arg = shift @ARGV;
89
            $simProg = $arg;
90
            push(@simProgArgs, @ARGV);
91
            last;  # end of options
92
        }
93
        elsif ($arg =~ /^-/) {
94
            error("unrecognized option $arg");
95
        }
96
        else {
97
            # process non-option args; first one is the simulation program, then its args
98
            $simProg = $arg;
99
            push(@simProgArgs, @ARGV);
100
            last;  # end of options
101
        }
102
    }
103

    
104
    if (!$simProg) {
105
        error("simulation program not specified");
106
    }
107

    
108
    # find -r option
109
    $runNumIndex = "";  # index of the argument of the -r option in the args list
110
    my $i = 0;
111
    foreach my $arg (@simProgArgs) {
112
        if ($arg eq "-r") {
113
            $runNumIndex = $i+1;
114
        }
115
        $i++;
116
    }
117
    if ($runNumIndex eq "") {
118
        error("-r option must be specified");
119
    }
120

    
121

    
122
    # expand run numbers to @runNumbers
123
    if ($runNumIndex eq "") {
124
        @runNumbers = 0;  # default run
125
    }
126
    else {
127
        @runNumbers = ();
128
        my $runSpec = $simProgArgs[$runNumIndex];
129
        foreach my $r (split(",", $runSpec)) {
130
            if ($r =~ /^\d+$/) {
131
                push(@runNumbers, $r);
132
            }
133
            elsif ($r =~ /^(\d+)(\.\.|-)(\d+)$/) {
134
                my $from = $1;
135
                my $to = $3;
136
                for (my $i=$from; $i<=$to; $i++) {
137
                    push(@runNumbers, $i);
138
                }
139
            }
140
            else {
141
                error("unrecognized run number spec: $r");
142
            }
143
        }
144
        print "-r $runSpec expands to: " . join(" ", @runNumbers) . "\n" if $verbose;
145
    }
146

    
147
    # generate makefile
148
    $banner  = "#\n";
149
    $banner .= "# This makefile was generated with the following command:\n";
150
    $banner .= "# $originalArgs\n";
151
    $banner .= "#\n";
152

    
153
    $targetList = "";
154
    $rules = "";
155
    $prefix = "r";
156
    foreach my $i (@runNumbers) {
157
        $targetList .= " $prefix$i";
158
        $rules .= "$prefix$i:\n";
159
        $simProgArgs[$runNumIndex] = $i if ($runNumIndex);
160
        $rules .= "\t$simProg " . join(" ", @simProgArgs) . "\n\n";
161
    }
162

    
163
    $content = "$banner\n" . ".PHONY: $targetList\n\n" . "all: $targetList\n\n" . $rules;
164

    
165
    if ($makefileToExport) {
166
        $filename = $makefileToExport;
167
    }
168
    else {
169
        # try new temporary filenames until we get one that didn't already exist
170
        # http://docstore.mik.ua/orelly/perl/cookbook/ch07_06.htm
171
        # see also END block below
172
        do { $tempfilename = tmpnam() }
173
            until IO::File->new($tempfilename, O_RDWR|O_CREAT|O_EXCL);
174
        $filename = $tempfilename;
175
    }
176

    
177
    open(OUT, ">$filename");
178
    print OUT $content;
179
    close OUT;
180

    
181
    print "$filename created\n" if $verbose;
182

    
183
    if (!$makefileToExport) {
184
        # invoke make
185
        $makeProg = $ENV{MAKE} ? $ENV{MAKE} : "make";
186
        $jOption = $jOption ? " $jOption" : "";
187
        $makeCommand = "$makeProg$jOption -f $filename";
188
        print "running $makeCommand...\n" if $verbose;
189
        runprog($makeCommand);
190
        print "done\n" if $verbose;
191
    }
192
}
193

    
194
# provide an END block so that when we exit or die, it automatically deletes
195
# the temporary file. Note: the END block ALWAYS gets invoked, even if control
196
# doesn't get here during the normal program flow!
197
END {
198
    if ($tempfilename) {
199
        print "deleting $tempfilename\n" if $verbose;
200
        unlink($tempfilename) or die "Couldn't unlink $tempfilename: $!"
201
    }
202
}
203

    
204
sub runprog
205
{
206
    my $cmd = shift;
207
    system($cmd);
208
}
209

    
210
sub error($)
211
{
212
    my($text) = @_;
213
    print STDERR "$ARG0: error: $text\n";
214
    exit(1);
215
}
216

    
217
sub warning($)
218
{
219
    my($text) = @_;
220
    print STDERR "$ARG0: warning: $text\n";
221
}
222