1 #!/usr/local/bin/perl -w |
|
2 # ============================================================================ |
|
3 # Name : buildIADsis.pl |
|
4 # Description: Creates SIS installation packages for S60 Browser that |
|
5 # meets Arrow/IAD program requirements for delivery to end-user devices. |
|
6 # Also generates R&D signed SIS packages for Nokia R&D internal use. |
|
7 # |
|
8 # Copyright © 2008 Nokia. All rights reserved. |
|
9 # This material, including documentation and any related computer |
|
10 # programs, is protected by copyright controlled by Nokia. All |
|
11 # rights are reserved. Copying, including reproducing, storing, |
|
12 # adapting or translating, any or all of this material requires the |
|
13 # prior written consent of Nokia. This material also contains |
|
14 # confidential information which may not be disclosed to others |
|
15 # without the prior written consent of Nokia. |
|
16 # ============================================================================ |
|
17 |
|
18 # TODOs |
|
19 # Baseline whatlog and build whatlog need to be processed and compared |
|
20 |
|
21 # Notes for maintainers: |
|
22 # Versioning guide: |
|
23 # http://s60wiki.nokia.com/S60Wiki/How_to_guide_for_versioning |
|
24 # Eclipsing ROM files using installers |
|
25 # http://s60wiki.nokia.com/S60Wiki/How_to_guide_for_eclipsing_ROM_files |
|
26 # Installers basics |
|
27 # http://s60wiki.nokia.com/S60Wiki/How_to_guide_for_creating/signing_sis_files |
|
28 # SIS file naming convention for IAD delivery |
|
29 # http://s60wiki.nokia.com/S60Wiki/How_to_guide_for_uploading_sis_packages_to_IAD_server |
|
30 |
|
31 use strict; |
|
32 use warnings; |
|
33 use Getopt::Long; |
|
34 use Data::Dumper; |
|
35 use File::Path; |
|
36 use Benchmark; |
|
37 |
|
38 my $usage = q{ |
|
39 Usage: buildIADsis.pl -opmode dev -appversion 7.1.2 -binversion 10.1 -variant 01 -nocache -verbose |
|
40 |
|
41 Mandatory arguments: |
|
42 -opmode : either dev or integration. If integration, use filelist argument below |
|
43 -appversion: Browser version as a string e.g 7.1.420 (major.minor.build). Minor must be 1 digit. |
|
44 -platform: S60 platform. E.g 3.23 or 5.0 |
|
45 -variant: S60 platform specific variant code. E.g for 3.23: 01->English, 22->Chinese etc. |
|
46 |
|
47 Optional arguments: |
|
48 -platform: S60 platform. Such as S60.323 or S60.50 |
|
49 -filelist: A text file containing list of files to include in the PKG |
|
50 File paths must be of the form \epoc32\dir\urel\file.ext |
|
51 -binversion: version to inject inside all EXEs and DLLs. Must be 10.0 or higher. |
|
52 -nocache: does everything cleanly, no old data used |
|
53 -verbose: Turns on debug statements |
|
54 -webkey: Web signing key filename |
|
55 -webcert: Web signing certificate filename |
|
56 -cenrepkey: Cenrep signing key filename |
|
57 -cenrepcert: Cenrep signing certificate filename |
|
58 |
|
59 For quick primer on differences between Application version and Binary version, see: |
|
60 http://s60wiki.nokia.com/S60Wiki/How_to_guide_for_versioning |
|
61 }; |
|
62 |
|
63 my ($s60platform, $rawFilelist,$appVersion, $binVersion, $variant,$opmode,$lang_code); |
|
64 my (@variants); |
|
65 my $langgroup; |
|
66 my $type = "rnd"; |
|
67 my $brExe_UID3 = "0x10008D39"; #Unique ID for Browser application |
|
68 my $packageTypeMajor = "RU"; # even though we use SA,RU, mention the RU in filename since it sounds more important |
|
69 #TODO: We should be able to query the S60 platform by parsing some file in epoc32. Dunno how to do this. This should NOT be hardcoded. |
|
70 # Inital value for s60Platform is S60.323 |
|
71 $s60platform = "S60.323"; |
|
72 my $cenrepPkg = ".\\pkg\\BrowserNG_Cenrep.pkg"; |
|
73 my $cenrepSis = "BrowserNG_Cenrep.sis"; |
|
74 my $finalBrowserPkg = ".\\pkg\\BrowserNG.pkg"; |
|
75 my $debug_printing = 1; |
|
76 my $nocache = 0; |
|
77 #TODO: We might want to pass this as a command-line argument? Note that unsigned SIS is also generated and can always |
|
78 # be signed separately. |
|
79 my $webkey = ".\\cert\\RDTest_02.key"; |
|
80 my $webcert = ".\\cert\\RDTest_02.der"; |
|
81 my $cenrepkey = ".\\cert\\RDTest_02.key"; |
|
82 my $cenrepcert = ".\\cert\\RDTest_02.der"; |
|
83 my $buildType = "urel"; |
|
84 |
|
85 my @cleanupList = (); |
|
86 |
|
87 GetOptions( |
|
88 "platform=s", \$s60platform, |
|
89 "appversion=s",\$appVersion, |
|
90 "binversion=s",\$binVersion, |
|
91 "variant=s",\$variant, |
|
92 "opmode=s",\$opmode, |
|
93 "nocache",\$nocache, |
|
94 "verbose",\$debug_printing, |
|
95 "filelist=s",\$rawFilelist, |
|
96 "webkey=s", \$webkey, |
|
97 "webcert=s", \$webcert, |
|
98 "cenrepkey=s", \$cenrepkey, |
|
99 "cenrepcert=s", \$cenrepcert, |
|
100 "build=s", \$buildType |
|
101 ); |
|
102 |
|
103 |
|
104 #### START OF ARG CHECKS |
|
105 if ( !defined $appVersion ) { print STDERR "\nBad argument: missing appversion\n $usage"; exit; } |
|
106 # Parse major.minor.build format string and choke if not well formed |
|
107 # We will later insert the parsed values inside the PKG file. |
|
108 my @parsedAppVer = checkAppVersion($appVersion); |
|
109 if (!$parsedAppVer[3]) { print STDERR "\nBad argument: malformed appversion string ($appVersion) \n $usage"; exit; } |
|
110 |
|
111 #By default ROM EXEs/DLLs have a version of 10.0, so you want the newDLLs to have equal or higher minor version. See IAD Eclipsing guide for details |
|
112 if ( !defined $binVersion ) { print STDOUT "\n Missing binary version, using default\n"; $binVersion = "10.1"; } |
|
113 my @parsedBinVer = checkBinaryVersion($binVersion); |
|
114 if (!$parsedBinVer[2]) { print STDERR "\nBad argument or default: malformed binversion string ($binVersion). \n $usage"; exit; } |
|
115 |
|
116 if ( !defined $variant ) { print STDERR "\nBad argument: missing variant\n $usage"; exit; } |
|
117 |
|
118 if ( !defined $opmode || !($opmode =~ /^dev/ || $opmode =~ /^int/)) { print STDERR "\nBad argument: Can't grok opmode\n $usage"; exit; } |
|
119 |
|
120 if (defined $rawFilelist && (! -e $rawFilelist) ) { print STDERR "\nBad argument: File is missing: $rawFilelist\n $usage"; exit; } |
|
121 |
|
122 print "no cache flag = $nocache \n" if $debug_printing; |
|
123 #print "verbose = $debug_printing \n"; |
|
124 #### END OF ARG CHECKS |
|
125 |
|
126 # IAD-compliant SIS file naming convention |
|
127 # ComponentName_<package UID>_v<package version>_<package type>_<platform>_<variant>.sis |
|
128 # Example: TestApplication_0x12345678_v1.2.3_SA_S60.32_Euro1.sis |
|
129 # Reference: http://s60wiki.nokia.com/S60Wiki/How_to_guide_for_uploading_sis_packages_to_IAD_server |
|
130 # Where: |
|
131 #package version: major.minor.build |
|
132 #package type: SIS package type (SA, SP,..) |
|
133 #platform: S60 Platform (S60.xx where xx = 32, 50,..) |
|
134 #variant: Language/operator variant |
|
135 |
|
136 my $browserSIS = "BrowserNG_${brExe_UID3}_v${appVersion}_${packageTypeMajor}_${s60platform}_${variant}.sis"; |
|
137 # For 323 we limit the number of IAD to Chinese, Western and Japan |
|
138 if ( $s60platform eq "S60.323" ) |
|
139 { |
|
140 if ( $variant == 50 ) { |
|
141 $browserSIS = "BrowserNG_${brExe_UID3}_v${appVersion}_${packageTypeMajor}_${s60platform}_western.sis"; |
|
142 } |
|
143 elsif ( $variant == 51 ) { |
|
144 $browserSIS = "BrowserNG_${brExe_UID3}_v${appVersion}_${packageTypeMajor}_${s60platform}_china.sis"; |
|
145 } |
|
146 elsif ( $variant == 16 ) { |
|
147 $browserSIS = "BrowserNG_${brExe_UID3}_v${appVersion}_${packageTypeMajor}_${s60platform}_japan.sis"; |
|
148 } |
|
149 else { |
|
150 print STDOUT "\n build variant $variant for RnD purpose \n"; |
|
151 } |
|
152 print STDOUT "\n=== SIS filename: $browserSIS \n" ; |
|
153 } |
|
154 # Handle S60.50 situations |
|
155 if ( $s60platform eq "S60.50" ) |
|
156 { |
|
157 # May need special handling later |
|
158 } |
|
159 |
|
160 ### Call pkg generation perl script |
|
161 system("CreateIADpackages.pl -s $s60platform -v $variant -p armv5 -r urel -bmajor $parsedAppVer[0] -bminor $parsedAppVer[1] -bnumber $parsedAppVer[2] -build $buildType"); |
|
162 |
|
163 # Pick up any files from the WHAT output that match any of these regex patterns |
|
164 my $filenameRegEx = join '|', qw( |
|
165 [.]dll$ |
|
166 [.]exe$ |
|
167 [.]mif$ |
|
168 [.]r..$); |
|
169 |
|
170 # These type of files need to be stamped with a version number >= 10.0 so that the |
|
171 # original files on ROM may be eclipsed. |
|
172 my $binariesRegEx = join '|', qw( |
|
173 [.]dll$ |
|
174 [.]exe$); |
|
175 |
|
176 |
|
177 |
|
178 |
|
179 |
|
180 |
|
181 # In any mode, use a $rawFilelist is passed from the command line |
|
182 if (defined $rawFilelist) { |
|
183 print STDOUT "\n=== Caller supplied list of files: $rawFilelist === \n" ; |
|
184 } else { |
|
185 # If no file list passed from command-line, we know how to generate one in DEV mode only |
|
186 if ($opmode =~ /^dev/) { |
|
187 $rawFilelist = "what_$buildType.log"; |
|
188 if ($nocache || (! -e $rawFilelist) ) { |
|
189 print STDOUT "\n=== Generating WHAT log, may take a while.. [",scalar(localtime),"] ===\n"; |
|
190 makeWhatLog($buildType, $rawFilelist); |
|
191 print STDOUT "\n=== Finished generating WHAT log ",scalar(localtime)," ===\n"; |
|
192 } else { |
|
193 print STDOUT "\n=== Will use cached WHAT log : $rawFilelist ===\n"; |
|
194 } |
|
195 } else { |
|
196 die("\nBad argument: File is missing: $rawFilelist\n $usage"); |
|
197 } |
|
198 |
|
199 } |
|
200 |
|
201 #Reduce list of files to those of interest |
|
202 my @rawList = getRawFileList($rawFilelist); |
|
203 my @filteredFiles = grep(/$filenameRegEx/i, @rawList); |
|
204 #print Dumper(@filteredFiles) if $debug_printing; |
|
205 |
|
206 print "Changing binary files with version\n" if $debug_printing; |
|
207 my @binariesOnly = grep(/$binariesRegEx/i, @filteredFiles); |
|
208 # print Dumper(@binariesOnly) if $debug_printing; |
|
209 for my $binaryFile (@binariesOnly) { |
|
210 print STDOUT "Fixing version to $binVersion for file: $binaryFile..\n" if $debug_printing; |
|
211 changeBinaryVersionAndMore("elftran", $binaryFile, $binVersion); |
|
212 if ( $? == -1 || ($? >> 8) != 0 ) { cleanDeath("Elftran failed to modify : $binaryFile "); } |
|
213 } |
|
214 |
|
215 |
|
216 print STDOUT "Creating CenRep installer\n" if $debug_printing; |
|
217 # No need to cleanup the sis file since it might be certificated differently |
|
218 # push(@cleanupList, "$cenrepSis"); |
|
219 system("makesis $cenrepPkg $cenrepSis"); |
|
220 if ( $? == -1 || ($? >> 8) != 0 ) { cleanDeath("Makesis on CenRep installer failed"); } else { |
|
221 #printf "\nOK %d\n", $? >> 8; |
|
222 } |
|
223 push(@cleanupList, "${cenrepSis}x"); |
|
224 print STDOUT "\nSigning CenRep installer\n" if $debug_printing; |
|
225 system("signsis -v $cenrepSis ${cenrepSis}x $cenrepcert $cenrepkey"); |
|
226 if ( $? == -1 || ($? >> 8) != 0 ) { cleanDeath("Signsis on CenRep installer failed"); } else { |
|
227 #printf "\nOK %d\n", $? >> 8; |
|
228 } |
|
229 |
|
230 print STDOUT "Creating main Browser installer with filename: $browserSIS\n" if $debug_printing; |
|
231 system("makesis $finalBrowserPkg $browserSIS"); |
|
232 if ( $? == -1 || ($? >> 8) != 0 ) { cleanDeath("Makesis on main Browser installer failed"); } else { |
|
233 #printf "\nOK %d\n", $? >> 8; |
|
234 } |
|
235 |
|
236 print STDOUT "\nSigning main Browser installer\n" if $debug_printing; |
|
237 system("signsis $browserSIS ${browserSIS}x $webcert $webkey"); |
|
238 if ( $? == -1 || ($? >> 8) != 0 ) { cleanDeath("Signsis on main Browser installer failed"); } else { |
|
239 #printf "OK %d\n", $? >> 8; |
|
240 } |
|
241 |
|
242 #cleanup all transient files |
|
243 cleanup(); |
|
244 |
|
245 |
|
246 # Helps us generate list of DLLs EXEs and resource files to be packaged in SIS package |
|
247 sub makeWhatLog |
|
248 { |
|
249 my $buildType = shift; |
|
250 my $file_whatLog = shift; |
|
251 |
|
252 system("\\gb_cmds\\gb_aurora_32_what.cmd armv5 $buildType > $file_whatLog"); |
|
253 } |
|
254 |
|
255 # Returns an in-memory list of all binary and resource files that the build process generates (WHAT output) |
|
256 sub getRawFileList |
|
257 { |
|
258 my $filename = shift; |
|
259 my @array = 0; |
|
260 #print "\n == Loading file with list of all assets : $filename == \n" if $debug_printing; |
|
261 open(HANDLE, $filename) || cleanDeath("Failed to open WHAT command output: $filename\n"); |
|
262 @array=<HANDLE>; |
|
263 close (HANDLE); |
|
264 #print Dumper(@rawList) if $debug_printing; |
|
265 |
|
266 return @array; |
|
267 } |
|
268 |
|
269 # |
|
270 sub changeBinaryVersionAndMore |
|
271 { |
|
272 my $elfCmd = shift; |
|
273 my $file = shift; |
|
274 my $binaryVersion = shift; |
|
275 |
|
276 system("$elfCmd -version $binaryVersion -compressionmethod bytepair $file"); |
|
277 } |
|
278 # Dies after doing cleanup |
|
279 sub cleanDeath { |
|
280 my $reason = shift; |
|
281 cleanup(); |
|
282 die($reason); |
|
283 } |
|
284 |
|
285 # Removes unwanted files from disk |
|
286 sub cleanup { |
|
287 for my $file (@cleanupList) { |
|
288 print "Cleaning up: $file\n"; |
|
289 unlink($file); |
|
290 } |
|
291 } |
|
292 |
|
293 # Checks for a well formed Binary Version string in major.minor format and that it is >= 10.0 |
|
294 # 10.0 is the default version of in-ROM binaries that must be eclipsed by our installation. |
|
295 sub checkBinaryVersion { |
|
296 my ($ver) = shift; |
|
297 |
|
298 my ($valid, $major, $minor) = (0, 0, 0); |
|
299 if ($ver =~ /^(\d+)\.(\d+)$/) { |
|
300 $valid = 1; |
|
301 ($major, $minor) = ($1, $2); |
|
302 # {=leading-zeros-ignored} |
|
303 $major =~ s/^0+//; |
|
304 $minor =~ s/^0+//; |
|
305 |
|
306 } |
|
307 |
|
308 my $intMajor = int($major || 0); |
|
309 my $intMinor = int($minor || 0); |
|
310 |
|
311 $valid = 0; |
|
312 if ( $intMajor >= 10 && $intMinor >=0 ) { |
|
313 $valid = 1; # enforce 10.0 or higher rule for IAD |
|
314 } |
|
315 |
|
316 my @binVerArray = ( |
|
317 $intMajor, |
|
318 $intMinor, |
|
319 $valid |
|
320 ); |
|
321 |
|
322 #print Dumper(@binVerArray) if $debug_printing; |
|
323 return @binVerArray; |
|
324 } |
|
325 |
|
326 # Checks for a well formed Application Version string in major.minor.build format |
|
327 # See the IAD versioning HOWTO (link above) for acceptable format |
|
328 sub checkAppVersion { |
|
329 my ($ver) = shift; |
|
330 |
|
331 my ($valid, $major, $minor, $build) = (0, 0, 0, 0); |
|
332 if ($ver =~ /^(\d+)\.(\d+).(\d+)$/) { |
|
333 $valid = 1; |
|
334 ($major, $minor, $build) = ($1, $2, $3); |
|
335 # {=leading-zeros-ignored} |
|
336 $major =~ s/^0+//; |
|
337 $minor =~ s/^0+//; |
|
338 $build =~ s/^0+//; |
|
339 } |
|
340 |
|
341 my $intMajor = int($major || 0); |
|
342 my $intMinor = int($minor || 0); |
|
343 my $intBuild = int($build || 0); |
|
344 |
|
345 if ($intMinor < 0 || $intMinor > 9) { |
|
346 $valid = 0; # enforce single digit minor rule for IAD |
|
347 } |
|
348 |
|
349 my @appVerArray = ( |
|
350 $intMajor, |
|
351 $intMinor, |
|
352 $intBuild, |
|
353 $valid |
|
354 ); |
|
355 #print Dumper(@appVerArray) if $debug_printing; |
|
356 return @appVerArray; |
|
357 } |
|
358 |
|