aboutsummaryrefslogtreecommitdiff
path: root/tools/build/module-install.pl
diff options
context:
space:
mode:
authorpmichaud <pmichaud@pobox.com>2012-08-28 00:36:53 -0500
committerpmichaud <pmichaud@pobox.com>2012-08-28 00:36:53 -0500
commitc012d8b882480151d8eb7da92c4cca80d1d9b814 (patch)
tree827354a3d38adfafe328ef55fa454147cc4af868 /tools/build/module-install.pl
parentc3ff6182252a634e2ce8167a8bd367932e858dd5 (diff)
Move skel/ into top-level directory, to try building directly from the repo.
Diffstat (limited to 'tools/build/module-install.pl')
-rw-r--r--tools/build/module-install.pl112
1 files changed, 112 insertions, 0 deletions
diff --git a/tools/build/module-install.pl b/tools/build/module-install.pl
new file mode 100644
index 0000000..8d69c78
--- /dev/null
+++ b/tools/build/module-install.pl
@@ -0,0 +1,112 @@
+#! perl
+
+use warnings;
+use strict;
+use File::Find;
+use File::Copy;
+use File::Path;
+use File::Basename;
+
+my $perl6bin = shift @ARGV;
+my $perl6lib = shift @ARGV;
+
+my @pmfiles;
+my @mod_pms;
+while (@ARGV) {
+ my $module = shift @ARGV;
+ print "== Installing module $module\n";
+ our $mlib = "$module/lib";
+
+ @mod_pms = ();
+ find({ no_chdir=>1, wanted => \&libcopy }, $mlib);
+
+ sub libcopy {
+ return unless /\.pm6?|\.pod/;
+ my $source = $File::Find::name;
+ my $target = $source;
+ $target =~ s/\Q$mlib\E/$perl6lib/;
+ print "$source => $target\n";
+ mkpath dirname($target);
+ copy($source, $target) or die "copy failed: $!\n";
+ push @mod_pms, $target if $target =~ /\.pm6?/;
+ }
+
+ my %usages_of;
+ my @modules;
+ my %module_to_path;
+ for my $module_file (@mod_pms) {
+ open(my $fh, '<', $module_file) or die $!;
+ my $module = path_to_module_name($module_file);
+ push @modules, $module;
+ $module_to_path{$module} = $module_file;
+ $usages_of{$module} = [];
+ while (<$fh>) {
+ if (/^\s* (?:use|need) \s+ (\w+ (?: :: \w+)*)/x and my $used = $1) {
+ next if $used eq 'v6';
+ next if $used eq 'MONKEY_TYPING';
+
+ push @{$usages_of{$module}}, $used;
+ }
+ }
+ }
+
+ my @order = topo_sort(\@modules, \%usages_of);
+ my @sources = map { $module_to_path{$_} } @order;
+ push @pmfiles, @sources;
+}
+
+# Internally, we treat the module names as module names, '::' and all.
+# But since they're really files externally, they have to be converted
+# from paths to module names, and back again.
+
+sub path_to_module_name {
+ $_ = shift;
+ s/^.+\blib\///;
+ s/^.+\blib6\///;
+ s/\.pm6?$//;
+ s/\//::/g;
+ $_;
+}
+
+chdir 'rakudo';
+foreach my $pm (@pmfiles) {
+ my $out = $pm;
+ $out =~ s/\.pm6?$/.pir/;
+ my @cmd = ($perl6bin, '--target=pir', "--output=$out", $pm);
+ print join(' ', @cmd), "\n";
+ system(@cmd);
+}
+
+
+# According to "Introduction to Algorithms" by Cormen et al., topological
+# sort is just a depth-first search of a graph where you pay attention to
+# the order in which you get done with a dfs-visit() for each node.
+
+sub topo_sort {
+ my ($modules, $dependencies) = @_;
+ my @modules = @$modules;
+ my @order;
+ my %color_of = map { $_ => 'not yet visited' } @modules;
+
+ for my $module (@modules) {
+ if ($color_of{$module} eq 'not yet visited') {
+ dfs_visit($module, \%color_of, $dependencies, \@order);
+ }
+ }
+ return @order;
+}
+
+sub dfs_visit {
+ my $module = shift;
+ my $color_of = shift;
+ my $dependencies = shift;
+ my $order = shift;
+ $color_of->{$module} = 'visited';
+ for my $used (@{$dependencies->{$module}}) {
+ $color_of->{$used} ||= '';
+ if ($color_of->{$used} eq 'not yet visited') {
+ dfs_visit($used, $color_of, $dependencies, $order);
+ }
+ }
+ push @$order, $module;
+}