Accidentally removed mingw32-gettext - readded.
[fedora-mingw.git] / nsiswrapper / nsiswrapper.pl
1 #!/usr/bin/perl -w
2 #
3 # NSISWrapper - a helper program for making Windows installers.
4 # Copyright (C) 2008 Red Hat Inc.
5 # Written by Richard W.M. Jones <rjones@redhat.com>,
6 # http://fedoraproject.org/wiki/MinGW
7 #
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or (at
11 # your option) any later version.
12 #
13 # This program is distributed in the hope that it will be useful, but
14 # WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 # General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public License
19 # along with this program; if not, write to the Free Software
20 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 use strict;
23 use Getopt::Long;
24 use Pod::Usage;
25 use File::Temp qw/tempfile/;
26 #use Data::Dumper;
27
28 =pod
29
30 =head1 NAME
31
32 nsiswrapper - Helper program for making NSIS Windows installers
33
34 =head1 SYNOPSIS
35
36  nsiswrapper [options] [roots...]
37
38  nsiswrapper myprogram.exe anotherprog.exe docs/ > script.nsis
39
40  nsiswrapper --run myprogram.exe anotherprog.exe docs/
41
42 =head1 DESCRIPTION
43
44 nsiswrapper is a helper program for making it easier to create Windows
45 installers in a cross-compiler environment.  It still requires NSIS (a
46 Windows installer generator) but cuts out the tedium of writing the
47 NSIS command script, and can even invoke NSIS automatically to
48 generate a final Windows executable.
49
50 The general way to use it is to list out some files that you want
51 packaged.  For example:
52
53   nsiswrapper myprogram.exe
54
55 This will search for C<myprogram.exe> and any libraries (C<*.dll>)
56 that it depends upon, and then it will print out an NSIS script.
57
58 If you want to have it run C<makensis> as well (to automatically
59 create a Windows installer) then do:
60
61   nsiswrapper --run myprogram.exe
62
63 which will generate C<installer.exe> output file that contains
64 C<myprogram.exe> plus any dependencies.
65
66 You can list other files and directories that you want to have
67 contained in your installer.  For example:
68
69   nsiswrapper myprogram.exe anotherprog.exe docs/*.html
70
71 There are many other command line options which control aspects of the
72 NSIS command script (and hence, the final installer), such as:
73
74 =over 4
75
76 =item *
77
78 The name of the final installer.
79
80 =item *
81
82 Desktop shortcuts and menu items.
83
84 =item *
85
86 License files.
87
88 =back
89
90 It's a good idea to examine the NSIS command script, to check that
91 nsiswrapper is including all the right dependencies.
92
93 =head1 ROOTS (FILES AND DIRECTORIES)
94
95 Each parameter should refer to a file or directory which is to be
96 included in the installer.
97
98 These are known as "roots" because we also automatically add any
99 dependencies to the list of files.  Thus if a Windows executable
100 requires any DLLs, those are added automatically.  DLLs are searched
101 for on the current C<$PATH> (environment variable).
102
103 We choose the install location by removing any common prefix from the
104 names of roots, which generally ensures that the original directory
105 structure is preserved.  Thus for example if the original roots (and
106 any dependencies) are:
107
108  /usr/i686-pc-mingw32/sys-root/mingw/bin/program.exe
109  /usr/i686-pc-mingw32/sys-root/mingw/bin/library.dll
110  /usr/i686-pc-mingw32/sys-root/mingw/etc/config
111
112 then the install directory will look like this:
113
114  $INSTDIR/bin/program.exe
115  $INSTDIR/bin/library.dll
116  $INSTDIR/etc/config
117
118 (C<$INSTDIR> is the installation directory chosen by the user at
119 install time).
120
121 You can also specify the install location (relative to C<$INSTDIR>) by
122 adding roots of the form:
123
124  source=destination
125
126 for example:
127
128  /usr/i686-pc-mingw32/sys-root/mingw/bin/program.exe=program.exe
129  /usr/i686-pc-mingw32/sys-root/mingw/bin/library.dll=library.dll
130  /usr/i686-pc-mingw32/sys-root/mingw/etc/config=conf/config
131
132 which results in:
133
134  $INSTDIR/program.exe
135  $INSTDIR/library.dll
136  $INSTDIR/conf/config
137
138 =head1 OPTIONS
139
140 =over 4
141
142 =item B<--help>
143
144 Print brief help message and exit.
145
146 =item B<--man>
147
148 Print the full manual page for the command and exit.
149
150 =item B<--verbose>
151
152 Print verbose messages while running.  If this is not given then we
153 try to operate quietly.
154
155 =item B<--run>
156
157 Normally this program just prints out the NSIS installer command
158 script.  However if you supply this option, then we run C<makensis>
159 and attempt to generate an actual Windows installer.
160
161 =item B<--with-gtk>
162
163 GTK programs should normally supply this option.  It ensures that the
164 correct files are copied and/or created by the installer for GTK
165 programs to work.
166
167 =item B<--name "Name">
168
169 Set the long name of the installer.
170
171 If not set, the script tries to invent a suitable name based on the
172 first root file given on the command line.
173
174 See also B<--outfile>.
175
176 =item B<--outfile myinstaller.exe>
177
178 Set the output filename for the installer.
179
180 If not set, this defaults to C<installer.exe>.
181
182 This is the same as the C<OutFile> option to NSIS.
183
184 =item B<--installdir 'C:\foo'>
185
186 Set the default Windows installation directory.  If not set, this
187 program will choose a suitable default based on the name.
188
189 In any case, the end user can override this when they run the
190 installer.
191
192 Note that since this string will contain backslashes, you should
193 single-quote it to protect it from the shell.
194
195 This is the same as the C<InstallDir> option to NSIS.
196
197 =item B<--installdirregkey 'HKLM SOFTWARE\FOO'>
198
199 Set the name of the registry key used to save the installation
200 directory.  This has two purposes: Firstly it is used to automagically
201 remember the installation directory between installs.  Secondly your
202 program can use this as one method to find its own installation
203 directory (there are other ways to do this).
204
205 The default is C<HKLM SOFTWARE\Name> where C<Name> is derived from the
206 name of the installer.
207
208 Note that since this string will contain backslashes and spaces, you
209 should single-quote it to protect it from the shell.
210
211 This is the same as the C<InstallDirRegKey> option to NSIS.
212
213 =back
214
215 =cut
216
217 my $objdump;
218 my %files;
219
220 my $help = '';
221 my $man = '';
222 my $verbose = '';
223 my $run = '';
224 my $with_gtk = '';
225 my $name = '';
226 my $outfile = 'installer.exe';
227 my $installdir = '';
228 my $installdirregkey = '';
229
230 # XXX Should make these configurable.
231 my $mingw32_prefix = '/usr/i686-pc-mingw32/sys-root/mingw';
232 my $mingw32_bindir = $mingw32_prefix . '/bin';
233 my $mingw32_libdir = $mingw32_prefix . '/lib';
234 my $mingw32_sysconfdir = $mingw32_prefix . '/etc';
235
236 sub get_options
237 {
238     my $result = GetOptions (
239         "help|?" => \$help,
240         "man" => \$man,
241         "verbose" => \$verbose,
242         "run" => \$run,
243         "with-gtk" => \$with_gtk,
244         "name=s" => \$name,
245         "outfile=s" => \$outfile,
246         "installdir=s" => \$installdir,
247         "installdirregkey=s" => \$installdirregkey,
248     );
249     die "nsiswrapper: use --help for information about command line options\n"
250         unless $result;
251
252     pod2usage(1) if $help;
253     pod2usage(-exitstatus => 0, -verbose => 2) if $man;
254
255     # Add the roots to the list of files.
256     die "nsiswrapper: no roots specified: use --help for more help\n"
257         if @ARGV == 0;
258     foreach my $file (@ARGV) {
259         my ($dir, $exec) = (0, 0);
260
261         # Is it source=destination?
262         my ($source, $dest);
263         if ($file =~ /^(.*)=(.*)$/) {
264             $source = $1;
265             $dest = $2;
266         } else {
267             $source = $file;
268         }
269
270         die "$source: not a file or directory\n"
271             unless -f $source || -d $source;
272
273         $exec = 1 if $source =~ m/\.exe$/i;
274         $dir = 1 if -d $source;
275
276         $files{$source} = {
277             name => $source,
278             root => 1,
279             dir => $dir,
280             exec => $exec,
281         };
282
283         # Deal with explicit destination.
284         if (defined $dest) {
285             my ($install_dir, $install_name);
286
287             if ($dest =~ m{(.*)/(.*)}) {
288                 $install_dir = $1;
289                 $install_name = $2;
290             } else {
291                 $install_dir = ".";
292                 $install_name = $dest;
293             }
294
295             # Convert / in install_dir into backslashes.
296             $install_dir =~ s{/}{\\}g;
297
298             $files{$source}->{install_dir} = $install_dir;
299             $files{$source}->{install_name} = $install_name;
300         }
301     }
302
303     # Name not set?
304     if (!$name) {
305         # Massage the first root into a suitable package name.
306         $_ = $ARGV[0];
307         s{.*/}{};
308         s{=.*$}{};
309         s{\.\w\w\w\w?$}{};
310         $_ = ucfirst;
311         $name = $_;
312     }
313
314     # InstallDir not set?
315     if (!$installdir) {
316         $_ = $name;
317         s/\W/-/g;
318         $installdir = "c:\\$_"
319     }
320
321     # InstallDirRegKey not set?
322     if (!$installdirregkey) {
323         $_ = $name;
324         s/\W/-/g;
325         $installdirregkey = "HKLM SOFTWARE\\$_"
326     }
327 }
328
329 # Check prerequisites.
330
331 sub check_prereqs
332 {
333     my @paths = split (/:/, $ENV{PATH});
334
335     if (! $objdump) {
336         $objdump = check_path ("i686-pc-mingw32-objdump", @paths);
337         if (! $objdump || ! -x $objdump) {
338             die "i686-pc-mingw32-objdump: program not found on \$PATH\n"
339         }
340     }
341 }
342
343 # Check for the existance of a file at the given paths (not
344 # necessarily executable).  Returns the pathname of the file or
345 # undefined if not found.
346
347 sub check_path
348 {
349     local $_ = shift;
350     my @paths = @_;
351
352     my $found;
353     foreach my $dir (@paths) {
354         my $file = $dir . "/" . $_;
355         if (-f $file) {
356             $found = $file;
357             last;
358         }
359     }
360     $found
361 }
362
363 # Print configuration.
364
365 sub print_config
366 {
367     print "Configuration:\n";
368     print "\t\$PATH = $ENV{PATH}\n";
369     print "\t\$objdump = $objdump\n";
370     print "\t\$verbose = $verbose\n";
371     print "\t\$name = \"$name\"\n";
372     print "\t\$outfile = \"$outfile\"\n";
373     print "\t\$installdir = \"$installdir\"\n";
374     print "\t\$installdirregkey = \"$installdirregkey\"\n";
375     my @roots = keys %files;
376     print "\t\@roots = (", join (", ", @roots), ")\n";
377     print "End of configuration.\n";
378 }
379
380 # Starting at the roots, get the dependencies.
381
382 my $missing_deps = 0;
383
384 sub do_dependencies
385 {
386     my $deps_added = 1;
387
388     while ($deps_added > 0) {
389         $deps_added = 0;
390
391         foreach (keys %files) {
392             my @deps = get_deps_for_file ($_);
393
394             # Add the deps as separate files.
395             foreach (@deps) {
396                 $deps_added += add_file_unless_exists (
397                     $_,
398                     root => 0,
399                     dir => 0,
400                     exec => 0
401                     );
402             }
403         }
404     }
405
406     die "please correct missing dependencies shown above\n"
407         if $missing_deps > 0;
408 }
409
410 sub add_file_unless_exists
411 {
412     my $name = shift;
413     my %details = @_;
414
415     unless (exists $files{$name}) {
416         die "$name: not a file or directory\n" unless -f $name || -d $name;
417
418         $details{name} = $name;
419         $files{$name} = \%details;
420
421         return 1;
422     } else {
423         return 0;
424     }
425 }
426
427 my $path_warning = 0;
428
429 sub get_deps_for_file
430 {
431     my $file = shift;
432     my @paths = split (/:/, $ENV{PATH});
433
434     # If we already fetched the dependencies for this file, just
435     # return that list now.
436     if (exists $files{$file}->{deps}) {
437         return @{$files{$file}->{deps}}
438     }
439
440     my @deps = ();
441
442     # We only know how to do this for *.exe and *.dll files.
443     if (m/\.exe$/i || m/\.dll$/i) {
444         my $cmd = "$objdump -p '$file' |
445                    grep 'DLL Name:' |
446                    grep -Eo '[-._[:alnum:]]+\.dll' |
447                    sort -u"; # XXX quoting
448         open DEPS, "$cmd |" or die "$cmd: $!";
449         foreach (<DEPS>) {
450             chomp; $_ = lc;
451
452             # Ignore Windows system DLL deps.
453             next if is_windows_system_dll ($_);
454
455             # Does the file exist on the path?
456             my $found = check_path ($_, @paths);
457             if ($found) {
458                 push @deps, $found;
459             } else {
460                 warn "MISSING DEPENDENCY: $_ (for $file)\n";
461                 $missing_deps++;
462                 unless ($path_warning) {
463                     warn "You may need to add the directory containing this file to your \$PATH\n";
464                     $path_warning = 1;
465                 }
466             }
467         }
468         close DEPS;
469
470         if ($verbose) {
471             if (@deps > 0) {
472                 print "dependencies found for binary $file:\n\t",
473                   join ("\n\t", @deps), "\n";
474             } else {
475                 print "no dependencies found for $file\n"
476             }
477         }
478
479     }
480
481     # Cache the list of dependencies so we can just return it
482     # immediately next time.
483     $files{$file}->{deps} = \@deps;
484     return @deps;
485 }
486
487 sub is_windows_system_dll
488 {
489     local $_ = shift;
490
491     $_ eq 'gdi32.dll' ||
492         $_ eq 'kernel32.dll' ||
493         $_ eq 'ole32.dll' ||
494         $_ eq 'mscoree.dll' ||
495         $_ eq 'msvcrt.dll' ||
496         $_ eq 'user32.dll'
497 }
498
499 # Add Gtk dependencies, if --with-gtk.
500
501 sub do_gtk
502 {
503     add_file_unless_exists (
504         "$mingw32_libdir/gtk-2.0",
505         root => 0,
506         dir => 1,
507         exec => 0,
508         install_dir => "lib",
509         install_name => "gtk-2.0"
510         );
511
512     add_file_unless_exists (
513         "$mingw32_libdir/pango",
514         root => 0,
515         dir => 1,
516         exec => 0,
517         install_dir => "lib",
518         install_name => "pango"
519         );
520
521     add_file_unless_exists (
522         "$mingw32_sysconfdir/fonts",
523         root => 0,
524         dir => 1,
525         exec => 0,
526         install_dir => "etc",
527         install_name => "fonts"
528         );
529
530     add_file_unless_exists (
531         "$mingw32_sysconfdir/gtk-2.0",
532         root => 0,
533         dir => 1,
534         exec => 0,
535         install_dir => "etc",
536         install_name => "gtk-2.0"
537         );
538
539     add_file_unless_exists (
540         "$mingw32_sysconfdir/pango",
541         root => 0,
542         dir => 1,
543         only_mkdir => 1,
544         exec => 0,
545         install_dir => "etc",
546         install_name => "pango"
547         );
548
549     # We need to run pango-querymodules after installation to
550     # rebuild etc\pango\pango.modules.
551     add_file_unless_exists (
552         "$mingw32_bindir/pango-querymodules.exe",
553         root => 0,
554         dir => 0,
555         exec => 0
556         );
557 }
558
559 # Decide how we will name the output files.  This removes the
560 # common prefix from filenames, if it can determine one.
561
562 sub install_names
563 {
564     my @names = keys %files;
565
566     # Don't care about files that already have an install
567     # directory/name defined, ie. they were specified as source=dest
568     # on the command line.
569     @names = grep { ! exists $files{$_}->{install_name} } @names;
570
571     # Determine if all the names share a common prefix.
572     my @namelens = map { length } @names;
573     my $shortest = min (@namelens);
574
575     my $prefixlen;
576     for ($prefixlen = $shortest; $prefixlen >= 0; --$prefixlen) {
577         my @ns = map { substr $_, 0, $prefixlen } @names;
578         last if same (@ns);
579     }
580
581     if ($verbose) { print "prefix length = $prefixlen\n" }
582
583     # Remove the prefix from each name and save the install directory
584     # and install filename separately.
585     foreach my $name (@names) {
586         my $install_as = substr $name, $prefixlen;
587
588         my ($install_dir, $install_name);
589
590         if ($install_as =~ m{(.*)/(.*)}) {
591             $install_dir = $1;
592             $install_name = $2;
593         } else {
594             $install_dir = ".";
595             $install_name = $install_as;
596         }
597
598         # Convert / in install_dir into backslashes.
599         $install_dir =~ s{/}{\\}g;
600
601         $files{$name}->{install_dir} = $install_dir;
602         $files{$name}->{install_name} = $install_name;
603     }
604 }
605
606 sub max
607 {
608     my $max = $_[0];
609     for (@_[1..$#_]) {
610         $max = $_ if $_ > $max;
611     }
612     $max
613 }
614
615 sub min
616 {
617     my $min = $_[0];
618     for (@_[1..$#_]) {
619         $min = $_ if $_ < $min;
620     }
621     $min
622 }
623
624 sub same
625 {
626     my  $s = $_[0];
627     for (@_[1..$#_]) {
628         return 0 if $_ ne $s;
629     }
630     1;
631 }
632
633 # Print the list of files.
634
635 sub print_files
636 {
637     print "Files:\n";
638     foreach (sort keys %files) {
639         print "\t$_";
640         if ($files{$_}->{root}) {
641             print " [root]";
642         }
643         if ($files{$_}->{dir}) {
644             print " [dir]";
645         }
646         print STDOUT ("\n\t  => ",
647                $files{$_}->{install_dir}, " \\ ", $files{$_}->{install_name},
648                "\n");
649     }
650     print "End of files.\n";
651 }
652
653 # Write the NSIS script.
654
655 sub write_script
656 {
657     my $io = shift;
658
659     print $io <<EOT;
660 #!Nsis Installer Command Script
661 #
662 # This is an NSIS Installer Command Script generated automatically
663 # by the Fedora nsiswrapper program.  For more information see:
664 #
665 #   http://fedoraproject.org/wiki/MinGW
666 #
667 # To build an installer from the script you would normally do:
668 #
669 #   makensis this_script
670 #
671 # which will generate the output file '$outfile' which is a Windows
672 # installer containing your program.
673
674 Name "$name"
675 OutFile "$outfile"
676 InstallDir "$installdir"
677 InstallDirRegKey $installdirregkey "Install_Dir"
678
679 ShowInstDetails hide
680 ShowUninstDetails hide
681
682 # Uncomment this to enable BZip2 compression, which results in
683 # slightly smaller files but uses more memory at install time.
684 #SetCompressor bzip2
685
686 XPStyle on
687
688 Page components
689 Page directory
690 Page instfiles
691
692 ComponentText "Select which optional components you want to install."
693
694 DirText "Please select the installation folder."
695
696 Section "$name"
697   SectionIn RO
698 EOT
699
700     # Set the output files.
701     my $olddir;
702     foreach (sort keys %files) {
703         if (!$olddir || $files{$_}->{install_dir} ne $olddir) {
704             # Moved into a new install directory.
705             my $dir = $files{$_}->{install_dir};
706             print $io "\n  SetOutPath \"\$INSTDIR\\$dir\"\n";
707             $olddir = $dir;
708         }
709
710         # If it's a directory, we copy it recursively, otherwise
711         # just copy the single file.
712         if ($files{$_}->{dir}) {
713             if ($files{$_}->{only_mkdir}) {
714                 # This is a hack to allow us to create empty directories.
715                 my $install_dir = $files{$_}->{install_dir};
716                 my $install_name = $files{$_}->{install_name};
717                 print $io "  CreateDirectory \"\$INSTDIR\\$install_dir\\$install_name\"\n";
718             } else {
719                 print $io "  File /r \"$_\"\n";
720             }
721         } else {
722             print $io "  File \"$_\"\n";
723         }
724     }
725
726     # GTK?
727     if ($with_gtk) {
728         my $install_dir = $files{"$mingw32_bindir/pango-querymodules.exe"}->{install_dir};
729         my $install_name = $files{"$mingw32_bindir/pango-querymodules.exe"}->{install_name};
730
731         # This particular piece of Windows stupidity is documented here:
732         # http://forums.winamp.com/showthread.php?postid=438771#post438771
733         # http://forums.winamp.com/printthread.php?s=53c76b4ae4221ff1d9dc361fc5bf7ea2&threadid=231797
734         print $io "\n";
735         print $io "  ReadEnvStr \$0 COMSPEC\n";
736         print $io "  SetOutPath \"\$INSTDIR\"\n";
737         print $io "  nsExec::ExecToLog '\$0 /C $install_dir\\$install_name > etc\\pango\\pango.modules'\n"
738     }
739
740     print $io <<EOT;
741 SectionEnd
742
743 Section "Start Menu Shortcuts"
744   CreateDirectory "\$SMPROGRAMS\\$name"
745   CreateShortCut "\$SMPROGRAMS\\$name\\Uninstall $name.lnk" "\$INSTDIR\\Uninstall $name.exe" "" "\$INSTDIR\\Uninstall $name.exe" 0
746 EOT
747
748     # Start menu entries for each executable.
749     foreach (sort keys %files) {
750         if ($files{$_}->{exec}) {
751             my $install_dir = $files{$_}->{install_dir};
752             my $install_name = $files{$_}->{install_name};
753             print $io "  CreateShortCut \"\$SMPROGRAMS\\$name\\$install_name.lnk\" \"\$INSTDIR\\$install_dir\\$install_name\" \"\" \"\$INSTDIR\\$install_dir\\$install_name\" 0\n";
754         }
755     }
756
757     print $io <<EOT;
758 SectionEnd
759
760 Section "Desktop Icons"
761 EOT
762
763     # Desktop icons for each executable.
764     foreach (sort keys %files) {
765         if ($files{$_}->{exec}) {
766             my $install_dir = $files{$_}->{install_dir};
767             my $install_name = $files{$_}->{install_name};
768             print $io "  CreateShortCut \"\$DESKTOP\\$install_name.lnk\" \"\$INSTDIR\\$install_dir\\$install_name\" \"\" \"\$INSTDIR\\$install_dir\\$install_name\" 0\n";
769         }
770     }
771
772     print $io <<EOT;
773 SectionEnd
774
775 Section "Uninstall"
776 EOT
777
778     # Remove desktop icons and menu shortcuts.
779     foreach (reverse sort keys %files) {
780         if ($files{$_}->{exec}) {
781             my $install_name = $files{$_}->{install_name};
782             print $io "  Delete /rebootok \"\$DESKTOP\\$install_name.lnk\"\n";
783             print $io "  Delete /rebootok \"\$SMPROGRAMS\\$name\\$install_name.lnk\"\n";
784         }
785     }
786     print $io "  Delete /rebootok \"\$SMPROGRAMS\\$name\\Uninstall $name.lnk\"\n";
787     print $io "  RMDir \"\$SMPROGRAMS\\$name\"\n\n";
788
789     # Remove remaining files.
790     $olddir = '';
791     foreach (reverse sort keys %files) {
792         if (!$olddir || $files{$_}->{install_dir} ne $olddir) {
793             # Moved into a new install directory, so delete the previous one.
794             print $io "  RMDir \"\$INSTDIR\\$olddir\"\n\n"
795                 if $olddir;
796             $olddir = $files{$_}->{install_dir};
797         }
798
799         # If it's a directory, we delete it recursively, otherwise
800         # just delete the single file.
801         my $install_dir = $files{$_}->{install_dir};
802         my $install_name = $files{$_}->{install_name};
803         if ($files{$_}->{dir}) {
804             print $io "  RMDir /r \"\$INSTDIR\\$install_dir\\$install_name\"\n\n";
805             $olddir = ''; # Don't double-delete directory.
806         } else {
807             print $io "  Delete /rebootok \"\$INSTDIR\\$install_dir\\$install_name\"\n";
808         }
809     }
810
811     print $io "  RMDir \"\$INSTDIR\\$olddir\"\n" if $olddir;
812
813     print $io <<EOT;
814   RMDir "\$INSTDIR"
815 SectionEnd
816
817 Section -post
818   WriteUninstaller "\$INSTDIR\\Uninstall $name.exe"
819 SectionEnd
820 EOT
821 }
822
823 # Run makensis on the named file.
824
825 sub run_makensis
826 {
827     my $filename = shift;
828
829     system ("makensis", $filename) == 0 or die "makensis: $?"
830 }
831
832 # Main program.
833
834 sub main
835 {
836     get_options ();
837     check_prereqs ();
838     print_config () if $verbose;
839     do_gtk () if $with_gtk;
840     do_dependencies ();
841     install_names ();
842     print_files () if $verbose;
843     if ($run) {
844         my ($io, $filename) = tempfile ("nswXXXXXX", UNLINK => 1);
845         write_script ($io);
846         close $io;
847         run_makensis ($filename);
848     } else {
849         write_script (\*STDOUT);
850     }
851 }
852
853 main ()