summaryrefslogtreecommitdiffstats
path: root/misc
diff options
context:
space:
mode:
authorFrank Benkstein <frank@benkstein.net>2016-06-21 13:04:02 (GMT)
committerFrank Benkstein <frank@benkstein.net>2016-06-23 10:23:23 (GMT)
commit1992ab65adfb796e1c65a1ca0631f31d5cce5eb0 (patch)
treef48eb798296a5343c491ce70cecd54334f4f9922 /misc
parent5739c144354c826b57042ad0968680c272a95856 (diff)
downloadNinja-1992ab65adfb796e1c65a1ca0631f31d5cce5eb0.zip
Ninja-1992ab65adfb796e1c65a1ca0631f31d5cce5eb0.tar.gz
Ninja-1992ab65adfb796e1c65a1ca0631f31d5cce5eb0.tar.bz2
enhance write_fake_manifest.py
Add an option to write_fake_manifest.py to generate sources expected by the manifest. Also slightly adapt command lines to the called commands. Together these changes mean that generated manifest can actually be executed successfully on Linux and OSX. Also add command line options to to change the number of targets being generated and the seed for the random number generator. Example usage: # create build directory in fake/build, sources in fake/src $ python misc/write_fake_manifest.py -s ../src fake/build # execute build in fake/build $ ninja -C fake/build
Diffstat (limited to 'misc')
-rw-r--r--misc/write_fake_manifests.py89
1 files changed, 71 insertions, 18 deletions
diff --git a/misc/write_fake_manifests.py b/misc/write_fake_manifests.py
index ca49535..cec28de 100644
--- a/misc/write_fake_manifests.py
+++ b/misc/write_fake_manifests.py
@@ -50,9 +50,10 @@ def moar(avg_options, p_suffix):
class GenRandom(object):
- def __init__(self):
+ def __init__(self, src_dir):
self.seen_names = set([None])
self.seen_defines = set([None])
+ self.src_dir = src_dir
def _unique_string(self, seen, avg_options=1.3, p_suffix=0.1):
s = None
@@ -76,7 +77,7 @@ class GenRandom(object):
def src_obj_pairs(self, path, name):
num_sources = paretoint(55, alpha=2) + 1
- return [(os.path.join('..', '..', path, s + '.cc'),
+ return [(os.path.join(self.src_dir, path, s + '.cc'),
os.path.join('obj', path, '%s.%s.o' % (name, s)))
for s in self._n_unique_strings(num_sources)]
@@ -103,12 +104,8 @@ class Target(object):
self.kind = kind
self.has_compile_depends = random.random() < 0.4
- @property
- def includes(self):
- return ['-I' + dep.dir_path for dep in self.deps]
-
-def write_target_ninja(ninja, target):
+def write_target_ninja(ninja, target, src_dir):
compile_depends = None
if target.has_compile_depends:
compile_depends = os.path.join(
@@ -117,8 +114,7 @@ def write_target_ninja(ninja, target):
ninja.newline()
ninja.variable('defines', target.defines)
- if target.deps:
- ninja.variable('includes', target.includes)
+ ninja.variable('includes', '-I' + src_dir)
ninja.variable('cflags', ['-Wall', '-fno-rtti', '-fno-exceptions'])
ninja.newline()
@@ -129,17 +125,63 @@ def write_target_ninja(ninja, target):
deps = [dep.output for dep in target.deps]
libs = [dep.output for dep in target.deps if dep.kind == LIB]
if target.kind == EXE:
- ninja.variable('ldflags', '-Wl,pie')
ninja.variable('libs', libs)
+ if sys.platform == "darwin":
+ ninja.variable('ldflags', '-Wl,-pie')
link = { LIB: 'alink', EXE: 'link'}[target.kind]
ninja.build(target.output, link, [obj for _, obj in target.src_obj_pairs],
implicit=deps)
+def write_sources(target, root_dir):
+ need_main = target.kind == EXE
+
+ includes = []
+
+ # Include siblings.
+ for cc_filename, _ in target.src_obj_pairs:
+ h_filename = os.path.basename(os.path.splitext(cc_filename)[0] + '.h')
+ includes.append(h_filename)
+
+ # Include deps.
+ for dep in target.deps:
+ for cc_filename, _ in dep.src_obj_pairs:
+ h_filename = os.path.basename(
+ os.path.splitext(cc_filename)[0] + '.h')
+ includes.append("%s/%s" % (dep.dir_path, h_filename))
+
+ for cc_filename, _ in target.src_obj_pairs:
+ cc_path = os.path.join(root_dir, cc_filename)
+ h_path = os.path.splitext(cc_path)[0] + '.h'
+ namespace = os.path.basename(target.dir_path)
+ class_ = os.path.splitext(os.path.basename(cc_filename))[0]
+ try:
+ os.makedirs(os.path.dirname(cc_path))
+ except OSError:
+ pass
+
+ with open(h_path, 'w') as f:
+ f.write('namespace %s { struct %s { %s(); }; }' % (namespace,
+ class_, class_))
+ with open(cc_path, 'w') as f:
+ for include in includes:
+ f.write('#include "%s"\n' % include)
+ f.write('\n')
+ f.write('namespace %s { %s::%s() {} }' % (namespace,
+ class_, class_))
+
+ if need_main:
+ f.write('int main(int argc, char **argv) {}\n')
+ need_main = False
+
def write_master_ninja(master_ninja, targets):
"""Writes master build.ninja file, referencing all given subninjas."""
master_ninja.variable('cxx', 'c++')
master_ninja.variable('ld', '$cxx')
+ if sys.platform == 'darwin':
+ master_ninja.variable('alink', 'libtool -static')
+ else:
+ master_ninja.variable('alink', 'ar rcs')
master_ninja.newline()
master_ninja.pool('link_pool', depth=4)
@@ -148,8 +190,8 @@ def write_master_ninja(master_ninja, targets):
master_ninja.rule('cxx', description='CXX $out',
command='$cxx -MMD -MF $out.d $defines $includes $cflags -c $in -o $out',
depfile='$out.d', deps='gcc')
- master_ninja.rule('alink', description='LIBTOOL-STATIC $out',
- command='rm -f $out && libtool -static -o $out $in')
+ master_ninja.rule('alink', description='ARCHIVE $out',
+ command='rm -f $out && $alink -o $out $in')
master_ninja.rule('link', description='LINK $out', pool='link_pool',
command='$ld $ldflags -o $out $in $libs')
master_ninja.rule('stamp', description='STAMP $out', command='touch $out')
@@ -181,9 +223,8 @@ def FileWriter(path):
f.close()
-def random_targets():
- num_targets = 1500
- gen = GenRandom()
+def random_targets(num_targets, src_dir):
+ gen = GenRandom(src_dir)
# N-1 static libraries, and 1 executable depending on all of them.
targets = [Target(gen, LIB) for i in xrange(num_targets - 1)]
@@ -199,16 +240,28 @@ def random_targets():
def main():
parser = argparse.ArgumentParser()
+ parser.add_argument('-s', '--sources', nargs="?", const="src",
+ help='write sources to directory (relative to output directory)')
+ parser.add_argument('-t', '--targets', type=int, default=1500)
+ help='number of targets (default: 1500)',
+ parser.add_argument('-S', '--seed', type=int, help='random seed',
+ default=12345)
parser.add_argument('outdir', help='output directory')
args = parser.parse_args()
root_dir = args.outdir
- random.seed(12345)
+ random.seed(args.seed)
- targets = random_targets()
+ do_write_sources = args.sources is not None
+ src_dir = args.sources if do_write_sources else "src"
+
+ targets = random_targets(args.targets, src_dir)
for target in targets:
with FileWriter(os.path.join(root_dir, target.ninja_file_path)) as n:
- write_target_ninja(n, target)
+ write_target_ninja(n, target, src_dir)
+
+ if do_write_sources:
+ write_sources(target, root_dir)
with FileWriter(os.path.join(root_dir, 'build.ninja')) as master_ninja:
master_ninja.width = 120