@@ -50,9 +50,10 @@ def moar(avg_options, p_suffix):
50
50
51
51
52
52
class GenRandom (object ):
53
- def __init__ (self ):
53
+ def __init__ (self , src_dir ):
54
54
self .seen_names = set ([None ])
55
55
self .seen_defines = set ([None ])
56
+ self .src_dir = src_dir
56
57
57
58
def _unique_string (self , seen , avg_options = 1.3 , p_suffix = 0.1 ):
58
59
s = None
@@ -76,7 +77,7 @@ def path(self):
76
77
77
78
def src_obj_pairs (self , path , name ):
78
79
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' ),
80
81
os .path .join ('obj' , path , '%s.%s.o' % (name , s )))
81
82
for s in self ._n_unique_strings (num_sources )]
82
83
@@ -103,12 +104,8 @@ def __init__(self, gen, kind):
103
104
self .kind = kind
104
105
self .has_compile_depends = random .random () < 0.4
105
106
106
- @property
107
- def includes (self ):
108
- return ['-I' + dep .dir_path for dep in self .deps ]
109
107
110
-
111
- def write_target_ninja (ninja , target ):
108
+ def write_target_ninja (ninja , target , src_dir ):
112
109
compile_depends = None
113
110
if target .has_compile_depends :
114
111
compile_depends = os .path .join (
@@ -117,8 +114,7 @@ def write_target_ninja(ninja, target):
117
114
ninja .newline ()
118
115
119
116
ninja .variable ('defines' , target .defines )
120
- if target .deps :
121
- ninja .variable ('includes' , target .includes )
117
+ ninja .variable ('includes' , '-I' + src_dir )
122
118
ninja .variable ('cflags' , ['-Wall' , '-fno-rtti' , '-fno-exceptions' ])
123
119
ninja .newline ()
124
120
@@ -129,17 +125,63 @@ def write_target_ninja(ninja, target):
129
125
deps = [dep .output for dep in target .deps ]
130
126
libs = [dep .output for dep in target .deps if dep .kind == LIB ]
131
127
if target .kind == EXE :
132
- ninja .variable ('ldflags' , '-Wl,pie' )
133
128
ninja .variable ('libs' , libs )
129
+ if sys .platform == "darwin" :
130
+ ninja .variable ('ldflags' , '-Wl,-pie' )
134
131
link = { LIB : 'alink' , EXE : 'link' }[target .kind ]
135
132
ninja .build (target .output , link , [obj for _ , obj in target .src_obj_pairs ],
136
133
implicit = deps )
137
134
138
135
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
+
139
177
def write_master_ninja (master_ninja , targets ):
140
178
"""Writes master build.ninja file, referencing all given subninjas."""
141
179
master_ninja .variable ('cxx' , 'c++' )
142
180
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' )
143
185
master_ninja .newline ()
144
186
145
187
master_ninja .pool ('link_pool' , depth = 4 )
@@ -148,8 +190,8 @@ def write_master_ninja(master_ninja, targets):
148
190
master_ninja .rule ('cxx' , description = 'CXX $out' ,
149
191
command = '$cxx -MMD -MF $out.d $defines $includes $cflags -c $in -o $out' ,
150
192
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' )
153
195
master_ninja .rule ('link' , description = 'LINK $out' , pool = 'link_pool' ,
154
196
command = '$ld $ldflags -o $out $in $libs' )
155
197
master_ninja .rule ('stamp' , description = 'STAMP $out' , command = 'touch $out' )
@@ -181,9 +223,8 @@ def FileWriter(path):
181
223
f .close ()
182
224
183
225
184
- def random_targets ():
185
- num_targets = 1500
186
- gen = GenRandom ()
226
+ def random_targets (num_targets , src_dir ):
227
+ gen = GenRandom (src_dir )
187
228
188
229
# N-1 static libraries, and 1 executable depending on all of them.
189
230
targets = [Target (gen , LIB ) for i in xrange (num_targets - 1 )]
@@ -199,16 +240,28 @@ def random_targets():
199
240
200
241
def main ():
201
242
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 )
202
249
parser .add_argument ('outdir' , help = 'output directory' )
203
250
args = parser .parse_args ()
204
251
root_dir = args .outdir
205
252
206
- random .seed (12345 )
253
+ random .seed (args . seed )
207
254
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 )
209
259
for target in targets :
210
260
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 )
212
265
213
266
with FileWriter (os .path .join (root_dir , 'build.ninja' )) as master_ninja :
214
267
master_ninja .width = 120
0 commit comments