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