Suggest -H to improve GC productivity, fixes #10474.
[ghc.git] / boot
1 #!/usr/bin/env perl
2
3 use warnings;
4 use strict;
5
6 use Cwd;
7 use File::Path 'rmtree';
8 use File::Basename;
9
10 my %required_tag;
11 my $validate;
12 my $curdir;
13
14 $required_tag{"-"} = 1;
15 $validate = 0;
16
17 $curdir = &cwd()
18     or die "Can't find current directory: $!";
19
20 while ($#ARGV ne -1) {
21     my $arg = shift @ARGV;
22
23     if ($arg =~ /^--required-tag=(.*)/) {
24         $required_tag{$1} = 1;
25     }
26     elsif ($arg =~ /^--validate$/) {
27         $validate = 1;
28     }
29     else {
30         die "Bad arg: $arg";
31     }
32 }
33
34 sub sanity_check_line_endings {
35     local $/ = undef;
36     open FILE, "packages" or die "Couldn't open file: $!";
37     binmode FILE;
38     my $string = <FILE>;
39     close FILE;
40
41     if ($string =~ /\r/) {
42         print STDERR <<EOF;
43 Found ^M in packages.
44 Perhaps you need to run
45     git config --global core.autocrlf false
46 and re-check out the tree?
47 EOF
48         exit 1;
49     }
50 }
51
52 sub sanity_check_tree {
53     my $tag;
54     my $dir;
55
56     # Check that we have all boot packages.
57     open PACKAGES, "< packages";
58     while (<PACKAGES>) {
59         if (/^#/) {
60             # Comment; do nothing
61         }
62         elsif (/^([a-zA-Z0-9\/.-]+) +([^ ]+) +[^ ]+ +[^ ]+$/) {
63             $dir = $1;
64             $tag = $2;
65
66             # If $tag is not "-" then it is an optional repository, so its
67             # absence isn't an error.
68             if (defined($required_tag{$tag})) {
69                 # We would like to just check for a .git directory here,
70                 # but in an lndir tree we avoid making .git directories,
71                 # so it doesn't exist. We therefore require that every repo
72                 # has a LICENSE file instead.
73                 if (! -f "$dir/LICENSE") {
74                     print STDERR "Error: $dir/LICENSE doesn't exist.\n";
75                     die "Maybe you haven't done './sync-all get'?";
76                 }
77             }
78         }
79         else {
80             die "Bad line in packages file: $_";
81         }
82     }
83     close PACKAGES;
84 }
85
86 # Create libraries/*/{ghc.mk,GNUmakefile}
87 sub boot_pkgs {
88     my @library_dirs = ();
89
90     my $package;
91
92     for $package (glob "libraries/*/") {
93         $package =~ s/\/$//;
94         my $pkgs = "$package/ghc-packages";
95         if (-f $pkgs) {
96             open PKGS, "< $pkgs"
97                 or die "Failed to open $pkgs: $!";
98             while (<PKGS>) {
99                 chomp;
100                 s/\r//g;
101                 if (/.+/) {
102                     push @library_dirs, "$package/$_";
103                 }
104             }
105         }
106         else {
107             push @library_dirs, $package;
108         }
109     }
110
111     for $package (@library_dirs) {
112         my $dir = &basename($package);
113         my @cabals = glob("$package/*.cabal");
114         if ($#cabals > 0) {
115             die "Too many .cabal file in $package\n";
116         }
117         if ($#cabals eq 0) {
118             my $cabal = $cabals[0];
119             my $pkg;
120             my $top;
121             if (-f $cabal) {
122                 $pkg = $cabal;
123                 $pkg =~ s#.*/##;
124                 $pkg =~ s/\.cabal$//;
125                 $top = $package;
126                 $top =~ s#[^/]+#..#g;
127                 $dir = $package;
128                 $dir =~ s#^libraries/##g;
129
130                 print "Creating $package/ghc.mk\n";
131                 open GHCMK, "> $package/ghc.mk"
132                     or die "Opening $package/ghc.mk failed: $!";
133                 print GHCMK "${package}_PACKAGE = ${pkg}\n";
134                 print GHCMK "${package}_dist-install_GROUP = libraries\n";
135                 print GHCMK "\$(if \$(filter ${dir},\$(PACKAGES_STAGE0)),\$(eval \$(call build-package,${package},dist-boot,0)))\n";
136                 print GHCMK "\$(if \$(filter ${dir},\$(PACKAGES_STAGE1)),\$(eval \$(call build-package,${package},dist-install,1)))\n";
137                 print GHCMK "\$(if \$(filter ${dir},\$(PACKAGES_STAGE2)),\$(eval \$(call build-package,${package},dist-install,2)))\n";
138                 close GHCMK
139                     or die "Closing $package/ghc.mk failed: $!";
140
141                 print "Creating $package/GNUmakefile\n";
142                 open GNUMAKEFILE, "> $package/GNUmakefile"
143                     or die "Opening $package/GNUmakefile failed: $!";
144                 print GNUMAKEFILE "dir = ${package}\n";
145                 print GNUMAKEFILE "TOP = ${top}\n";
146                 print GNUMAKEFILE "include \$(TOP)/mk/sub-makefile.mk\n";
147                 print GNUMAKEFILE "FAST_MAKE_OPTS += stage=0\n";
148                 close GNUMAKEFILE
149                     or die "Closing $package/GNUmakefile failed: $!";
150             }
151         }
152     }
153 }
154
155 # autoreconf everything that needs it.
156 sub autoreconf {
157     my $dir;
158
159     foreach $dir (".", glob("libraries/*/")) {
160         if (-f "$dir/configure.ac") {
161             print "Booting $dir\n";
162             chdir $dir or die "can't change to $dir: $!";
163             system("autoreconf") == 0
164                 or die "Running autoreconf failed with exitcode $?";
165             chdir $curdir or die "can't change to $curdir: $!";
166         }
167     }
168 }
169
170 sub checkBuildMk {
171     if ($validate eq 0 && ! -f "mk/build.mk") {
172         print <<EOF;
173
174 WARNING: You don't have a mk/build.mk file.
175
176 By default a standard GHC build will be done, which uses optimisation
177 and builds the profiling libraries. This will take a long time, so may
178 not be what you want if you are developing GHC or the libraries, rather
179 than simply building it to use it.
180
181 For information on creating a mk/build.mk file, please see:
182     http://ghc.haskell.org/trac/ghc/wiki/Building/Using#Buildconfiguration
183
184 EOF
185     }
186 }
187
188 &sanity_check_line_endings();
189 &sanity_check_tree();
190 &boot_pkgs();
191 &autoreconf();
192 &checkBuildMk();
193