Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
tree: b20d985641
Fetching contributors…

Cannot retrieve contributors at this time

executable file 206 lines (164 sloc) 5.559 kb
#!/usr/bin/env perl6
# This is the template for the entire generated Makefile.
sub makefile_template() {
return q{
.PHONY: all build test install clean distclean purge
PERL6 = $binary
PREFIX = ~/.perl6
BLIB = blib
P6LIB = $(PWD)/$(BLIB)/lib:$(PWD)/lib:$(PERL6LIB)
$sources
$scripts
PIRS = $(patsubst %.pm6,%.pir,$(SOURCES:%.pm=%.pir))
BLIB_PIRS = $(PIRS:%=$(BLIB)/%)
BLIB_PMS = $(SOURCES:%=$(BLIB)/%)
INSTALL_SOURCES = $(SOURCES:%=$(PREFIX)/%)
INSTALL_SCRIPTS = $(SCRIPTS:%=$(PREFIX)/%)
INSTALL_PIRS = $(PIRS:%=$(PREFIX)/%)
TESTS = $(shell if [ -d 't' ]; then find t -name '*.t'; fi)
all:: build
build:: $(BLIB_PIRS) $(BLIB_PMS)
$(BLIB)/%.pm:: %.pm
mkdir -p `dirname '$@'`
cp $< $@
$(BLIB)/%.pm6:: %.pm6
mkdir -p `dirname '$@'`
cp $< $@
$(BLIB)/%.pir:: %.pm
mkdir -p `dirname '$@'`
env PERL6LIB=$(P6LIB) $(PERL6) --target=pir --output=$@ $<
$(BLIB)/%.pir:: %.pm6
mkdir -p `dirname '$@'`
env PERL6LIB=$(P6LIB) $(PERL6) --target=pir --output=$@ $<
test:: build
env PERL6LIB=$(P6LIB) prove -e '$(PERL6)' -r t/
loudtest:: build
env PERL6LIB=$(P6LIB) prove -ve '$(PERL6)' -r t/
timetest:: build
env PERL6LIB=$(P6LIB) PERL6_TEST_TIMES=1 prove -ve '$(PERL6)' -r t/
$(TESTS):: build
env PERL6LIB=$(P6LIB) prove -v -e '$(PERL6)' -r $@
install:: build $(INSTALL_SOURCES) $(INSTALL_PIRS) $(INSTALL_SCRIPTS)
$(PREFIX)/%.pm:: %.pm
mkdir -p `dirname '$@'`
install $< $@
$(PREFIX)/%.pm6:: %.pm6
mkdir -p `dirname '$@'`
install $< $@
$(PREFIX)/%.pir:: blib/%.pir
mkdir -p `dirname '$@'`
install $< $@
$(PREFIX)/bin/%:: bin/%
mkdir -p `dirname '$@'`
install $< $@
clean::
rm -fr $(BLIB)
distclean purge:: clean
rm -r Makefile
}
}
sub MAIN($filename = 'Makefile', Bool :$alpha) {
my $binary = $alpha ?? 'alpha' !! 'perl6';
if $alpha {
note "Using 'alpha' as the Perl 6 binary. Please upgrade your code.";
}
my $sources = get_sources();
my $scripts = get_scripts();
my $makefile = $filename eq '-' ?? $*OUT !! open $filename, :w;
$makefile.print(
makefile_template()\
.subst(/^\n/, '')\
.subst('$binary', $binary)\
.subst('$sources', $sources)\
.subst('$scripts', $scripts)
);
$makefile.close;
}
sub get_scripts() {
my $ret = 'SCRIPTS=';
if 'bin'.IO ~~ :d {
$ret ~= qx[echo bin/*].chomp;
}
return $ret;
}
sub get_sources() {
return 'SOURCES=' unless 'lib/'.IO ~~ :d || 'lib6/'.IO ~~ :d;
# The grep is needed because 'find' prints a final newline, so there'll be an
# empty-string element at the end of the list.
my @module-files;
if 'lib/'.IO ~~ :d {
@module-files.push: grep { $_ },
split "\n",
qx[find lib -name \*.pm -or -name \*.pm6];
}
if 'lib6/'.IO ~~ :d {
@module-files.push: grep { $_ },
split "\n",
qx[find lib6 -name \*.pm -or -name \*.pm6];
}
# To know the best order of compilation, we build a dependency graph of
# all the modules in lib/. %usages_of ends up containing a graph, with
# the keys (containing names modules) being nodes, and the values
# (containing arrays of names) denoting directed edges.
my @modules = map { path-to-module-name($_) }, @module-files;
my %module-to-path = @modules Z=> @module-files;
my %usages_of;
for @module-files -> $module-file {
my $fh = open($module-file, :r);
my $module = path-to-module-name($module-file);
%usages_of{$module} = [];
for $fh.lines() {
if /^\s* 'use' \s+ (\w+ ['::' \w+]*)/ && $0 -> $used {
next if $used eq 'v6';
next if $used eq 'MONKEY_TYPING';
%usages_of{$module}.push(~$used);
}
}
}
my @order = topo-sort(@modules, %usages_of);
# The intended effect of the below loop is to put as many module paths on
# each line as possible, breaking when necessary, and indenting nicely.
my @sources = map { %module-to-path{$_} }, @order;
my $sources = 'SOURCES=';
my $line-length = 0;
for @sources -> $source {
$line-length += $source.chars + 1;
if $line-length > 65 {
# SOURCES=
$sources ~= "\\\n ";
$line-length = $source.chars + 1;
}
$sources ~= $source ~ ' ';
}
$sources.=trim-trailing;
return $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($path) {
$path.subst(/^'lib/'/, '').subst(/^'lib6/'/, '').subst(/\.pm6?$/, '').subst('/', '::', :g);
}
# 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(@modules, %dependencies) {
my @order;
my %color_of = @modules X=> 'not yet visited';
sub dfs-visit($module) {
%color_of{$module} = 'visited';
for %dependencies{$module}.list -> $used {
if (%color_of{$used} // '') eq 'not yet visited' {
dfs-visit($used);
}
}
push @order, $module;
}
for @modules -> $module {
if %color_of{$module} eq 'not yet visited' {
dfs-visit($module);
}
}
@order;
}
# vim: ft=perl6
Jump to Line
Something went wrong with that request. Please try again.