Skip to content

Instantly share code, notes, and snippets.

@gerdr
Created June 7, 2012 20:14
Show Gist options
  • Save gerdr/2891292 to your computer and use it in GitHub Desktop.
Save gerdr/2891292 to your computer and use it in GitHub Desktop.
ufo with dwimmy dependency generation
#!/usr/bin/env perl6
sub dirwalk($dir = '.', Mu :$d = none(<. ..>), Mu :$f = *,
:&dx = -> $ {}, :&fx = -> $ {}) {
for dir($dir, :test(*)) -> $name {
given "$dir/$name" {
when .IO.f {
&fx.($_) if $f.ACCEPTS($name)
}
when .IO.d {
dirwalk($_, :$d, :$f, :&dx, :&fx) if $d.ACCEPTS($name)
}
}
}
&dx.($dir);
}
sub mkdir-p($file, Bool :$f = False) {
my @parents = $file.split('/');
@parents.pop if $f;
my $path = '';
for @parents {
$path ~= "$_/";
mkdir($path) unless $path.IO.d;
}
}
sub rmdir-r($path) {
dirwalk($path, :dx(&rmdir), :fx(&unlink))
}
sub compile($src, $dest) {
use lib <blib/lib blib/lib6>;
my $comp := pir::compreg__Ps('perl6');
my $args := nqp::list;
nqp::push($args, $?FILE);
nqp::push($args, '--target=pir');
nqp::push($args, "--output=$dest");
nqp::push($args, $src);
$comp.command_line($args, :encoding<utf8>);
}
sub parse-makefile($file) {
gather for $file.IO.lines {
next unless /'.pir:'/;
my ($target, @deps) = .comb(/[<![:]>\S]+/);
take $target => @deps;
}
}
sub parse-pm-file($file) {
gather for $file.IO.lines {
take ~$0 if /^\s* ['use'|'need'] \s+ (\w+ ['::' \w+]*)/;
}
}
sub pir-from-pm($file) {
'blib/' ~ $file.subst(/\.pm6?$/, '.pir');
}
sub name-from-pm($file) {
$file.subst(/^lib6?\/|\.pm6?$/, '', :g).subst('/', '::', :g);
}
multi MAIN() {
my $last-run = 'Makefile'.IO.f ?? 'Makefile'.IO.modified !! -Inf;
my @modules = gather <lib lib6>.grep(*.IO.d).map({
dirwalk($_, :f(/\.pm6?$/), :fx(&take))
});
my %targets = @modules.map(&name-from-pm) Z=> @modules.map(&pir-from-pm);
my %deps = parse-makefile('Makefile') if 'Makefile'.IO.f;
for @modules {
next if $last-run > .IO.modified;
say "ufo: parsing $_";
my $name = name-from-pm($_);
my $target = %targets{$name};
my @deps = "blib/$_",
parse-pm-file($_).grep(* ne $name).map({ %targets{$_} // Nil });
%deps{$target} = @deps;
}
my $ufo = "$*EXECUTABLE_NAME $?FILE";
given open('Makefile', :w) {
LEAVE .close;
.say(
"build: {%targets.values}
clean:
$ufo rmdir blib
realclean: clean
$ufo rm Makefile
Makefile: {@modules}
$ufo
");
for @modules -> $file {
.say(
"blib/$file: $file
$ufo cp $file blib/$file
");
}
for %deps.kv -> $target, @deps {
.say(
"$target: {@deps}
$ufo compile {@deps[0]} $target
");
}
}
}
multi MAIN('rm', *@files) {
unlink($_) for @files.grep(*.IO.e);
}
multi MAIN('rmdir', *@dirs) {
rmdir-r($_) for @dirs.grep(*.IO.e);
}
multi MAIN('compile', $src, $dest) {
mkdir-p($dest, :f);
compile($src, $dest);
}
multi MAIN('cp', $src, $dest) {
mkdir-p($dest, :f);
$src.IO.copy($dest);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment