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