]> mj.ucw.cz Git - libucw.git/blob - ucw/perl/UCW/Configure.pm
UCW::Configure: Translate local filenames to "./file"
[libucw.git] / ucw / perl / UCW / Configure.pm
1 #       Perl module for UCW Configure Scripts
2 #
3 #       (c) 2005--2010 Martin Mares <mj@ucw.cz>
4 #
5 #       This software may be freely distributed and used according to the terms
6 #       of the GNU Lesser General Public License.
7
8 package UCW::Configure;
9
10 use strict;
11 use warnings;
12
13 BEGIN {
14         # The somewhat hairy Perl export mechanism
15         use Exporter();
16         our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
17         $VERSION = 1.0;
18         @ISA = qw(Exporter);
19         @EXPORT = qw(&Init &Log &Notice &Warn &Fail &IsSet &IsGiven &Set &UnSet &Append &Override &Get &Test &TestBool &Include &Finish &FindFile &TryFindFile &DebugDump &PostConfig &AtWrite);
20         @EXPORT_OK = qw();
21         %EXPORT_TAGS = ();
22 }
23
24 our %vars;
25 our %overriden;
26 our @postconfigs;
27 our @atwrites;
28
29 sub DebugDump() {
30         print "VARS:\n";
31         print "$_: $vars{$_}\n" foreach( keys %vars );
32 }
33
34 sub Log($) {
35         print @_;
36 }
37
38 sub Notice($) {
39         print @_ if $vars{"VERBOSE"};
40 }
41
42 sub Warn($) {
43         print "WARNING: ", @_;
44 }
45
46 sub Fail($) {
47         Log("ERROR: " . (shift @_) . "\n");
48         exit 1;
49 }
50
51 sub IsSet($) {
52         my ($x) = @_;
53         return exists $vars{$x};
54 }
55
56 sub IsGiven($) {
57         my ($x) = @_;
58         return exists $overriden{$x};
59 }
60
61 sub Get($) {
62         my ($x) = @_;
63         return $vars{$x};
64 }
65
66 sub Set($;$) {
67         my ($x,$y) = @_;
68         $y=1 unless defined $y;
69         $vars{$x}=$y unless $overriden{$x};
70 }
71
72 sub UnSet($) {
73         my ($x) = @_;
74         delete $vars{$x} unless $overriden{$x};
75 }
76
77 sub Append($$) {
78         my ($x,$y) = @_;
79         Set($x, (IsSet($x) ? (Get($x) . " $y") : $y));
80 }
81
82 sub Override($;$) {
83         my ($x,$y) = @_;
84         $y=1 unless defined $y;
85         $vars{$x}=$y;
86         $overriden{$x} = 1;
87 }
88
89 sub Test($$$) {
90         my ($var,$msg,$sub) = @_;
91         Log "$msg ... ";
92         if (IsSet($var)) {
93                 Log Get($var) . " (preset)\n";
94         } else {
95                 my $val = &$sub();
96                 Set($var, $val);
97                 Log "$val\n";
98         }
99 }
100
101 sub TestBool($$$) {
102         my ($var,$msg,$sub) = @_;
103         Log "$msg ... ";
104         if (IsSet($var) || IsGiven($var)) {
105                 Log ((Get($var) ? "yes" : "no") . " (set)\n");
106         } else {
107                 my ($val, $comment) = &$sub();
108                 Set($var, $val);
109                 Log (($val ? "yes" : "no") . "\n");
110         }
111 }
112
113 sub TryFindFile($) {
114         my ($f) = @_;
115         if ($f =~ m{^/}) {
116                 return (-f $f) ? $f : undef;
117         } elsif (-f $f) {
118                 return "./$f";
119         } elsif (-f (Get("SRCDIR")."/$f")) {
120                 return Get("SRCDIR")."/$f";
121         } else {
122                 return undef;
123         }
124 }
125
126 sub FindFile($) {
127         my ($f) = @_;
128         my $F;
129         defined ($F = TryFindFile($f)) or Fail "Cannot find file $f";
130         return $F;
131 }
132
133 sub Init($$) {
134         my ($srcdir,$defconfig) = @_;
135         sub usage($) {
136                 my ($dc) = @_;
137                 print STDERR "Usage: [<srcdir>/]configure " . (defined $dc ? "[" : "") . "<config-name>" . (defined $dc ? "]" : "") .
138                         " [<option>[=<value>] | -<option>] ...\n";
139                 exit 1;
140         }
141         Set('CONFIG' => $defconfig) if defined $defconfig;
142         if (@ARGV) {
143                 usage($defconfig) if $ARGV[0] eq "--help";
144                 if (!defined($defconfig) || $ARGV[0] !~ /^-?[A-Z][A-Z0-9_]*(=|$)/) {
145                         # This does not look like an option, so read it as a file name
146                         Set('CONFIG' => shift @ARGV);
147                 }
148         }
149         Set("SRCDIR", $srcdir);
150
151         foreach my $x (@ARGV) {
152                 if ($x =~ /^(\w+)=(.*)/) {
153                         Override($1 => $2);
154                 } elsif ($x =~ /^-(\w+)$/) {
155                         Override($1 => 0);
156                         delete $vars{$1};
157                 } elsif ($x =~ /^(\w+)$/) {
158                         Override($1 => 1);
159                 } else {
160                         print STDERR "Invalid option $x\n";
161                         exit 1;
162                 }
163         }
164
165         defined Get("CONFIG") or usage($defconfig);
166         if (!TryFindFile(Get("CONFIG"))) {
167                 TryFindFile(Get("CONFIG")."/config") or Fail "Cannot find configuration " . Get("CONFIG");
168                 Override("CONFIG" => Get("CONFIG")."/config");
169         }
170 }
171
172 sub Include($) {
173         my ($f) = @_;
174         $f = FindFile($f);
175         Notice "Loading configuration $f\n";
176         require $f;
177 }
178
179 sub PostConfig(&) {
180         unshift @postconfigs, $_[0];
181 }
182
183 sub AtWrite(&) {
184         unshift @atwrites, $_[0];
185 }
186
187 sub Finish() {
188         for my $post (@postconfigs) {
189                 &$post();
190         }
191
192         print "\n";
193
194         if (Get("SRCDIR") ne ".") {
195                 Log "Preparing for compilation from directory " . Get("SRCDIR") . " to obj/ ... ";
196                 -l "src" and unlink "src";
197                 symlink Get("SRCDIR"), "src" or Fail "Cannot link source directory to src: $!";
198                 Override("SRCDIR" => "src");
199                 -l "Makefile" and unlink "Makefile";
200                 -f "Makefile" and Fail "Makefile already exists";
201                 symlink "src/Makefile", "Makefile" or Fail "Cannot link Makefile: $!";
202         } else {
203                 Log "Preparing for compilation from current directory to obj/ ... ";
204         }
205         if (-d "obj") {
206                 `rm -rf obj`; Fail "Cannot delete old obj directory" if $?;
207         }
208         -d "obj" or mkdir("obj", 0777) or Fail "Cannot create obj directory: $!";
209         -d "obj/ucw" or mkdir("obj/ucw", 0777) or Fail "Cannot create obj/ucw directory: $!";
210         Log "done\n";
211
212         Log "Generating config.mk ... ";
213         open X, ">obj/config.mk" or Fail $!;
214         print X "# Generated automatically by $0, please don't touch manually.\n";
215         foreach my $x (sort keys %vars) {
216                 print X "$x=$vars{$x}\n";
217         }
218         print X "s=\${SRCDIR}\n";
219         print X "o=obj\n";
220         close X;
221         Log "done\n";
222
223         for my $wr (@atwrites) {
224                 &$wr();
225         }
226 }
227
228 1;  # OK