bin/cross-run.in: Pass `-k', `-n' and `-s' flags through to `make'.
[mdw-cross] / src / cross-run.in
CommitLineData
6cb0a33a
MW
1#! /usr/bin/perl
2
3use Data::Dumper;
4
5use File::FnMatch qw(fnmatch);
6use MdwOpt;
7
8our $CROSSDIR = "@crossdir@";
9(our $ME = $0) =~ s:^.*/::;
10
11###--------------------------------------------------------------------------
12### Utilities.
13
14sub usage (*) {
15 my ($fh) = @_;
16 print $fh
17 "usage: $ME [-j N] =ARCHGLOB|:FLAVOUR ... [--] CMD [ARGS ...]\n";
18}
19sub barf ($) {
20 my ($msg) = @_;
21 print STDERR "$0: $msg\n";
22 exit 2;
23}
24
25###--------------------------------------------------------------------------
26### Read and prepare the configuration.
27
28our %C = ();
29open my $fh, "<", "$CROSSDIR/etc/config.sh" or barf "open config: $!";
30while (<$fh>) {
31 chomp;
32 if (/^\s*(#|$)/) { next; }
33 if (!/^([^=]+)='(.*)'$/) { barf "bad config line `$_'"; }
34 my ($k, $v) = ($1, $2);
35 $v =~ s/'\\''/'/g;
36 $C{$k} = $v;
37}
38
39our @ALLARCH;
40our %FLAVOUR;
41for my $f (split ' ', $C{"FLAVOURS"}) {
42 (my $v = $f) =~ tr/-/_/;
43 my @a = split ' ', $C{"${v}_ARCHS"};
44 @{$FLAVOUR{$f}} = @a;
45 push @ALLARCH, @a;
46}
47
48###--------------------------------------------------------------------------
49### Parse the command line.
50
51our @ARCH = ();
52our $JOBS = undef;
c65bb1c1
MW
53our $KEEPGOING = 0;
54our $SILENT = 0;
55our $DRYRUN = 0;
6cb0a33a
MW
56our $DIR = ".";
57our $MARKER = "{}";
58our @CMD = ();
59
c65bb1c1 60my $mo = new MdwOpt "hC:j:km:ns",
6cb0a33a
MW
61 { "help" => { 'return' => "h" },
62 "directory" => { 'return' => 'C', 'arg' => 'req' },
63 "jobs" => { 'return' => "j", 'arg' => 'req' },
c65bb1c1
MW
64 "keep-going" => { 'return' => "k" },
65 "marker" => { 'return' => "m", 'arg' => 'req' },
66 "dry-run" => { 'return' => "n" },
67 "silent" => { 'return' => "s" } },
6cb0a33a
MW
68 \@ARGV,
69 ['inorder'];
70my $bad = 0;
71OPT: for (;;) {
72 my ($opt, $arg) = $mo->read;
73 last OPT unless defined $opt;
74 if ($opt eq "h") { usage STDOUT; exit 0; }
75 elsif ($opt eq "C") { $DIR = $arg; }
76 elsif ($opt eq "j")
77 { $arg =~ /^[+]?\d+$/ or barf "bad integer `$arg'"; $JOBS = $arg; }
c65bb1c1 78 elsif ($opt eq "k") { $KEEPGOING = 1; }
6cb0a33a 79 elsif ($opt eq "m") { $MARKER = $arg; }
c65bb1c1
MW
80 elsif ($opt eq "n") { $DRYRUN = $arg; }
81 elsif ($opt eq "s") { $SILENT = $arg; }
6cb0a33a
MW
82 elsif ($opt eq '') {
83 if ($arg =~ /^=(.*)$/) {
84 my $pat = $1;
85 my $match = 0;
86 ARCH: for my $a (@ALLARCH) {
87 next ARCH unless fnmatch $pat, $a;
88 $match = 1; push @ARCH, $a;
89 }
90 $match or barf "no architectures match `$pat'";
91 } elsif ($arg =~ /^:(.*)$/) {
92 my $f = $1;
93 exists $FLAVOUR{$f} or barf "no architeture flavour `$f'";
94 push @ARCH, @{%FLAVOUR{$f}};
95 } else {
96 push @CMD, $arg;
97 last OPT;
98 }
99 } else {
100 $bad = 1;
101 }
102}
103$bad = 1 unless @ARCH && @CMD;
104push @CMD, $mo->rest, @{$mo->{argv}};
105if ($bad) { usage STDERR; exit 2; }
106
107###--------------------------------------------------------------------------
108### Hack the arguments and run `make'.
109
110sub hack ($) {
111 my ($x) = @_;
112 $x =~ s/'/'\\''/g;
113 $x =~ s/\$/\$\$/g;
114 $x =~ s/\Q$MARKER/\$*/g;
115 return "'$x'";
116}
117
118our $TARGET = "run";
119if ($CMD[0] eq 'make') { $TARGET = "run-make"; shift @CMD; }
120our @MAKE = ("make");
121push @MAKE, "-f$CROSSDIR/Makefile";
122push @MAKE, "-j$JOBS" if defined $JOBS;
c65bb1c1
MW
123push @MAKE, "-k" if $KEEPGOING;
124push @MAKE, "-n" if $DRYRUN;
125push @MAKE, "-s" if $SILENT;
6cb0a33a
MW
126push @MAKE, $TARGET;
127push @MAKE, "ARCHS=" . join " ", @ARCH;
128push @MAKE, "ARGS=" . join " ", map { hack $_ } @CMD;
129push @MAKE, "CROSSDIR=$CROSSDIR";
130push @MAKE, "DIR=" . hack $DIR;
131exec @MAKE;
132barf "make: $!";
133
134###----- That's all, folks --------------------------------------------------