source: trunk/bin/createpackage.pl@ 1106

Last change on this file since 1106 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 15.2 KB
Line 
1#!/usr/bin/perl
2#############################################################################
3##
4## Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
5## All rights reserved.
6## Contact: Nokia Corporation ([email protected])
7##
8## This file is part of the S60 port of the Qt Toolkit.
9##
10## $QT_BEGIN_LICENSE:LGPL$
11## Commercial Usage
12## Licensees holding valid Qt Commercial licenses may use this file in
13## accordance with the Qt Commercial License Agreement provided with the
14## Software or, alternatively, in accordance with the terms contained in
15## a written agreement between you and Nokia.
16##
17## GNU Lesser General Public License Usage
18## Alternatively, this file may be used under the terms of the GNU Lesser
19## General Public License version 2.1 as published by the Free Software
20## Foundation and appearing in the file LICENSE.LGPL included in the
21## packaging of this file. Please review the following information to
22## ensure the GNU Lesser General Public License version 2.1 requirements
23## will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24##
25## In addition, as a special exception, Nokia gives you certain additional
26## rights. These rights are described in the Nokia Qt LGPL Exception
27## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28##
29## GNU General Public License Usage
30## Alternatively, this file may be used under the terms of the GNU
31## General Public License version 3.0 as published by the Free Software
32## Foundation and appearing in the file LICENSE.GPL included in the
33## packaging of this file. Please review the following information to
34## ensure the GNU General Public License version 3.0 requirements will be
35## met: http://www.gnu.org/copyleft/gpl.html.
36##
37## If you have questions regarding the use of this file, please contact
38## Nokia at [email protected].
39## $QT_END_LICENSE$
40##
41#############################################################################
42
43############################################################################################
44#
45# Convenience script for creating signed packages you can install on your phone.
46#
47############################################################################################
48
49use strict;
50
51# use a command-line parsing module
52use Getopt::Long;
53# Use file name parsing module
54use File::Basename;
55# Use File::Spec services mainly rel2abs
56use File::Spec;
57# Use File::Path - to make stub sis target directory
58use File::Path;
59# use CWD abs_bath, which is exported only on request
60use Cwd 'abs_path';
61
62
63sub Usage() {
64 print <<ENDUSAGESTRING;
65
66==============================================================================================
67Convenience script for creating signed packages you can install on your phone.
68
69Usage: createpackage.pl [options] templatepkg [target]-[platform] [certificate key [passphrase]]
70
71Where supported options are as follows:
72 [-i|install] = Install the package right away using PC suite.
73 [-p|preprocess] = Only preprocess the template .pkg file.
74 [-c|certfile <file>] = The file containing certificate information for signing.
75 The file can have several certificates, each specified in
76 separate line. The certificate, key and passphrase in line
77 must be ';' separated. Lines starting with '#' are treated
78 as a comments. Also empty lines are ignored. The paths in
79 <file> can be absolute or relative to <file>.
80 [-u|unsigned] = Preserves the unsigned package.
81 [-o|only-unsigned] = Creates only unsigned package.
82 [-s|stub] = Generates stub sis for ROM.
83 [-n|sisname <name>] = Specifies the final sis name.
84 [-g|gcce-is-armv5] = Convert gcce platform to armv5.
85 [-d|dont-patch] = Skip automatic patching of capabilities and pkg file if default certificate
86 is used. Instead non-self-signable capabilities just cause warnings.
87Where parameters are as follows:
88 templatepkg = Name of .pkg file template
89 target = Either debug or release
90 platform = One of the supported platform
91 winscw | gcce | armv5 | armv6 | armv7
92 Note that when packaging binaries built using gcce and symbian-sbsv2
93 mkspec, armv5 must be used for platform instead of gcce.
94 certificate = The certificate file used for signing
95 key = The certificate's private key file
96 passphrase = The passphrase of the certificate's private key file
97
98Example:
99 createpackage.pl fluidlauncher_template.pkg release-armv5
100
101Example with certfile:
102 createpackage.pl -c=mycerts.txt fluidlauncher_template.pkg release-armv5
103
104 Content of 'mycerts.txt' must be something like this:
105 # This is comment line, also the empty lines are ignored
106 rd.cer;rd-key.pem
107 .\\cert\\mycert.cer;.\\cert\\mykey.key;yourpassword
108 X:\\QtS60\\s60installs\\selfsigned.cer;X:\\QtS60\\s60installs\\selfsigned.key
109
110If no certificate and key files are provided, either a RnD certificate or
111a self-signed certificate from QtDir\\src\\s60installs directory is used.
112In the latter case the resulting package will also be automatically patched
113using patch_capabilities.pl script, which makes it unsuitable for distribution.
114Always specify certificates explicitly if you wish to distribute your package.
115
116==============================================================================================
117
118ENDUSAGESTRING
119
120 exit();
121}
122
123# Read given options
124my $install = "";
125my $preprocessonly = "";
126my $certfile = "";
127my $preserveUnsigned = "";
128my $stub = "";
129my $signed_sis_name = "";
130my $onlyUnsigned = "";
131my $convertGcce = "";
132my $dontPatchCaps = "";
133
134unless (GetOptions('i|install' => \$install,
135 'p|preprocess' => \$preprocessonly,
136 'c|certfile=s' => \$certfile,
137 'u|unsigned' => \$preserveUnsigned,
138 'o|only-unsigned' => \$onlyUnsigned,
139 's|stub' => \$stub,
140 'n|sisname=s' => \$signed_sis_name,
141 'g|gcce-is-armv5' => \$convertGcce,
142 'd|dont-patch' => \$dontPatchCaps,)) {
143 Usage();
144}
145
146my $epocroot = $ENV{EPOCROOT};
147my $epocToolsDir = "";
148if ($epocroot ne "") {
149 $epocroot =~ s,\\,/,g;
150 if ($epocroot =~ m,[^/]$,) {
151 $epocroot = $epocroot."/";
152 }
153 $epocToolsDir = "${epocroot}epoc32/tools/";
154}
155
156my $certfilepath = abs_path(dirname($certfile));
157
158# Read params to variables
159my $templatepkg = $ARGV[0];
160my $targetplatform = lc $ARGV[1];
161
162if ($targetplatform eq "") {
163 $targetplatform = "-";
164}
165
166my @tmpvalues = split('-', $targetplatform);
167my $target;
168$target = $tmpvalues[0] or $target = "";
169my $platform;
170$platform = $tmpvalues[1] or $platform = "";
171
172if ($platform =~ m/^gcce$/i) {
173 if (($convertGcce ne "")) {
174 $platform = "armv5";
175 } elsif ($ENV{SBS_HOME}) {
176 # Print a informative note in case suspected misuse is detected.
177 print "\nNote: You should use armv5 as platform or specify -g parameter to convert platform\n";
178 print " when packaging gcce binaries built using symbian-sbsv2 mkspec.\n\n";
179 }
180}
181
182# Convert visual target to real target (debug->udeb and release->urel)
183$target =~ s/debug/udeb/i;
184$target =~ s/release/urel/i;
185
186my $certificate;
187$certificate = $ARGV[2] or $certificate = "";
188my $key;
189$key = $ARGV[3] or $key = "";
190my $passphrase;
191$passphrase = $ARGV[4] or $passphrase = "";
192
193# Generate output pkg basename (i.e. file name without extension)
194my $pkgoutputbasename = $templatepkg;
195my $preservePkgOutput = "";
196$pkgoutputbasename =~ s/_template/_$targetplatform/g;
197$pkgoutputbasename =~ s/_installer\.pkg/_installer___temp\.pkg/g;
198if ($pkgoutputbasename eq $templatepkg) {
199 $preservePkgOutput = "1";
200}
201$pkgoutputbasename =~ s/\.pkg//g;
202
203# Store output file names to variables
204my $pkgoutput = $pkgoutputbasename.".pkg";
205my $sisoutputbasename;
206if ($signed_sis_name eq "") {
207 $sisoutputbasename = $pkgoutputbasename;
208 $sisoutputbasename =~ s/_$targetplatform//g;
209 $sisoutputbasename =~ s/_installer___temp/_installer/g;
210 $signed_sis_name = $sisoutputbasename.".sis";
211} else {
212 $sisoutputbasename = $signed_sis_name;
213 if ($sisoutputbasename =~ m/(\.sis$|\.sisx$)/i) {
214 $sisoutputbasename =~ s/$1//i;
215 } else {
216 $signed_sis_name = $signed_sis_name.".sis";
217 }
218}
219
220my $installer_unsigned_app_sis_name = "";
221my $installer_app_sis_name = "";
222
223if ($templatepkg =~ m/_installer\.pkg$/i && $onlyUnsigned) {
224 $installer_unsigned_app_sis_name = $templatepkg;
225 $installer_unsigned_app_sis_name =~ s/_installer.pkg$/_unsigned.sis/i;
226 $installer_app_sis_name = $installer_unsigned_app_sis_name;
227 $installer_app_sis_name =~ s/_unsigned.sis$/.sis/;
228}
229
230my $unsigned_sis_name = $sisoutputbasename."_unsigned.sis";
231my $stub_sis_name = $sisoutputbasename.".sis";
232
233# Store some utility variables
234my $scriptpath = dirname(__FILE__);
235my $certtext = $certificate;
236# certificates are one step up in hierarchy
237my $certpath = File::Spec->catdir($scriptpath, File::Spec->updir(), "src/s60installs/");
238
239# Check some pre-conditions and print error messages if needed.
240unless (length($templatepkg)) {
241 print "\nERROR: Template PKG filename is not defined!\n";
242 Usage();
243}
244
245# Check template exist
246stat($templatepkg);
247unless( -e _ ) {
248 print "\nERROR: Package description file '$templatepkg' does not exist!\n";
249 Usage();
250}
251
252# Check certifcate preconditions and set default certificate variables if needed
253if (length($certificate)) {
254 unless(length($key)) {
255 print "\nERROR: Custom certificate key file parameter missing.!\n";
256 Usage();
257 }
258} else {
259 #If no certificate is given, check default options
260 $certtext = "RnD";
261 $certificate = File::Spec->catfile($certpath, "rd.cer");
262 $key = File::Spec->catfile($certpath, "rd-key.pem");
263
264 stat($certificate);
265 unless( -e _ ) {
266 $certtext = "Self Signed";
267 $certificate = File::Spec->catfile($certpath, "selfsigned.cer");
268 $key = File::Spec->catfile($certpath, "selfsigned.key");
269 }
270}
271
272# Read the certificates from file to two dimensional array
273my @certificates;
274if (length($certfile)) {
275 open CERTFILE, "<$certfile" or die $!;
276 while(<CERTFILE>){
277 s/#.*//; # ignore comments by erasing them
278 next if /^(\s)*$/; # skip blank lines
279 chomp; # remove trailing newline characters
280 my @certinfo = split(';', $_); # split row to certinfo
281
282 # Trim spaces
283 for(@certinfo) {
284 s/^\s+//;
285 s/\s+$//;
286 }
287
288 # Do some validation
289 unless(scalar(@certinfo) >= 2 && scalar(@certinfo) <= 3 && length($certinfo[0]) && length($certinfo[1]) ) {
290 print "\nERROR: $certfile line '$_' does not contain valid information!\n";
291 Usage();
292 }
293
294 push @certificates, [@certinfo]; # push data to two dimensional array
295 }
296}
297
298# Remove any existing .sis packages
299unlink $unsigned_sis_name;
300if (!$onlyUnsigned) {
301 unlink $signed_sis_name;
302}
303if (!$preservePkgOutput) {
304 unlink $pkgoutput;
305}
306
307# Preprocess PKG
308
309local $/;
310# read template file
311open( TEMPLATE, $templatepkg) or die "ERROR: '$templatepkg': $!";
312$_=<TEMPLATE>;
313close (TEMPLATE);
314
315# If the pkg file does not contain macros, there is no need for platform or target.
316if (m/\$\(PLATFORM\)/) {
317 unless (length($platform) && length($target)) {
318 print "\nERROR: Platform or target is not defined!\n";
319 Usage();
320 }
321}
322
323# replace the PKG variables
324s/\$\(PLATFORM\)/$platform/gm;
325s/\$\(TARGET\)/$target/gm;
326
327if ($installer_unsigned_app_sis_name ne "") {
328 s/$installer_app_sis_name\"/$installer_unsigned_app_sis_name\"/;
329}
330
331#write the output
332open( OUTPUT, ">$pkgoutput" ) or die "ERROR: '$pkgoutput' $!";
333print OUTPUT $_;
334close OUTPUT;
335
336if ($preprocessonly) {
337 exit;
338}
339
340if($stub) {
341 if(!($epocroot)) { die("ERROR: EPOCROOT must be set to create stub sis files"); }
342 my $systeminstall = "${epocroot}epoc32/data/z/system/install";
343 mkpath($systeminstall);
344 my $stub_sis_name = $systeminstall."/".$stub_sis_name;
345 # Create stub SIS.
346 system ("${epocToolsDir}makesis -s $pkgoutput $stub_sis_name");
347} else {
348 if ($certtext eq "Self Signed"
349 && !@certificates
350 && $templatepkg !~ m/_installer\.pkg$/i
351 && !$onlyUnsigned) {
352 my $patch_capabilities = File::Spec->catfile(dirname($0), "patch_capabilities");
353 if ($dontPatchCaps) {
354 system ("$patch_capabilities -c $pkgoutput") and print ("Warning: Package check for self-signing viability failed. Installing the package on a device will most likely fail!\n\n");
355 } else {
356 print("Auto-patching self-signed package.\n");
357 system ("$patch_capabilities $pkgoutput") and die ("ERROR: Automatic patching failed");
358 }
359 }
360
361 # Create SIS.
362 # The 'and' is because system uses 0 to indicate success.
363 system ("${epocToolsDir}makesis $pkgoutput $unsigned_sis_name") and die ("ERROR: makesis failed");
364
365 print("\n");
366
367 my $targetInsert = "";
368 if ($targetplatform ne "-") {
369 $targetInsert = " for $targetplatform";
370 }
371
372 if ($onlyUnsigned) {
373 stat($unsigned_sis_name);
374 if( -e _ ) {
375 print ("Successfully created unsigned package ${unsigned_sis_name}${targetInsert}!\n");
376 } else {
377 print ("\nUnsigned package creation failed!\n");
378 }
379
380 if (!$preservePkgOutput) {
381 unlink $pkgoutput;
382 }
383 print ("\n");
384 exit;
385 }
386
387 # Sign SIS with certificate info given as an argument.
388 my $relcert = File::Spec->abs2rel($certificate);
389 my $relkey = File::Spec->abs2rel($key);
390 # The 'and' is because system uses 0 to indicate success.
391 system ("${epocToolsDir}signsis $unsigned_sis_name $signed_sis_name $relcert $relkey $passphrase") and die ("ERROR: signsis failed");
392
393 # Check if creating signed SIS Succeeded
394 stat($signed_sis_name);
395 if( -e _ ) {
396 print ("Successfully created signed package ${signed_sis_name}${targetInsert} using certificate: $certtext!\n");
397
398 # Sign with additional certificates & keys
399 for my $row ( @certificates ) {
400 # Get certificate absolute file names, relative paths are relative to certfilepath
401 my $relcert = File::Spec->abs2rel(File::Spec->rel2abs( $row->[0], $certfilepath));
402 my $relkey = File::Spec->abs2rel(File::Spec->rel2abs( $row->[1], $certfilepath));
403
404 system ("${epocToolsDir}signsis $signed_sis_name $signed_sis_name $relcert $relkey $row->[2]");
405 print ("\tAdditionally signed the SIS with certificate: $row->[0]!\n");
406 }
407
408 # remove temporary pkg and unsigned sis
409 if (!$preservePkgOutput) {
410 unlink $pkgoutput;
411 }
412 if (!$preserveUnsigned) {
413 unlink $unsigned_sis_name;
414 }
415
416 # Install the sis if requested
417 if ($install) {
418 print ("\nInstalling $signed_sis_name...\n");
419 system ("$signed_sis_name");
420 }
421 } else {
422 # Lets leave the generated PKG for problem solving purposes
423 print ("\nSIS creation failed!\n");
424 }
425 print ("\n");
426}
427
428#end of file
Note: See TracBrowser for help on using the repository browser.