|
1 # Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 # All rights reserved. |
|
3 # This component and the accompanying materials are made available |
|
4 # under the terms of "Eclipse Public License v1.0" |
|
5 # which accompanies this distribution, and is available |
|
6 # at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 # |
|
8 # Initial Contributors: |
|
9 # Nokia Corporation - initial contribution. |
|
10 # |
|
11 # Contributors: |
|
12 # |
|
13 # Description: |
|
14 # all variables called *Path* are set up to end with a backslash |
|
15 # all variables called *Path or *File are stored as absolute (file)paths within makmake |
|
16 # all variables called UpPath* are stored as relative paths within makmake |
|
17 # |
|
18 # |
|
19 |
|
20 |
|
21 use FindBin; # for FindBin::Bin |
|
22 use File::Find; |
|
23 use Cwd; |
|
24 |
|
25 my $PerlLibPath; # fully qualified pathname of the directory containing our Perl modules |
|
26 |
|
27 BEGIN { |
|
28 # check user has a version of perl that will cope |
|
29 require 5.005_03; |
|
30 # establish the path to the Perl libraries: currently the same directory as this script |
|
31 $PerlLibPath = $FindBin::Bin; # X:/epoc32/tools |
|
32 $PerlLibPath =~ s/\//\\/g; # X:\epoc32\tools |
|
33 $PerlLibPath .= "\\"; |
|
34 } |
|
35 |
|
36 use lib $PerlLibPath; |
|
37 use E32env; |
|
38 use Prepfile; |
|
39 use Pathutl; |
|
40 |
|
41 # autoflush prevents our ouptut from getting jumbled up |
|
42 use FileHandle; |
|
43 autoflush STDOUT 1; |
|
44 autoflush STDERR 1; |
|
45 |
|
46 my (@Commands, @BldInfDirs); |
|
47 # should end in .mbc where .mbc means for "MetaBld Configuration file" |
|
48 # must end in .mbc if passed on command-line |
|
49 my $ConfigFile; |
|
50 |
|
51 my $StartDir=&cwd(); |
|
52 my $relative; |
|
53 { |
|
54 # Process command-line |
|
55 |
|
56 unless (@ARGV) |
|
57 { |
|
58 &Usage(); |
|
59 } |
|
60 else |
|
61 { |
|
62 # check to see if we are using a relative path |
|
63 if ($ARGV[0] eq "-r") |
|
64 { |
|
65 $relative = 1; |
|
66 shift @ARGV; |
|
67 } |
|
68 |
|
69 # check for a root from a config file in EPOCROOT dir as first argument |
|
70 if (-e "$ENV{EPOCROOT}$ARGV[0].mbc") |
|
71 { |
|
72 $ConfigFile="$ENV{EPOCROOT}$ARGV[0].mbc"; |
|
73 shift @ARGV; |
|
74 } |
|
75 # check for a config file as the first argument |
|
76 elsif ($ARGV[0]=~/.mbc$/io) |
|
77 { |
|
78 $ConfigFile=shift @ARGV; |
|
79 if ($ConfigFile=~/^.:/o) |
|
80 { |
|
81 &Error("Config file can't be specified with a drive letter, as \"$ConfigFile\" is"); |
|
82 } |
|
83 unless (-e $ConfigFile) |
|
84 { |
|
85 &Error("Can't find file $ConfigFile"); |
|
86 } |
|
87 } |
|
88 if (@ARGV) |
|
89 { |
|
90 # pass any other arguments as commands |
|
91 @Commands=("@ARGV"); |
|
92 } |
|
93 } |
|
94 } |
|
95 |
|
96 { |
|
97 # scan config file if necessary |
|
98 |
|
99 if ($ConfigFile) |
|
100 { |
|
101 # make config file path absolute |
|
102 $ConfigFile=&Path_AbsToWork($ConfigFile); |
|
103 |
|
104 my @Config2D; |
|
105 eval { &Prepfile_ProcessL(\@Config2D, $ConfigFile); }; |
|
106 &Error($@) if $@; |
|
107 |
|
108 my %CheckDir; |
|
109 |
|
110 my @ConfigCommands; |
|
111 my $Section=''; |
|
112 my @Death; |
|
113 my $Line; |
|
114 my $CurFile=$ConfigFile; |
|
115 LINE: foreach $Line (@Config2D) |
|
116 { |
|
117 my $LineNum=shift @$Line; |
|
118 $_=shift @$Line; |
|
119 if ($LineNum eq '#') |
|
120 { |
|
121 $CurFile=$_; |
|
122 next; |
|
123 } |
|
124 if (/^SECTION_(\w*)$/io) |
|
125 { |
|
126 $Section=uc $1; |
|
127 if ($Section=~/^(COMMANDS|DIRS|OPTIONALDIRS)$/o) |
|
128 { |
|
129 if (@$Line) |
|
130 { |
|
131 push @Death, "$CurFile($LineNum) : Can't specify anything on the same line as a section header\n"; |
|
132 } |
|
133 next LINE; |
|
134 } |
|
135 push @Death, "$CurFile($LineNum) : Unknown section header - $_\n"; |
|
136 $Section=0; |
|
137 next LINE; |
|
138 } |
|
139 unshift @$Line, $_; |
|
140 if ($Section eq 'COMMANDS') |
|
141 { |
|
142 if ($$Line[0]=~/^ONEOFF$/io) |
|
143 { |
|
144 # check syntax for oneoff commands |
|
145 unless (@$Line>=3) |
|
146 { |
|
147 push @Death, "$CurFile($LineNum) : Too few arguments for oneoff command\n"; |
|
148 } |
|
149 # resolve oneoff dir relative to .mb file location |
|
150 $$Line[1]=~s-^.*[^\\]$-$&\\-o; # add trailing backslash if necessary |
|
151 $$Line[1]=&Path_MakeAbs($CurFile, $$Line[1]); |
|
152 unless (-d $$Line[1]) |
|
153 { |
|
154 warn "$CurFile($LineNum) : Can't find dir $$Line[1]\n"; |
|
155 } |
|
156 } |
|
157 push @ConfigCommands, "@$Line"; |
|
158 next LINE; |
|
159 } |
|
160 if ($Section eq 'DIRS' || $Section eq 'OPTIONALDIRS') |
|
161 { |
|
162 my $Dir; |
|
163 foreach $Dir (@$Line) |
|
164 { |
|
165 if ($Dir=~/^.:/o) |
|
166 { |
|
167 push @Death, "$CurFile($LineNum) : directory $Dir is specified with a drive letter\n"; |
|
168 next; |
|
169 } |
|
170 $Dir=~s-^.*[^\\]$-$&\\-o; |
|
171 $Dir=&Path_MakeAbs($CurFile, $Dir); # dirs must be the same for check |
|
172 if ($CheckDir{uc $Dir}) |
|
173 { |
|
174 # Silently ignore duplicate directories - #including of several .mbc files |
|
175 # will often cause directory duplication. |
|
176 # We can't do the same for duplicate commands because the order in which |
|
177 # the commands are executed might be significant. |
|
178 # push @Death, "$CurFile($LineNum) : Directory $Dir already specified\n"; |
|
179 next; |
|
180 } |
|
181 print "$Dir\n"; |
|
182 |
|
183 unless (-d $Dir) |
|
184 { |
|
185 if ($Section ne 'OPTIONALDIRS') |
|
186 { |
|
187 push @Death, "$CurFile($LineNum) : Can't find directory $Dir\n"; |
|
188 } |
|
189 next; |
|
190 } |
|
191 push @BldInfDirs, $Dir; |
|
192 $CheckDir{uc $Dir}=$LineNum; |
|
193 } |
|
194 next LINE; |
|
195 } |
|
196 else |
|
197 { |
|
198 push @Death, "$CurFile($LineNum) : No section specified\n"; |
|
199 } |
|
200 } |
|
201 |
|
202 if (@Death) |
|
203 { |
|
204 chomp $Death[$#Death]; |
|
205 &Error(@Death); |
|
206 } |
|
207 |
|
208 # apply the commands unless already collected |
|
209 unless (@Commands) |
|
210 { |
|
211 &Error("$ConfigFile : No Commands specified") unless @ConfigCommands; |
|
212 @Commands=@ConfigCommands; |
|
213 } |
|
214 } |
|
215 |
|
216 # Should have commands now |
|
217 &Usage() unless @Commands; |
|
218 } |
|
219 |
|
220 { |
|
221 # Search for the BLD.INF files if necessary |
|
222 |
|
223 my $mystartdir; |
|
224 if ($relative) |
|
225 { |
|
226 $mystartdir = substr($StartDir, 2); |
|
227 } |
|
228 |
|
229 $mystartdir=~s:\/:\\:g; |
|
230 |
|
231 if ($mystartdir ne "\\") |
|
232 { |
|
233 $mystartdir=$mystartdir."\\"; |
|
234 } |
|
235 |
|
236 unless (@BldInfDirs) |
|
237 { |
|
238 # find the files in the source directories - skip the EPOCROOT directory |
|
239 |
|
240 my $EPOCROOTDir=$E32env::Data{EPOCPath}; |
|
241 $EPOCROOTDir=~s/^\\([^\\]*).*$/$1/o; |
|
242 |
|
243 opendir DIR, $mystartdir or &Error("Can't open dir: $!"); |
|
244 # remove ., .. and EPOCROOT dir |
|
245 my @SrcDirs=grep !/^(\.\.?|$EPOCROOTDir|RECYCLER|System Volume Information)$/i, readdir DIR; |
|
246 foreach (@SrcDirs) |
|
247 { |
|
248 # prepend with current path |
|
249 $_=$mystartdir.$_; |
|
250 } |
|
251 @SrcDirs=grep -d, @SrcDirs; |
|
252 find(\&BldInfDirs, @SrcDirs); |
|
253 @BldInfDirs=sort @BldInfDirs; |
|
254 |
|
255 # if we are doing it relative to current location, need to include current dir |
|
256 # if it contains a bld.inf |
|
257 if (-f "BLD.INF" && $relative) |
|
258 { |
|
259 push @BldInfDirs, $mystartdir; |
|
260 } |
|
261 |
|
262 } |
|
263 } |
|
264 |
|
265 { |
|
266 # Execute the commands |
|
267 |
|
268 my $Time=localtime; |
|
269 print "=== metabld started $Time.\n"; |
|
270 my $Command; |
|
271 foreach $Command (@Commands) |
|
272 { |
|
273 |
|
274 $Time=localtime; |
|
275 # Check if we should execute this command just the once |
|
276 if ($Command=~s/^\s*ONEOFF\s+(\S+)\s+(.*)$/$2/io) |
|
277 { |
|
278 my $OneOffDir=$1; |
|
279 # execute the command once rather than for each BLD.INF directory |
|
280 chdir $OneOffDir or &Error("Can't change dir to $OneOffDir: $!"); |
|
281 print |
|
282 ( |
|
283 "===-------------------------------------------------\n", |
|
284 "=== $Command\n", |
|
285 "===-------------------------------------------------\n", |
|
286 "=== $Command started $Time.\n", |
|
287 "=== $Command == $OneOffDir\n" |
|
288 ); |
|
289 system( "$Command"); |
|
290 } |
|
291 else |
|
292 { |
|
293 # execute the command for each BLD.INF directory |
|
294 print |
|
295 ( |
|
296 "===-------------------------------------------------\n", |
|
297 "=== $Command\n", |
|
298 "===-------------------------------------------------\n", |
|
299 "=== $Command started $Time.\n", |
|
300 ); |
|
301 my $Dir; |
|
302 foreach $Dir (@BldInfDirs) |
|
303 { |
|
304 chdir $Dir or &Error("Can't change dir to $Dir: $!"); |
|
305 print "=== $Command == $Dir\n"; |
|
306 system( "$Command"); |
|
307 } |
|
308 } |
|
309 chdir $StartDir or &Error("Can't change dir to $StartDir: $!"); |
|
310 $Time=localtime; |
|
311 print "=== $Command finished $Time.\n"; |
|
312 } |
|
313 } |
|
314 |
|
315 |
|
316 ################################################# |
|
317 # SUBROUTINES |
|
318 ################################################# |
|
319 |
|
320 sub Usage |
|
321 { |
|
322 print <<ENDHERESTRING; |
|
323 usage: metabld [EPOCROOT .mbc file basename|.mbc config file] [command] |
|
324 MetaBld is a tool for carrying out build commands across several components. |
|
325 A .mbc config file contains directories and commands, eg: |
|
326 |
|
327 SECTION_COMMANDS |
|
328 bldmake bldfiles |
|
329 abld target wins udeb |
|
330 // "oneoff" means carry out command just once, not for each directory. |
|
331 // First arg after "oneoff" must be a start dir, and can be "." |
|
332 oneoff \\e32\\rombuild rom xxx |
|
333 oneoff . \\e32test\\group\\abld test build wins urel |
|
334 SECTION_DIRS |
|
335 \\e32 |
|
336 \\f32\\group |
|
337 |
|
338 It's possible to #include lists of dirs from other files if necessary, |
|
339 and may be useful for carrying out different sets of commands on the same set |
|
340 of directories via different .mbc files. |
|
341 If a command is specified on the command-line, it will be executed instead |
|
342 of any commands specified in a .mbc file. |
|
343 If no directories are specified in a .mbc file, then all the directories |
|
344 containing a bld.inf file on the current drive will be searched for instead. |
|
345 ENDHERESTRING |
|
346 exit 1; |
|
347 } |
|
348 |
|
349 sub Error (@) |
|
350 { |
|
351 |
|
352 die |
|
353 @_, "\n", |
|
354 "Error executing metabld.bat\n" |
|
355 ; |
|
356 } |
|
357 |
|
358 sub BldInfDirs |
|
359 { |
|
360 s-\/-\\-go; |
|
361 if (/^BLD.INF$/io) |
|
362 { |
|
363 $File::Find::dir=~s-\/-\\-go; |
|
364 push @BldInfDirs, $File::Find::dir; |
|
365 } |
|
366 } |
|
367 |