]> granicus.if.org Git - fortune-mod/blob - scripts/Tatzer
gh actions #3: win32 fix pacman
[fortune-mod] / scripts / Tatzer
1 #!/usr/bin/env perl
2
3 # This is a script to configure the distribution. Its primary audience
4 # are the core developers and halo developers, and not end-users. Please
5 # see the INSTALL file for proper building instructions using cmake.
6 #
7 # "Tatzer" (Taf-Tzadik-Reish) is the Hebrew word for "configure!".
8
9 use strict;
10 use warnings;
11
12 use Getopt::Long qw/ GetOptions /;
13 use Path::Tiny qw/path/;
14
15 my %BOOL_OPTS_WITH_FALSE_DEFAULTS =
16     ( 'omit-frame' => 'OPTIMIZATION_OMIT_FRAME_POINTER', );
17
18 my %TRUE_BOOL_OPTS = ( 'test-suite' => 'WITH_TEST_SUITE', );
19
20 my %INT_OPTS = ( 'pack-size' => 'FCS_IA_PACK_SIZE', );
21
22 my %STR_OPTS = (
23     'arch'   => { param => 'CPU_ARCH', },
24     'prefix' => { param => 'CMAKE_INSTALL_PREFIX', },
25     (
26         map {
27             my ( $key, $param ) = @$_;
28             ( $key => +{ prefix => "${param}_", param => $param } )
29         } ( [], )
30     ),
31 );
32
33 my @BOOL_OPTS_WITH_FALSE_DEFAULTS__KEYS = keys %BOOL_OPTS_WITH_FALSE_DEFAULTS;
34
35 my %bool_opts_with_false_defaults__values =
36     ( map { $_ => 0 } @BOOL_OPTS_WITH_FALSE_DEFAULTS__KEYS );
37
38 my @TRUE_BOOL_KEYS         = keys %TRUE_BOOL_OPTS;
39 my %true_bool_opts__values = map { $_ => 1 } @TRUE_BOOL_KEYS;
40
41 my @INT_OPS__KEYS = keys %INT_OPTS;
42
43 my %int_opts__values = ( map { $_ => undef() } @INT_OPS__KEYS );
44
45 my @STR_OPTS__KEYS = keys %STR_OPTS;
46 for my $k (@STR_OPTS__KEYS)
47 {
48     $STR_OPTS{$k}{'value'} = undef();
49     $STR_OPTS{$k}{'prefix'} //= '';
50 }
51
52 $STR_OPTS{'prefix'}{value} = '/usr';
53
54 my $build_type = "debug";
55 my $generate_what;
56 my $with_context_var      = 1;
57 my $max_bench_threads_num = 4;
58
59 sub set_both
60 {
61     my $val = shift;
62     foreach my $k ('p|pos')
63     {
64         $STR_OPTS{$k}{'value'} = $val;
65     }
66     return;
67 }
68
69 sub set_hash
70 {
71     return set_both("INTERNAL_HASH");
72 }
73
74 set_hash();
75
76 my %themes = (
77     tt         => [qw(-r --notest-suite)],
78     bench      => [qw(-l tt --omit-frame)],
79     fc_bench   => [qw(-l bench)],
80     testing    => [qw(--rwd --test-suite)],
81     pysol_defs => [],
82 );
83
84 my $SEED_KEY = 'FCS_THEME_RAND';
85 my $SEED     = $ENV{$SEED_KEY};
86 if ( defined $SEED )
87 {
88     if ( $SEED =~ /[^0-9]/ )
89     {
90         die "Invalid value for seed!";
91     }
92     my %k;
93     foreach my $flags ( values %themes )
94     {
95         for ( my $idx = 0 ; $idx < @$flags ; ++$idx )
96         {
97             my $flag = $flags->[$idx];
98             if ( $flag eq '-l' )
99             {
100                 ++$idx;
101             }
102             else
103             {
104                 $k{$flag} = 1;
105             }
106         }
107     }
108     my @k = sort { $a cmp $b } keys %k;
109
110     require Math::Random::MT;
111     my $gen = Math::Random::MT->new($SEED);
112     my @subset;
113     foreach my $key (@k)
114     {
115         if ( $gen->rand() < 0.5 )
116         {
117             push @subset, $key;
118         }
119     }
120     my $FN = "run-t-$SEED.bash";
121     path($FN)->spew_utf8( join( ' ', $^X, $0, @subset ) . "\n" );
122     delete $ENV{$SEED_KEY};
123     exec( "bash", $FN );
124 }
125
126 my $HOME = $ENV{HOME} // $ENV{userprofile} // "";
127
128 foreach my $rec (
129     { id => "c2",  a => "core2", },
130     { id => "ci7", a => "corei7-avx", },
131     { id => "n2",  a => "native", },
132     { id => "p4",  a => "pentium4" },
133     { id => "x64", a => "barcelona" },
134     )
135 {
136     my $id   = $rec->{id};
137     my $arch = $rec->{a};
138
139     $themes{$id} = [ "--arch=$arch", "--prefix=$HOME/apps/fcs", ];
140
141     my $def = sub {
142         my ( $suffix, $theme ) = @_;
143         $themes{ $id . $suffix } = [@$theme];
144         return;
145     };
146     my $id_def = sub {
147         my ( $suffix, $theme ) = @_;
148         return $def->( $suffix, [ '-l', $theme, '-l', $id ] );
149     };
150     my $bb_def = sub {
151         my ( $suffix, $theme ) = @_;
152         return $def->( $suffix, [ '-l', $id . 'bb', @$theme ] );
153     };
154
155     # Benchmark for freecell only
156     $id_def->( b => 'fc_bench' );
157
158     # Generalised benchmark - not freecell-only - should pass the tests.
159     $id_def->( bb => 'bench' );
160
161     # Memory conserving theme - for freecell only
162     $id_def->( m => 'fc_reduce_mem' );
163
164     # Generalised Memory conserving theme - not only for freecell
165     $id_def->( mm => 'reduce_mem' );
166
167     # Testing theme - aims to run the tests quickly
168     $bb_def->( t => [qw(-l testing)] );
169
170     # For use by PySolFC
171     $bb_def->(
172         _pysol => [ '-l', 'pysol_defs', "--prefix=$HOME/apps/fcs-for-pysol", ]
173     );
174 }
175
176 my @new_argv = @ARGV;
177
178 CALC_NEW_ARGV:
179 for ( my $idx = 0 ; $idx < @new_argv ; ++$idx )
180 {
181     if ( my ($arg_val) = $new_argv[$idx] =~ m{\A-l(.*)\z}ms )
182     {
183         my $start_idx = $idx;
184
185         my $param = $arg_val || $new_argv[ ++$idx ];
186
187         if ( !( my $cmd = $themes{$param} ) )
188         {
189             die "Unknown -l argument $param!";
190         }
191         else
192         {
193             splice( @new_argv, $start_idx, $idx - $start_idx + 1, @$cmd );
194         }
195
196         $idx = $start_idx;
197         redo CALC_NEW_ARGV;
198     }
199 }
200
201 @ARGV = @new_argv;
202
203 if ( $ENV{VERBOSE} )
204 {
205     print "<@ARGV>";
206 }
207
208 GetOptions(
209     'd|debug' => sub {
210         my ( $opt, $val ) = @_;
211         if ($val)
212         {
213             $build_type = "debug";
214         }
215         return;
216     },
217     'r|release' => sub {
218         my ( $opt, $val ) = @_;
219         if ($val)
220         {
221             $build_type = "release";
222         }
223         elsif ( $build_type eq "release" )
224         {
225             $build_type = "debug";
226         }
227         return;
228     },
229     'hash'    => \&set_hash,
230     'profile' => sub {
231         my ( $opt, $val ) = @_;
232         if ($val)
233         {
234             $build_type = "profile";
235         }
236         elsif ( $build_type eq "profile" )
237         {
238             $build_type = "debug";
239         }
240         return;
241     },
242     'minsize' => sub {
243         $build_type = "MinSizeRel";
244         return;
245     },
246     'gen=s' => \$generate_what,
247     'rwd'   => sub {
248         my ( $opt, $val ) = @_;
249
250         $build_type = "RelWithDebInfo";
251
252         return;
253     },
254     'tokyo'                   => sub { return set_both("TOKYO_CAB_HASH"); },
255     'with-ctx-var!'           => \$with_context_var,
256     'max-bench-threads-num=i' => \$max_bench_threads_num,
257     (
258         map { ; "$_!" => \( $bool_opts_with_false_defaults__values{$_} ) }
259             @BOOL_OPTS_WITH_FALSE_DEFAULTS__KEYS
260     ),
261     ( map { ; "$_!"  => \( $true_bool_opts__values{$_} ) } @TRUE_BOOL_KEYS ),
262     ( map { ; "$_=i" => \( $int_opts__values{$_} ) } @INT_OPS__KEYS ),
263     ( map { ; "$_=s" => \( $STR_OPTS{$_}{value} ) } @STR_OPTS__KEYS ),
264 ) or die "Wrong options";
265
266 my $path_to_source_dir;
267
268 if (@ARGV)
269 {
270     $path_to_source_dir = shift(@ARGV);
271
272     if (@ARGV)
273     {
274         die "Junk at the end of ARGV - <@ARGV>";
275     }
276 }
277 else
278 {
279     $path_to_source_dir = path($0)->parent(2)->child("fortune-mod");
280 }
281
282 # This cache is sometimes causing problems.
283 unlink("CMakeCache.txt");
284 path($_)->remove_tree foreach ( '_Inline', 't/_Inline' );
285 unlink( glob("*.so") );
286
287 my @cmd = (
288     "cmake",
289     (
290         defined( $ENV{CMAKE_MAKE_PROGRAM} )
291         ? "-DCMAKE_MAKE_PROGRAM=$ENV{CMAKE_MAKE_PROGRAM}"
292         : ()
293     ),
294     ( defined($generate_what) ? ( "-G", $generate_what ) : () ),
295     "-DCMAKE_BUILD_TYPE=$build_type",
296     "-DDATADIR=$STR_OPTS{prefix}{value}/share",
297     (
298         map {
299             $bool_opts_with_false_defaults__values{$_}
300                 ? ( "-D" . $BOOL_OPTS_WITH_FALSE_DEFAULTS{$_} . "=1" )
301                 : ()
302         } @BOOL_OPTS_WITH_FALSE_DEFAULTS__KEYS
303     ),
304     (
305         map {
306                   '-D'
307                 . $TRUE_BOOL_OPTS{$_} . '='
308                 . ( $true_bool_opts__values{$_} ? '1' : '' )
309         } @TRUE_BOOL_KEYS
310     ),
311     (
312         map {
313             defined( $int_opts__values{$_} )
314                 ? ( "-D" . $INT_OPTS{$_} . "=" . $int_opts__values{$_} )
315                 : ()
316         } @INT_OPS__KEYS
317     ),
318     (
319         map {
320             my $k = $_;
321             my $r = $STR_OPTS{$k};
322             my $v = $r->{value};
323             defined($v) ? ("-D$r->{param}=$r->{prefix}$v") : ()
324         } @STR_OPTS__KEYS
325     ),
326 );
327
328 push @cmd, $path_to_source_dir;
329
330 print( join( " ", @cmd ), "\n" );
331 my $exit_code = system(@cmd);
332 exit( $exit_code ? 1 : 0 );
333
334 __END__
335
336 =head1 COPYRIGHT AND LICENSE
337
338 This file is part of Black Hole Solitaire Solver. It is subject to the license
339 terms in the COPYING file found in the top-level directory of this distribution
340 and at https://github.com/shlomif/black-hole-solitaire/blob/master/LICENSE .
341 No part of Black Hole Solitaire Solver, including this file, may be copied,
342 modified, propagated, or distributed except according to the terms contained
343 in the COPYING file.
344
345 Copyright (c) 2009 Shlomi Fish
346
347 =cut