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