Skip to content
Newer
Older
100755 208 lines (188 sloc) 4.82 KB
549dc38 @RaimoNiskanen Replace Makefile with build.pl
RaimoNiskanen authored
1 #! /usr/bin/perl
2 ##
3 ## Build script, since make is sooo unportable.
4 ##
5 ## Copyright 2010: Erlang/OTP, Raimo Niskanen
6 ## This document has been placed in the public domain.
7 #
8 #
9 # $0 Build all outdated targets
10 # $0 -a | --all Force build of all targets
11 # $0 -c | --clean Remove all targets
12 # $0 [--] Target [Target2 ...] Force build of only target(s)
13
14 use strict;
15
16 my $mk = $0;
17 my @perl = ("perl", "-w");
18 my $utf8 = '-CSD'; # Perl UTF-8 command line switch
19 my $md = "md/Markdown.pl";
20 my $ix = "eep-index.pl";
21 my $pre = "eep-pre.pl";
22
23 my $eeps_dir = 'eeps/';
24 my $src_ext = '.md';
25 my $dst_ext = '.html';
26 my @basenames =
27 &dir_files($eeps_dir, sub {s/^(eep-\d+)$src_ext$/$1/});
b129679 @RaimoNiskanen Fix build.pl to make index depend on all sources
RaimoNiskanen authored
28 my @sources = @basenames;
29 foreach (@sources) { $_ .= $src_ext }
13a1fcc Better order of build commands in rules
Raimo Niskanen authored
30 my $ix_base = $eeps_dir.'eep-0000';
549dc38 @RaimoNiskanen Replace Makefile with build.pl
RaimoNiskanen authored
31
32 my %rules =
13a1fcc Better order of build commands in rules
Raimo Niskanen authored
33 (# 'target' => [['build commands',...], 'dependencies',...]
34
35 "README.html" =>
36 [[@perl, $md, "README.md", \&redirect, "README.html"],
37 "README.md", $mk, $md],
38
39 $ix_base.$dst_ext =>
40 [[@perl, $utf8, $ix, $ix_base.$src_ext, \&pipe,
41 @perl, $utf8, $pre, \&pipe,
42 @perl, $md, \&redirect, $ix_base.$dst_ext],
b129679 @RaimoNiskanen Fix build.pl to make index depend on all sources
RaimoNiskanen authored
43 @sources, $mk, $ix, $pre, $md],
549dc38 @RaimoNiskanen Replace Makefile with build.pl
RaimoNiskanen authored
44 );
45 # Add rules for wildcard targets
46 foreach (@basenames) {
47 my $src = $_.$src_ext;
48 my $dst = $_.$dst_ext;
49 unless (defined $rules{$dst}) {
13a1fcc Better order of build commands in rules
Raimo Niskanen authored
50 $rules{$dst} =
51 [[@perl, $utf8, $pre, $src, \&pipe,
52 @perl, $md, \&redirect, $dst],
53 $src, $mk, $pre, $md];
549dc38 @RaimoNiskanen Replace Makefile with build.pl
RaimoNiskanen authored
54 }
55 }
56
57
58
13a1fcc Better order of build commands in rules
Raimo Niskanen authored
59 # Find out what to do
549dc38 @RaimoNiskanen Replace Makefile with build.pl
RaimoNiskanen authored
60 my %mtime;
61 my %targets;
62 if (defined ($_ = $ARGV[0])) {
13a1fcc Better order of build commands in rules
Raimo Niskanen authored
63 # Sort out command line arguments
64 if (/^(?:-a|--all)$/) {
549dc38 @RaimoNiskanen Replace Makefile with build.pl
RaimoNiskanen authored
65 foreach (keys %rules) { # force build all
66 $targets{$_} = 1;
67 }
13a1fcc Better order of build commands in rules
Raimo Niskanen authored
68 } elsif (/^(?:-c|--clean)$/) {
549dc38 @RaimoNiskanen Replace Makefile with build.pl
RaimoNiskanen authored
69 my @files = keys %rules;
70 print "rm @files\n";
71 unlink @files;
72 exit 0;
73 } else {
74 shift if /^--$/; # only targets after this
75 foreach (@ARGV) {
13a1fcc Better order of build commands in rules
Raimo Niskanen authored
76 defined $rules{$_} or die "Unknown target: $_";
549dc38 @RaimoNiskanen Replace Makefile with build.pl
RaimoNiskanen authored
77 $targets{$_} = 1; # force build
78 }
79 foreach (keys %rules) { # build only forced
80 delete $rules{$_} unless $targets{$_};
81 }
82 }
83 } else {
13a1fcc Better order of build commands in rules
Raimo Niskanen authored
84 # Build outdated targets
549dc38 @RaimoNiskanen Replace Makefile with build.pl
RaimoNiskanen authored
85 &foreach_rules(sub {
86 shift;
87 foreach (@_) {
13a1fcc Better order of build commands in rules
Raimo Niskanen authored
88 unless (defined $mtime{$_}) {
89 if (-f) {
90 $mtime{$_} = (stat _)[9];
91 } else {
92 $mtime{$_} = ''; # No such file
93 }
549dc38 @RaimoNiskanen Replace Makefile with build.pl
RaimoNiskanen authored
94 }
95 }
96 });
97 }
98
13a1fcc Better order of build commands in rules
Raimo Niskanen authored
99 # Call build function for all to rebuild
549dc38 @RaimoNiskanen Replace Makefile with build.pl
RaimoNiskanen authored
100 &foreach_rules(sub {
101 my ($build, $target, @deps) = @_;
102 my @build = @{$build};
13a1fcc Better order of build commands in rules
Raimo Niskanen authored
103 if ($targets{$target}) {
104 #print "Target $target forced\n";
549dc38 @RaimoNiskanen Replace Makefile with build.pl
RaimoNiskanen authored
105 &build(@build);
106 return;
107 }
108 my $target_mtime = $mtime{$target};
13a1fcc Better order of build commands in rules
Raimo Niskanen authored
109 unless ($target_mtime) {
110 #print "Target $target does not exist\n";
111 &build(@build);
112 return;
113 }
114 foreach (@deps) {
115 $mtime{$_} or die "Missing dependency: $_";
116 if ($mtime{$_} >= $target_mtime) {
117 #print "Target $target outdated vs $_\n";
549dc38 @RaimoNiskanen Replace Makefile with build.pl
RaimoNiskanen authored
118 &build(@build);
119 return;
120 }
121 }
122 });
123
124 exit 0;
125
126
127
13a1fcc Better order of build commands in rules
Raimo Niskanen authored
128 # Toplevel per rule build, wait for last pid
549dc38 @RaimoNiskanen Replace Makefile with build.pl
RaimoNiskanen authored
129 sub build {
13a1fcc Better order of build commands in rules
Raimo Niskanen authored
130 ##print "build <@_>\n";
131 open SAVEOUT, ">&STDOUT" or die "Can't save STDOUT: $!";
132 my $last_pid = &recurse;
549dc38 @RaimoNiskanen Replace Makefile with build.pl
RaimoNiskanen authored
133 close STDOUT;
134 waitpid $last_pid, 0;
13a1fcc Better order of build commands in rules
Raimo Niskanen authored
135 open STDOUT, ">&SAVEOUT" or die "Can't restore STDOUT: $!";
549dc38 @RaimoNiskanen Replace Makefile with build.pl
RaimoNiskanen authored
136 }
137
13a1fcc Better order of build commands in rules
Raimo Niskanen authored
138 # Pipe command to the next
549dc38 @RaimoNiskanen Replace Makefile with build.pl
RaimoNiskanen authored
139 sub pipe {
13a1fcc Better order of build commands in rules
Raimo Niskanen authored
140 ##print "pipe <@_>\n";
141 my @cmd = @{+shift};
142 print "@cmd | ";
143 my $call_pid = &recurse;
144 unless (my $pid = open STDOUT, '|-') {
145 defined $pid or die "Can't fork: $!";
146 exec {$cmd[0]} @cmd or die "Can't exec @cmd: $!";
549dc38 @RaimoNiskanen Replace Makefile with build.pl
RaimoNiskanen authored
147 }
13a1fcc Better order of build commands in rules
Raimo Niskanen authored
148 return $call_pid;
549dc38 @RaimoNiskanen Replace Makefile with build.pl
RaimoNiskanen authored
149 }
150
13a1fcc Better order of build commands in rules
Raimo Niskanen authored
151 # Redirect command to destination file.
152 # Next item is a filename, not command.
549dc38 @RaimoNiskanen Replace Makefile with build.pl
RaimoNiskanen authored
153 sub redirect {
13a1fcc Better order of build commands in rules
Raimo Niskanen authored
154 ##print "redirect <@_>\n";
155 my @cmd = @{+shift};
549dc38 @RaimoNiskanen Replace Makefile with build.pl
RaimoNiskanen authored
156 my $dst = shift;
13a1fcc Better order of build commands in rules
Raimo Niskanen authored
157 print "@cmd > $dst\n";
549dc38 @RaimoNiskanen Replace Makefile with build.pl
RaimoNiskanen authored
158 my $pid;
159 unless ($pid = open STDOUT, '|-') {
13a1fcc Better order of build commands in rules
Raimo Niskanen authored
160 defined $pid or die "Can't fork: $!";
161 open STDOUT, ">$dst" or die "Can't open > $dst: $!";
162 exec {$cmd[0]} @cmd or die "Can't exec @cmd: $!";
549dc38 @RaimoNiskanen Replace Makefile with build.pl
RaimoNiskanen authored
163 }
164 return $pid;
165 }
166
13a1fcc Better order of build commands in rules
Raimo Niskanen authored
167 # Recursion helper, arguments are all remaining commands
168 # Call next command with its arguments as first parameter
169 # and remaing commands as the rest of the parameters.
170 #
171 # &recurse(1, 2, 3, \&call, @commands) ->
172 # return &call([1, 2, 3], @commands)
173 #
174 sub recurse {
175 ##print "recurse <@_>\n";
176 my @call;
177 while (@_) {
178 $_ = shift @_;
179 if ((ref $_) eq 'CODE') {
180 unshift @_, \@call;
181 return &{$_};
182 }
183 push @call, $_;
184 }
185 die "Build spec error - no next command";
186 }
187
549dc38 @RaimoNiskanen Replace Makefile with build.pl
RaimoNiskanen authored
188 # Helper loop subroutine over %rules
189 sub foreach_rules {
190 my ($func) = @_;
191 foreach my $target (sort (keys %rules)) {
192 my ($build, @files) = @{$rules{$target}};
193 &{$func}($build, $target, @files);
194 }
195 }
196
197 # Filename wildcard
198 sub dir_files {
199 my ($dir, $subst) = @_;
200 my @names;
201 opendir D, $dir || die "Can't opendir $dir: $!";
202 while ($_ = readdir(D)) {
13a1fcc Better order of build commands in rules
Raimo Niskanen authored
203 push @names, $dir.$_ if &{$subst}();
549dc38 @RaimoNiskanen Replace Makefile with build.pl
RaimoNiskanen authored
204 }
205 closedir D;
206 return @names;
207 }
Something went wrong with that request. Please try again.