Skip to content
This repository was archived by the owner on Jun 15, 2023. It is now read-only.

Commit 717b7b4

Browse files
committed
v1.7.2
2 parents b49b0fc + b0cce09 commit 717b7b4

15 files changed

+201
-69
lines changed

configure.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ def uses_usr_local(self):
9898
return self._platform in ('freebsd', 'openbsd', 'bitrig')
9999

100100
def supports_ppoll(self):
101-
return self._platform in ('linux', 'openbsd', 'bitrig')
101+
return self._platform in ('freebsd', 'linux', 'openbsd', 'bitrig')
102102

103103
def supports_ninja_browse(self):
104104
return (not self.is_windows()

misc/measure.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,16 @@
1717
"""measure the runtime of a command by repeatedly running it.
1818
"""
1919

20+
from __future__ import print_function
21+
2022
import time
2123
import subprocess
2224
import sys
2325

2426
devnull = open('/dev/null', 'w')
2527

2628
def run(cmd, repeat=10):
27-
print 'sampling:',
29+
print('sampling:', end=' ')
2830
sys.stdout.flush()
2931

3032
samples = []
@@ -33,10 +35,10 @@ def run(cmd, repeat=10):
3335
subprocess.call(cmd, stdout=devnull, stderr=devnull)
3436
end = time.time()
3537
dt = (end - start) * 1000
36-
print '%dms' % int(dt),
38+
print('%dms' % int(dt), end=' ')
3739
sys.stdout.flush()
3840
samples.append(dt)
39-
print
41+
print()
4042

4143
# We're interested in the 'pure' runtime of the code, which is
4244
# conceptually the smallest time we'd see if we ran it enough times
@@ -45,10 +47,10 @@ def run(cmd, repeat=10):
4547
# Also print how varied the outputs were in an attempt to make it
4648
# more obvious if something has gone terribly wrong.
4749
err = sum(s - best for s in samples) / float(len(samples))
48-
print 'estimate: %dms (mean err %.1fms)' % (best, err)
50+
print('estimate: %dms (mean err %.1fms)' % (best, err))
4951

5052
if __name__ == '__main__':
5153
if len(sys.argv) < 2:
52-
print 'usage: measure.py command args...'
54+
print('usage: measure.py command args...')
5355
sys.exit(1)
5456
run(cmd=sys.argv[1:])

misc/write_fake_manifests.py

+71-18
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,10 @@ def moar(avg_options, p_suffix):
5050

5151

5252
class GenRandom(object):
53-
def __init__(self):
53+
def __init__(self, src_dir):
5454
self.seen_names = set([None])
5555
self.seen_defines = set([None])
56+
self.src_dir = src_dir
5657

5758
def _unique_string(self, seen, avg_options=1.3, p_suffix=0.1):
5859
s = None
@@ -76,7 +77,7 @@ def path(self):
7677

7778
def src_obj_pairs(self, path, name):
7879
num_sources = paretoint(55, alpha=2) + 1
79-
return [(os.path.join('..', '..', path, s + '.cc'),
80+
return [(os.path.join(self.src_dir, path, s + '.cc'),
8081
os.path.join('obj', path, '%s.%s.o' % (name, s)))
8182
for s in self._n_unique_strings(num_sources)]
8283

@@ -103,12 +104,8 @@ def __init__(self, gen, kind):
103104
self.kind = kind
104105
self.has_compile_depends = random.random() < 0.4
105106

106-
@property
107-
def includes(self):
108-
return ['-I' + dep.dir_path for dep in self.deps]
109107

110-
111-
def write_target_ninja(ninja, target):
108+
def write_target_ninja(ninja, target, src_dir):
112109
compile_depends = None
113110
if target.has_compile_depends:
114111
compile_depends = os.path.join(
@@ -117,8 +114,7 @@ def write_target_ninja(ninja, target):
117114
ninja.newline()
118115

119116
ninja.variable('defines', target.defines)
120-
if target.deps:
121-
ninja.variable('includes', target.includes)
117+
ninja.variable('includes', '-I' + src_dir)
122118
ninja.variable('cflags', ['-Wall', '-fno-rtti', '-fno-exceptions'])
123119
ninja.newline()
124120

@@ -129,17 +125,63 @@ def write_target_ninja(ninja, target):
129125
deps = [dep.output for dep in target.deps]
130126
libs = [dep.output for dep in target.deps if dep.kind == LIB]
131127
if target.kind == EXE:
132-
ninja.variable('ldflags', '-Wl,pie')
133128
ninja.variable('libs', libs)
129+
if sys.platform == "darwin":
130+
ninja.variable('ldflags', '-Wl,-pie')
134131
link = { LIB: 'alink', EXE: 'link'}[target.kind]
135132
ninja.build(target.output, link, [obj for _, obj in target.src_obj_pairs],
136133
implicit=deps)
137134

138135

136+
def write_sources(target, root_dir):
137+
need_main = target.kind == EXE
138+
139+
includes = []
140+
141+
# Include siblings.
142+
for cc_filename, _ in target.src_obj_pairs:
143+
h_filename = os.path.basename(os.path.splitext(cc_filename)[0] + '.h')
144+
includes.append(h_filename)
145+
146+
# Include deps.
147+
for dep in target.deps:
148+
for cc_filename, _ in dep.src_obj_pairs:
149+
h_filename = os.path.basename(
150+
os.path.splitext(cc_filename)[0] + '.h')
151+
includes.append("%s/%s" % (dep.dir_path, h_filename))
152+
153+
for cc_filename, _ in target.src_obj_pairs:
154+
cc_path = os.path.join(root_dir, cc_filename)
155+
h_path = os.path.splitext(cc_path)[0] + '.h'
156+
namespace = os.path.basename(target.dir_path)
157+
class_ = os.path.splitext(os.path.basename(cc_filename))[0]
158+
try:
159+
os.makedirs(os.path.dirname(cc_path))
160+
except OSError:
161+
pass
162+
163+
with open(h_path, 'w') as f:
164+
f.write('namespace %s { struct %s { %s(); }; }' % (namespace,
165+
class_, class_))
166+
with open(cc_path, 'w') as f:
167+
for include in includes:
168+
f.write('#include "%s"\n' % include)
169+
f.write('\n')
170+
f.write('namespace %s { %s::%s() {} }' % (namespace,
171+
class_, class_))
172+
173+
if need_main:
174+
f.write('int main(int argc, char **argv) {}\n')
175+
need_main = False
176+
139177
def write_master_ninja(master_ninja, targets):
140178
"""Writes master build.ninja file, referencing all given subninjas."""
141179
master_ninja.variable('cxx', 'c++')
142180
master_ninja.variable('ld', '$cxx')
181+
if sys.platform == 'darwin':
182+
master_ninja.variable('alink', 'libtool -static')
183+
else:
184+
master_ninja.variable('alink', 'ar rcs')
143185
master_ninja.newline()
144186

145187
master_ninja.pool('link_pool', depth=4)
@@ -148,8 +190,8 @@ def write_master_ninja(master_ninja, targets):
148190
master_ninja.rule('cxx', description='CXX $out',
149191
command='$cxx -MMD -MF $out.d $defines $includes $cflags -c $in -o $out',
150192
depfile='$out.d', deps='gcc')
151-
master_ninja.rule('alink', description='LIBTOOL-STATIC $out',
152-
command='rm -f $out && libtool -static -o $out $in')
193+
master_ninja.rule('alink', description='ARCHIVE $out',
194+
command='rm -f $out && $alink -o $out $in')
153195
master_ninja.rule('link', description='LINK $out', pool='link_pool',
154196
command='$ld $ldflags -o $out $in $libs')
155197
master_ninja.rule('stamp', description='STAMP $out', command='touch $out')
@@ -181,9 +223,8 @@ def FileWriter(path):
181223
f.close()
182224

183225

184-
def random_targets():
185-
num_targets = 1500
186-
gen = GenRandom()
226+
def random_targets(num_targets, src_dir):
227+
gen = GenRandom(src_dir)
187228

188229
# N-1 static libraries, and 1 executable depending on all of them.
189230
targets = [Target(gen, LIB) for i in xrange(num_targets - 1)]
@@ -199,16 +240,28 @@ def random_targets():
199240

200241
def main():
201242
parser = argparse.ArgumentParser()
243+
parser.add_argument('-s', '--sources', nargs="?", const="src",
244+
help='write sources to directory (relative to output directory)')
245+
parser.add_argument('-t', '--targets', type=int, default=1500,
246+
help='number of targets (default: 1500)')
247+
parser.add_argument('-S', '--seed', type=int, help='random seed',
248+
default=12345)
202249
parser.add_argument('outdir', help='output directory')
203250
args = parser.parse_args()
204251
root_dir = args.outdir
205252

206-
random.seed(12345)
253+
random.seed(args.seed)
207254

208-
targets = random_targets()
255+
do_write_sources = args.sources is not None
256+
src_dir = args.sources if do_write_sources else "src"
257+
258+
targets = random_targets(args.targets, src_dir)
209259
for target in targets:
210260
with FileWriter(os.path.join(root_dir, target.ninja_file_path)) as n:
211-
write_target_ninja(n, target)
261+
write_target_ninja(n, target, src_dir)
262+
263+
if do_write_sources:
264+
write_sources(target, root_dir)
212265

213266
with FileWriter(os.path.join(root_dir, 'build.ninja')) as master_ninja:
214267
master_ninja.width = 120

src/browse.py

+10-6
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
except ImportError:
2828
import BaseHTTPServer as httpserver
2929
import argparse
30+
import cgi
3031
import os
3132
import socket
3233
import subprocess
@@ -58,6 +59,9 @@ def match_strip(line, prefix):
5859
return (False, line)
5960
return (True, line[len(prefix):])
6061

62+
def html_escape(text):
63+
return cgi.escape(text, quote=True)
64+
6165
def parse(text):
6266
lines = iter(text.split('\n'))
6367

@@ -124,27 +128,27 @@ def create_page(body):
124128
''' + body
125129

126130
def generate_html(node):
127-
document = ['<h1><tt>%s</tt></h1>' % node.target]
131+
document = ['<h1><tt>%s</tt></h1>' % html_escape(node.target)]
128132

129133
if node.inputs:
130134
document.append('<h2>target is built using rule <tt>%s</tt> of</h2>' %
131-
node.rule)
135+
html_escape(node.rule))
132136
if len(node.inputs) > 0:
133137
document.append('<div class=filelist>')
134138
for input, type in sorted(node.inputs):
135139
extra = ''
136140
if type:
137-
extra = ' (%s)' % type
141+
extra = ' (%s)' % html_escape(type)
138142
document.append('<tt><a href="?%s">%s</a>%s</tt><br>' %
139-
(input, input, extra))
143+
(html_escape(input), html_escape(input), extra))
140144
document.append('</div>')
141145

142146
if node.outputs:
143147
document.append('<h2>dependent edges build:</h2>')
144148
document.append('<div class=filelist>')
145149
for output in sorted(node.outputs):
146150
document.append('<tt><a href="?%s">%s</a></tt><br>' %
147-
(output, output))
151+
(html_escape(output), html_escape(output)))
148152
document.append('</div>')
149153

150154
return '\n'.join(document)
@@ -177,7 +181,7 @@ def do_GET(self):
177181
page_body = generate_html(parse(ninja_output.strip()))
178182
else:
179183
# Relay ninja's error message.
180-
page_body = '<h1><tt>%s</tt></h1>' % ninja_error
184+
page_body = '<h1><tt>%s</tt></h1>' % html_escape(ninja_error)
181185

182186
self.send_response(200)
183187
self.end_headers()

src/build.cc

+23-13
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ void BuildStatus::BuildEdgeStarted(Edge* edge) {
9797
++started_edges_;
9898

9999
if (edge->use_console() || printer_.is_smart_terminal())
100-
PrintStatus(edge);
100+
PrintStatus(edge, kEdgeStarted);
101101

102102
if (edge->use_console())
103103
printer_.SetConsoleLocked(true);
@@ -109,6 +109,7 @@ void BuildStatus::BuildEdgeFinished(Edge* edge,
109109
int* start_time,
110110
int* end_time) {
111111
int64_t now = GetTimeMillis();
112+
112113
++finished_edges_;
113114

114115
RunningEdgeMap::iterator i = running_edges_.find(edge);
@@ -123,7 +124,7 @@ void BuildStatus::BuildEdgeFinished(Edge* edge,
123124
return;
124125

125126
if (!edge->use_console())
126-
PrintStatus(edge);
127+
PrintStatus(edge, kEdgeFinished);
127128

128129
// Print the command that is spewing before printing its output.
129130
if (!success) {
@@ -158,13 +159,18 @@ void BuildStatus::BuildEdgeFinished(Edge* edge,
158159
}
159160
}
160161

162+
void BuildStatus::BuildStarted() {
163+
overall_rate_.Restart();
164+
current_rate_.Restart();
165+
}
166+
161167
void BuildStatus::BuildFinished() {
162168
printer_.SetConsoleLocked(false);
163169
printer_.PrintOnNewLine("");
164170
}
165171

166172
string BuildStatus::FormatProgressStatus(
167-
const char* progress_status_format) const {
173+
const char* progress_status_format, EdgeStatus status) const {
168174
string out;
169175
char buf[32];
170176
int percent;
@@ -189,10 +195,15 @@ string BuildStatus::FormatProgressStatus(
189195
break;
190196

191197
// Running edges.
192-
case 'r':
193-
snprintf(buf, sizeof(buf), "%d", started_edges_ - finished_edges_);
198+
case 'r': {
199+
int running_edges = started_edges_ - finished_edges_;
200+
// count the edge that just finished as a running edge
201+
if (status == kEdgeFinished)
202+
running_edges++;
203+
snprintf(buf, sizeof(buf), "%d", running_edges);
194204
out += buf;
195205
break;
206+
}
196207

197208
// Unstarted edges.
198209
case 'u':
@@ -209,14 +220,14 @@ string BuildStatus::FormatProgressStatus(
209220
// Overall finished edges per second.
210221
case 'o':
211222
overall_rate_.UpdateRate(finished_edges_);
212-
snprinfRate(overall_rate_.rate(), buf, "%.1f");
223+
SnprintfRate(overall_rate_.rate(), buf, "%.1f");
213224
out += buf;
214225
break;
215226

216227
// Current rate, average over the last '-j' jobs.
217228
case 'c':
218229
current_rate_.UpdateRate(finished_edges_);
219-
snprinfRate(current_rate_.rate(), buf, "%.1f");
230+
SnprintfRate(current_rate_.rate(), buf, "%.1f");
220231
out += buf;
221232
break;
222233

@@ -246,7 +257,7 @@ string BuildStatus::FormatProgressStatus(
246257
return out;
247258
}
248259

249-
void BuildStatus::PrintStatus(Edge* edge) {
260+
void BuildStatus::PrintStatus(Edge* edge, EdgeStatus status) {
250261
if (config_.verbosity == BuildConfig::QUIET)
251262
return;
252263

@@ -256,11 +267,7 @@ void BuildStatus::PrintStatus(Edge* edge) {
256267
if (to_print.empty() || force_full_command)
257268
to_print = edge->GetBinding("command");
258269

259-
if (finished_edges_ == 0) {
260-
overall_rate_.Restart();
261-
current_rate_.Restart();
262-
}
263-
to_print = FormatProgressStatus(progress_status_format_) + to_print;
270+
to_print = FormatProgressStatus(progress_status_format_, status) + to_print;
264271

265272
printer_.Print(to_print,
266273
force_full_command ? LinePrinter::FULL : LinePrinter::ELIDE);
@@ -643,6 +650,9 @@ bool Builder::Build(string* err) {
643650
command_runner_.reset(new RealCommandRunner(config_));
644651
}
645652

653+
// We are about to start the build process.
654+
status_->BuildStarted();
655+
646656
// This main loop runs the entire build process.
647657
// It is structured like this:
648658
// First, we attempt to start as many commands as allowed by the

0 commit comments

Comments
 (0)