Remove old testsuite
[dyninst.git] / testsuite / src / specification / makemake.py
1 import os
2 import tuples
3
4 ######################################################################
5 # Utility functions
6 ######################################################################
7 #
8
9 def uniq(lst):
10    return reduce(lambda l, i: ((i not in l) and l.append(i)) or l, lst, [])
11
12 info = {}
13 def read_tuples(tuplefile):
14    f = open(tuplefile)
15    info['platforms'] = tuples.parse_platforms(f.readline())
16    info['languages'] = tuples.parse_languages(f.readline())
17    info['compilers'] = tuples.parse_compilers(f.readline())
18    info['mutators'] = tuples.parse_mutators(f.readline())
19    info['mutatees'] = tuples.parse_mutatees(f.readline())
20    info['tests'] = tuples.parse_tests(f.readline())
21    info['rungroups'] = tuples.parse_rungroups(f.readline())
22 #  info['exception_types'] = tuples.parse_exception_types(f.readline())
23    info['exception_types'] = None
24 #  info['exceptions'] = tuples.parse_exceptions(f.readline())
25    info['exceptions'] = None
26    info['objects'] = tuples.parse_object_files(f.readline())
27    f.close()
28
29
30 def extension(filename):
31    ext_ndx = filename.rfind('.')
32    return filename[ext_ndx:]
33
34 def replace_extension(name, ext):
35    dot_ndx = name.rfind('.')
36    return name[:dot_ndx] + ext
37
38 # Get the name of the language for the given file.  If more than one
39 # is possible, I don't really know what to do...  Return a list of all
40 # the possibilities with compilers on the current platform?
41 # We should not ever get more than one language for a given extension.  We're
42 # enforcing that in the tuple generator.
43 def get_file_lang(filename):
44    ext = extension(filename)
45    langs = filter(lambda x: ext in x['extensions'], info['languages'])
46    # We have a list of all languages which match the extension of the file
47    # Filter out all of those languages for which there is no compiler on this
48    # platform:
49    #  Find the compilers available on this platform
50    platform = os.environ.get('PLATFORM')
51    comps = filter(lambda x: platform in info['compilers'][x]['platforms'],
52                info['compilers'])
53    #  Get a list of all the languages supported by those compilers
54    supported_langs = map(lambda x: info['compilers'][x]['languages'],
55                     comps)
56    supported_langs = reduce(lambda x,y:x+y, supported_langs)
57    supported_langs = uniq(supported_langs)
58    #  Remove all languages from langs that aren't in supported_langs
59    langs = filter(lambda x: x['name'] in supported_langs, langs)
60    if len(langs) > 1:
61       return langs
62    else:
63       return langs[0]
64
65 def compiler_count(lang):
66    plat = os.environ.get('PLATFORM')
67    return len(filter(lambda x: lang in info['compilers'][x]['languages']
68                        and plat in info['compilers'][x]['platforms']
69                  , info['compilers']))
70
71 def find_platform(pname):
72    plist = filter(lambda p: p['name'] == pname, info['platforms'])
73    if len(plist) == 0:
74       return None
75    else:
76       return plist[0]
77
78 def find_language(lname):
79    llist = filter(lambda l: l['name'] == lname, info['languages'])
80    if len(llist) == 0:
81       return None
82    else:
83       return llist[0]
84
85 # Returns a string containing the mutatee's compile-time options filename
86 # component: a string of the form _<compiler>_<ABI>_<optimization>
87 def mutatee_cto_component(mutatee):
88    compiler = info['compilers'][mutatee['compiler']]
89    return fullspec_cto_component(compiler,
90                           mutatee['abi'],
91                           mutatee['optimization'])
92
93 # Returns a string containing the mutatee's compile-time options filename
94 # component for mutatees compiled with an auxilliary compiler
95 def auxcomp_cto_component(compiler, mutatee):
96    return fullspec_cto_component(compiler,
97                           mutatee['abi'],
98                           mutatee['optimization'])
99
100 # Returns a string containing the mutatee's compile-time options filename
101 # component for a fully specified set of build-time options
102 def fullspec_cto_component(compiler, abi, optimization):
103    retval = "_%s_%s_%s" % (compiler['executable'],
104                      abi,
105                      optimization)
106    return retval
107
108 # Returns a string containing the link-time options component for a fully-
109 # specified set of link-time options
110 # NOTE: There are currently no link-time options specified
111 def fullspec_lto_component():
112    return ""
113
114 # Returns a string containing the link-time options component for a mutatee's
115 # filename
116 # NOTE: There are currently no link-time options specified
117 def mutatee_lto_component(mutatee):
118    return fullspec_lto_component()
119
120 # Returns a string containing the link-time options component for a mutatee's
121 # filename when the mutatee is compiled using an auxilliary compiler
122 # NOTE: I think this function is pointless
123 def auxcomp_lto_component(compiler, mutatee):
124    return fullspec_lto_component()
125
126 # Returns a string containing the build-time options component for a fully-
127 # specified set of build-time options
128 def fullspec_bto_component(compiler, abi, optimization):
129    return "%s%s" % (fullspec_cto_component(compiler, abi, optimization),
130                 fullspec_lto_component())
131
132 # Returns a string containing the build-time options component for a mutatee's
133 # filename
134 def mutatee_bto_component(mutatee):
135    return "%s%s" % (mutatee_cto_component(mutatee),
136                 mutatee_lto_component(mutatee))
137
138 # Returns a string containing the build-time options component for a mutatee's
139 # filename, when the mutatee is built using an auxilliary compiler
140 # NOTE: I don't think this ever happens.
141 def auxcomp_bto_component(compiler, mutatee):
142    return "%s%s" % (auxcomp_cto_component(compiler, mutatee),
143                 auxcomp_lto_component(compiler, mutatee))
144
145 def mutatee_binary(mutatee):
146    # Returns standard name for the solo mutatee binary for this mutatee
147    platform = find_platform(os.environ.get('PLATFORM'))
148    es = platform['filename_conventions']['executable_suffix']
149    return "%s.mutatee_solo%s%s" % (mutatee['name'],
150                            mutatee_bto_component(mutatee),
151                            es)
152
153 #
154 ######################################################################
155
156
157 ######################################################################
158 # make.mutators.gen
159 ######################################################################
160 #
161
162 def print_mutators_list(out, mutator_dict, test_dict):
163         platform = find_platform(os.environ.get('PLATFORM'))
164         LibSuffix = platform['filename_conventions']['library_suffix']
165         ObjSuffix = platform['filename_conventions']['object_suffix']
166
167         out.write("######################################################################\n")
168         out.write("# A list of all the mutators to be compiled\n")
169         out.write("######################################################################\n\n")
170
171         module_list = []
172         for t in test_dict:
173                 module_list.append(t['module'])
174         module_set = set(module_list)
175
176         for m in module_set:
177                 out.write("\n")
178                 out.write("%s_MUTATORS = " % (m))
179                 module_tests = filter(lambda t: m == t['module'], test_dict)
180                 module_mutators = map(lambda t: t['mutator'], module_tests)
181                 for t in uniq(module_mutators):
182                         out.write("%s " % (t))
183                 out.write("\n\n")
184                 out.write("%s_OBJS_ALL_MUTATORS = " % (m))
185                 for t in uniq(module_mutators):
186                         out.write("%s%s " % (t, ObjSuffix))
187                 out.write("\n\n")
188
189
190         # Now we'll print out a rule for each mutator..
191         for m in mutator_dict:
192                 tests = filter(lambda t: t['mutator'] == m['name'], test_dict)
193                 modules = map(lambda t: t['module'], tests)
194                 if(len(uniq(modules)) != 1):
195                          print "ERROR: multiple modules for test " + m['name']
196                          raise
197                 module = modules.pop()
198                 # FIXME Don't hardcode $(LIBTESTSUITE)
199                 out.write("%s%s: " % (m['name'], LibSuffix))
200                 # Loop through the files listed in this mutator's source list and
201                 # add object files corresponding to each to the list of dependencies
202                 try:
203                         for s in m['sources']:
204                                 # Print out the object file for this source file
205                                 out.write("%s%s " % (s[0:-len(extension(s))], ObjSuffix))
206                         out.write("$(OBJS_FORALL_MUTATORS) $(DEPENDDIR)/%s.dep $(LIBTESTSUITE) $(%s_COMPONENT_LIB)\n" % (m['name'], module))
207                 except KeyError:
208                         print "Couldn't find sources for mutator " + m['name']
209                         raise
210                 # FIXME Make this one better too.  Right now it's copied straight from
211                 # make.module.tmpl
212                 out.write("\t$(CXX) -o $@ -shared $(filter %%%s,$^) $(%s_MUTATOR_FLAGS) $(MUTATOR_SO_LDFLAGS) $(LIBDIR) $(LIBS) $(LDFLAGS)\n" % (ObjSuffix, module))
213                 out.write("ifndef NO_OPT_FLAG\n")
214                 out.write("ifdef STRIP_SO\n")
215                 out.write("\t$(STRIP_SO) $@\n")
216                 out.write("endif\n")
217                 out.write("endif\n\n")
218
219         for m in module_set:
220                 rest = """
221
222 # Create shared library names from the mutator test names
223 %s_MUTATORS_SO += $(addsuffix %s,$(%s_MUTATORS))
224
225 """ % (m, LibSuffix, m)
226                 out.write(rest)
227
228        
229
230
231
232 def write_make_mutators_gen(filename, tuplefile):
233    read_tuples(tuplefile)
234    mutator_dict = info['mutators']
235    test_dict = info['tests']
236    platform = find_platform(os.environ.get('PLATFORM'))
237    LibSuffix = platform['filename_conventions']['library_suffix']
238    header = """
239 # This file is automatically generated by the Dyninst testing system.
240 # For more information, see core/testsuite/src/specification/makemake.py
241
242 """
243    out = open(filename, "w")
244    out.write(header)
245    print_mutators_list(out, mutator_dict, test_dict)
246    out.close()
247
248 #
249 ######################################################################
250
251 ######################################################################
252 # test_info_new.gen.C
253 ######################################################################
254 #
255
256 def write_test_info_new_gen(filename, tuplefile):
257    header = """/* This file automatically generated from test specifications.  See
258  * specification/spec.pl and specification/makemake.py
259  */
260
261 #include "test_info_new.h"
262
263
264 """
265    read_tuples(tuplefile)
266    compilers = info['compilers']
267    rungroups = info['rungroups']
268    out = open(filename, "w")
269    out.write(header)
270    print_initialize_mutatees(out, rungroups, compilers)
271    out.close()
272
273 # Return the name of the mutatee executable for this rungroup
274 def mutatee_filename(rungroup, compilers):
275    if rungroup['mutatee'] == 'none':
276       retval = ""
277    else:
278       compiler = compilers[rungroup['compiler']]
279       mutatee = rungroup['mutatee']
280       bto = fullspec_bto_component(compiler,
281                             rungroup['abi'],
282                             rungroup['optimization'])
283       platform = find_platform(os.environ.get('PLATFORM'))
284       es = platform['filename_conventions']['executable_suffix']
285       retval = "%s.mutatee_solo%s%s" % (mutatee, bto, es)
286    return retval
287
288 # Return the name of the mutator for this test
289 def test_mutator(testname):
290    testobj = filter(lambda t: t['name'] == testname, info['tests'])
291    if len(testobj) >= 1:
292       testobj = testobj[0]
293    else:
294       # TODO Handle this case better
295       testobj = None
296    if testobj != None:
297       mrname = testobj['mutator']
298    else:
299       mrname = None
300    return mrname
301
302 # Builds a text label for a test based on the run group's information
303 # FIXME This is hardcoded to set grouped to false.  It needs to be fixed to
304 # support the group mutatee optimization
305 def build_label(test, mutator, rungroup):
306    label = "{test: %s, mutator: %s, grouped: false" % (test, mutator)
307    for n in rungroup:
308       # We've already dealt with tests and we don't handle groupable yet
309       if n not in ['tests', 'groupable']:
310          label = label + ", " + n + ": " + rungroup[n]
311    label = label + "}"
312    return label
313
314
315 def print_initialize_mutatees(out, rungroups, compilers):
316         header = """
317 // Now we insert the test lists into the run groups
318 void initialize_mutatees(std::vector<RunGroup *> &tests) {
319         unsigned int group_count = 0;
320         // Keep track of which element each test is, for later use with the resumelog
321         unsigned int test_count;
322         RunGroup *rg;
323 """
324         out.write(header)
325
326         platform = find_platform(os.environ.get('PLATFORM'))
327         LibSuffix = platform['filename_conventions']['library_suffix']
328
329         # TODO Change these to get the string conversions from a tuple output
330         for group in rungroups:
331                 compiler = info['compilers'][group['compiler']]
332                 if compiler['presencevar'] != 'true':
333                         out.write("#ifdef %s\n" % (compiler['presencevar']))
334                 mutateename = mutatee_filename(group, compilers)
335                 out.write('  test_count = 0;\n')
336                 out.write('  rg = new RunGroup("%s", ' % (mutateename))
337                 if group['start_state'] == 'stopped':
338                         out.write('STOPPED, ')
339                 elif group['start_state'] == 'running':
340                         out.write('RUNNING, ')
341                 else: # Assuming 'selfstart'
342                         out.write('SELFSTART, ')
343                 if group['run_mode'] == 'createProcess':
344                         out.write('CREATE, ')
345                 elif group['run_mode'] == 'useAttach':
346                         out.write('USEATTACH, ')
347                 elif group['run_mode'] == 'deserialize':
348                         out.write('DESERIALIZE, ')
349                 else:
350                         out.write('DISK, ')
351                 if group['groupable'] == 'true':
352                         out.write('false') # !groupable
353                 else:
354                         out.write('true') # !groupable
355                 try:
356                         testobj = filter(lambda t: t['name'] == group['tests'][0], info['tests'])
357                         if len(testobj) < 1:
358                                 raise TestNotFound, 'Test not found: ' + test
359                         else:
360                                 module = testobj[0]['module']
361                 except KeyError:
362                         print "No module found! Test object: " 
363                         print testobj[0]
364                         raise
365                 out.write(', "%s", "%s", "%s", "%s"' % (module, group['compiler'], group['optimization'], group['abi']))
366                 out.write(');\n')
367                 for test in group['tests']:
368                         # Set the tuple string for this test
369                         # (<test>, <mutatee compiler>, <mutatee optimization>, <create mode>)
370                         # I need to get the mutator that this test maps to..
371                         mutator = test_mutator(test)
372                         ts = build_label(test, mutator, group)
373                         if test in ['test_serializable']:
374                                 serialize_enable = 'true'
375                         else:
376                                 serialize_enable = 'false'
377                         out.write('  rg->tests.push_back(new TestInfo(test_count++, "%s", "%s", "%s%s", %s, "%s"));\n' % (test, mutator, mutator, LibSuffix, serialize_enable, ts))
378                 out.write('  rg->index = group_count++;\n')
379                 out.write('  tests.push_back(rg);\n')
380                 # Close compiler presence #ifdef
381                 if compiler['presencevar'] != 'true':
382                         out.write("#endif // defined(%s)\n" % (compiler['presencevar']))
383         out.write('}\n')
384
385 #
386 ##########
387
388 ######################################################################
389 # make.solo_mutatee.gen
390 ######################################################################
391 #
392
393 def collect_mutatee_comps(mutatees):
394    comps = []
395    for m in mutatees:
396       if m['compiler'] != '' and m['compiler'] not in comps:
397          comps.append(m['compiler'])
398    return comps
399
400 # Print makefile variable initializations for all the compilers used for
401 # makefiles on this platform
402 def print_mutatee_comp_defs(out):
403    out.write("# Define variables for our compilers, if they aren't already defined\n")
404    pname = os.environ.get('PLATFORM')
405    # TODO Check that we got a string
406    comps = filter(lambda c: c != ''
407                          and pname in info['compilers'][c]['platforms'],
408                info['compilers'])
409    for c in comps:
410       if info['compilers'][c]['presencevar'] != 'true':
411          out.write("ifdef %s\n" % (info['compilers'][c]['presencevar']))
412       out.write('M_%s ?= %s\n' % (info['compilers'][c]['defstring'], info['compilers'][c]['executable']))
413       if info['compilers'][c]['presencevar'] != 'true':
414          out.write("endif\n")
415    out.write('\n')
416
417 def get_module(mutatee):
418    return mutatee["module"]
419
420 def group_uses_module(group, module):
421    mutatee_name = group['mutatee']
422    mutatees = filter(lambda t: t['name'] == group['mutatee'], info['mutatees'])
423    return get_module(mutatees[0]) == module
424
425 def has_multiple_tests(testgroup):
426    try:
427       t = testgroup['tests']
428       return len(t) > 1
429    except TypeError:
430       print "Test group's test list was not a list"
431       print t
432       raise
433
434 def print_mutatee_rules(out, mutatees, compiler, module):
435         if(len(mutatees) == 0):
436                 return
437         mut_names = map(lambda x: mutatee_binary(x), mutatees)
438         out.write("######################################################################\n")
439         out.write("# Mutatees compiled with %s for %s\n" % (mutatees[0]['compiler'], module))
440         out.write("######################################################################\n\n")
441         if compiler['presencevar'] != 'true':
442                 out.write("ifdef %s\n" % (compiler['presencevar']))
443                 out.write("# We only want to build these targets if the compiler exists\n")
444         out.write("%s_SOLO_MUTATEES_%s = " % (module, compiler['defstring']))
445         for m in mut_names:
446                 out.write("%s " % (m))
447         out.write('\n')
448         if compiler['presencevar'] != 'true':
449                 out.write("endif\n")
450         out.write("\n")
451         out.write("# Now a list of rules for compiling the mutatees with %s\n\n"
452                           % (mutatees[0]['compiler']))
453
454         pname = os.environ.get('PLATFORM')
455         platform = find_platform(pname)
456         ObjSuffix = platform['filename_conventions']['object_suffix']
457         groups = info['rungroups']
458
459         # Write rules for building the mutatee executables from the object files
460         for (m, n) in zip(mutatees, mut_names):
461                 out.write("%s: " % (n))
462
463                 group_mutatee_list = filter(has_multiple_tests, groups)
464                 group_mutatee_list = filter(lambda g: g['mutatee'] == m['name'], group_mutatee_list)
465                 group_boilerplates = uniq(map(lambda g: g['mutatee'] + '_group.c', group_mutatee_list))
466                 for bp in group_boilerplates:
467                         cto = mutatee_cto_component(m)
468                         out.write("%s " % (replace_extension(bp, "%s%s"
469                                                          % (cto, ObjSuffix))))
470
471                 for f in m['preprocessed_sources']:
472                         # List all the compiled transformed source files
473                         # I need to futz with the compiler here to make sure it's correct..
474                         # FIXME This next line may end up arbitrarily picking the first
475                         # language from a list of more than one for an extension
476                         lang = filter(lambda l: extension(f) in l['extensions'],
477                                                   info['languages'])[0]['name']
478                         if (lang in compiler['languages']):
479                                 cto = mutatee_cto_component(m)
480                                 out.write("%s " % (replace_extension(f, "_solo%s%s"
481                                                                                                          % (cto, ObjSuffix))))
482                         else: # Preprocessed file compiled with auxilliary compiler
483                                 pname = os.environ.get('PLATFORM')
484                                 # TODO Check that we got a string..
485                                 platform = find_platform(pname)
486                                 # TODO Check that we retrieved a platform object
487                                 try:
488                                         aux_comp = platform['auxilliary_compilers'][lang]
489                                 except KeyError:
490                                         print "Working on mutatee: " + n + ", file: " + f + ", no language for " + lang + ", platform object:"
491                                         print platform
492                                         raise
493                                 # TODO Verify that we got a compiler
494                                 cto = auxcomp_cto_component(info['compilers'][aux_comp], m)
495                                 out.write("%s " % (replace_extension(f, "_solo%s%s"
496                                                                                                          % (cto, ObjSuffix))))
497                 # TODO Let's grab the languages used in the preprocessed sources, and
498                 # save them for later.  We use this to determine which raw sources get
499                 # compiled with the same options as the preprocessed ones, in the case
500                 # of a compiler that is used for more than one language (e.g. GCC in
501                 # tests test1_35 or test_mem)
502
503                 # FIXME I'm doing this wrong: the compiler for preprocessed files might
504                 # not be the compiler that we're testing..
505                 # Get the compiler..
506                 maincomp_langs = uniq(info['compilers'][m['compiler']]['languages'])
507                 pp_langs = uniq(map(lambda x: get_file_lang(x)['name'], m['preprocessed_sources']))
508                 # So we want to print out a list of object files that go into this
509                 # mutatee.  For files that can be compiled with m['compiler'], we'll
510                 # use it, and compile at optimization level m['optimization'].  For
511                 # other files, we'll just use the appropriate compiler and not worry
512                 # about optimization levels?
513                 for f in m['raw_sources']:
514                         # Figure out whether or not this file can be compiled with
515                         # m['compiler']
516                         lang = get_file_lang(f)
517                         if type(lang) == type([]):
518                                 lang = lang[0] # BUG This may cause unexpected behavior if more
519                                                # than one language was returned, but more than
520                                                            # one language should never be returned
521                         if lang['name'] in maincomp_langs:
522                                 # This file is compiled with the main compiler for this mutatee
523                                 cto = mutatee_cto_component(m)
524                                 out.write("%s " % (replace_extension(f, "%s%s"
525                                                                                                          % (cto, ObjSuffix))))
526                         else:
527                                 # This file is compiled with an auxilliary compiler
528                                 # Find the auxilliary compiler for this language on this
529                                 # platform
530                                 # This assumes that there is only one possible auxilliary
531                                 # compiler for a language ending with the extension of interest
532                                 # on the platform.  This condition is enforced by sanity checks
533                                 # in the specification file.
534                                 aux_comp = platform['auxilliary_compilers'][lang['name']]
535                                 cto = fullspec_cto_component(info['compilers'][aux_comp],
536                                                                                          m['abi'], 'none')
537                                 out.write("%s " % (replace_extension(f, '%s%s'
538                                                                                                          % (cto, ObjSuffix))))
539                 # FIXME Check whether the current compiler compiles C files and if not
540                 # then use the aux compiler for this platform for the mutatee driver
541                 # object.
542                 if 'c' in info['compilers'][m['compiler']]['languages']:
543                         out.write("mutatee_driver_solo_%s_%s%s\n"
544                                           % (info['compilers'][m['compiler']]['executable'],
545                                                  m['abi'], ObjSuffix))
546                 else:
547                         # Get the aux compiler for C on this platform and use it
548                         aux_c = find_platform(os.environ.get('PLATFORM'))['auxilliary_compilers']['c']
549                         aux_c = info['compilers'][aux_c]['executable']
550                         out.write("mutatee_driver_solo_%s_%s%s\n"
551                                           % (aux_c, m['abi'], ObjSuffix))
552                 # Print the actions used to link the mutatee executable
553                 out.write("\t%s -o $@ $(filter %%%s,$^) %s %s "
554                                   % (platform['linker'] or "$(M_%s)" % compiler['defstring'],
555                                          ObjSuffix,
556                                          compiler['flags']['link'],
557                                          compiler['abiflags'][platform['name']][m['abi']]))
558                 for l in m['libraries']:
559                         # Need to include the required libraries on the command line
560                         # FIXME Use a compiler-specific command-line flag instead of '-l'
561                         out.write("-l%s" % (l))
562                         if os.environ.get('PLATFORM') == 'x86_64-unknown-linux2.4':
563                                 if m['abi'] == '32':
564                                         if l == 'testA':
565                                                 out.write('_m32')
566                         out.write(" ")
567                 out.write('\n')
568
569                 # ***ADD NEW BUILD-TIME ACTIONS HERE***
570
571
572 # Prints all the special object file compile rules for a given compiler
573 # FIXME This doesn't deal with preprocessed files!
574 def print_special_object_rules(compiler, out):
575         out.write("\n# Exceptional rules for mutatees compiled with %s\n\n"
576                           % (compiler))
577         objects = filter(lambda o: o['compiler'] == compiler, info['objects'])
578         for o in objects:
579                 # Print a rule to build this object file
580                 # TODO Convert the main source file name to an object name
581                 #  * Crap!  I don't know if this is a preprocessed file or not!
582                 #  * This should be okay soon; I'm removing the proprocessing stage..
583                 platform = os.environ.get("PLATFORM")
584                 ofileext = find_platform(platform)['filename_conventions']['object_suffix']
585                 ofilename = o['object'] + ofileext
586                 out.write("%s: " % (ofilename))
587                 for s in o['sources']:
588                         out.write("../src/%s " % (s))
589                 for i in o['intermediate_sources']:
590                         out.write("%s " % (i))
591                 for d in o['dependencies']:
592                         out.write("%s " % (d))
593                 out.write("\n")
594                 out.write("\t$(M_%s) $(SOLO_MUTATEE_DEFS) " % (info['compilers'][compiler]['defstring']))
595                 for f in o['flags']:
596                         out.write("%s " % (f))
597                 out.write("-o $@ %s " % info['compilers'][compiler]['parameters']['partial_compile'])
598                 for s in o['sources']:
599                         out.write("../src/%s " % (s))
600                 for i in o['intermediate_sources']:
601                         out.write("%s " % (i))
602                 out.write("\n")
603         out.write("\n")
604
605 # Produces a string of compiler flags for compiling mutatee object files with
606 # the specified build-time options
607 def object_flag_string(platform, compiler, abi, optimization):
608    return "%s %s %s %s %s" % (compiler['flags']['std'],
609                         compiler['flags']['mutatee'],
610                         compiler['parameters']['partial_compile'],
611                         compiler['abiflags'][platform['name']][abi],
612                         compiler['optimization'][optimization])
613
614
615 def print_patterns_wildcards(c, out, module):
616    compiler = info['compilers'][c]
617    platform = find_platform(os.environ.get('PLATFORM'))
618    ObjSuffix = platform['filename_conventions']['object_suffix']
619    
620    for abi in platform['abis']:
621       for o in compiler['optimization']:
622          cto = fullspec_cto_component(compiler, abi, o)
623          for l in compiler['languages']:
624             lang = find_language(l) # Get language dictionary from name
625             for e in lang['extensions']:
626                if (module == None):
627                   out.write("%%%s%s: ../src/%%%s\n"
628                             % (cto, ObjSuffix, e))
629                else:
630                   out.write("%%%s%s: ../src/%s/%%%s\n"
631                             % (cto, ObjSuffix, module, e))
632                out.write("\t$(M_%s) $(SOLO_MUTATEE_DEFS) %s -o $@ $<\n"
633                          % (compiler['defstring'],
634                             object_flag_string(platform, compiler,
635                                                abi, o)))
636
637 def is_groupable(mutatee):
638          if(mutatee['groupable'] == 'false'):
639                   return 'false'
640          groups = info['rungroups']
641          mutatee_tests = filter(lambda g: g['mutatee'] == mutatee['name'], groups)
642          if(max(map(lambda g: len(g['tests']), mutatee_tests)) > 1):
643                   return 'true'
644          else:
645                   return 'false'
646
647 def get_all_mutatee_sources(groupable, module):
648         return uniq(reduce(lambda a, b: set(a) | set(b),
649                 (map(lambda m: m['preprocessed_sources'],
650                 filter(lambda m: m['name'] != 'none'
651                         and is_groupable(m) == groupable and get_module(m) == module,
652                         info['mutatees']))),
653                 []))
654          
655    
656 # Prints generic rules for compiling from mutatee boilerplate
657 def print_patterns(c, out, module):
658         out.write("\n# Generic rules for %s's mutatees and varying optimization levels for %s\n" % (c, module))
659
660         compiler = info['compilers'][c]
661         platform = find_platform(os.environ.get('PLATFORM'))
662         ObjSuffix = platform['filename_conventions']['object_suffix']
663
664         ng_sources = get_all_mutatee_sources('false', module)
665         g_sources = get_all_mutatee_sources('true', module)
666
667         for abi in platform['abis']:
668                 for o in compiler['optimization']:
669                         # Rules for compiling source files to .o files
670                         cto = fullspec_cto_component(compiler, abi, o)
671
672                         #FIXME this prints out one rule for every mutatee preprocessed source for EVERY optimization
673                         #      I don't know whether the previous targets require every combination of source/opt
674                         #      i.e. printing ALL of them may be superfluous
675                         for sourcefile in ng_sources:
676                                 ext = extension(sourcefile)
677                                 boilerplate = "solo_mutatee_boilerplate" + ext
678                                 basename = sourcefile[0:-len('_mutatee') - len(ext)]
679
680                                 out.write("%s_mutatee_solo%s%s: ../src/%s ../src/%s/%s\n"
681                                                 % (basename, cto, ObjSuffix, boilerplate, module, sourcefile))
682                                 out.write("\t$(M_%s) $(%s_SOLO_MUTATEE_DEFS) %s -I../src/%s -DTEST_NAME=%s -DGROUPABLE=0 -DMUTATEE_SRC=../src/%s/%s -o $@ $<\n"
683                                                 % (compiler['defstring'], module,
684                                                    object_flag_string(platform, compiler, abi, o),
685                                                    module,
686                                                    basename, module, sourcefile))
687                         for sourcefile in g_sources:
688                                 ext = extension(sourcefile)
689                                 boilerplate = "solo_mutatee_boilerplate" + ext
690                                 basename = sourcefile[0:-len('_mutatee') - len(ext)]
691
692                                 out.write("%s_mutatee_solo%s%s: ../src/%s ../src/%s/%s\n"
693                                                 % (basename, cto, ObjSuffix, boilerplate, module, sourcefile))
694                                 out.write("\t$(M_%s) $(%s_SOLO_MUTATEE_DEFS) %s -I../src/%s -DTEST_NAME=%s -DGROUPABLE=1 -DMUTATEE_SRC=../src/%s/%s -o $@ $<\n"
695                                                 % (compiler['defstring'], module,
696                                                    object_flag_string(platform, compiler, abi, o),
697
698                                                    module,
699                                                    basename, module, sourcefile))
700         groups = info['rungroups']
701         group_mutatee_list = filter(has_multiple_tests, groups)
702         groups_for_module = filter(lambda g: group_ok_for_module(g, module) == 'true', group_mutatee_list)
703         group_boilerplates = uniq(map(lambda g: g['mutatee'] + '_group.c', groups_for_module))
704         for abi in platform['abis']:
705                 for o in compiler['optimization']:
706                         cto = fullspec_cto_component(compiler, abi, o)
707                         for sourcefile in group_boilerplates:
708                                 ext = extension(sourcefile)
709                                 basename = sourcefile[0:-len(ext)]
710                                 out.write("%s%s%s: %s\n" % (basename, cto, ObjSuffix, sourcefile))
711                                 out.write("\t$(M_%s) $(%s_SOLO_MUTATEE_DEFS) %s -DGROUPABLE=1 -o $@ $<\n" 
712                                                          % (compiler['defstring'], module, 
713                                                                  object_flag_string(platform, compiler, abi, o)))
714
715         out.write("\n")
716
717
718
719 # Prints pattern rules for this platform's auxilliary compilers
720 def print_aux_patterns(out, platform, comps, module):
721         # Pattern rules for auxilliary compilers supported on this platform
722         out.write("\n# Generic rules for this platform's auxilliary compilers\n\n")
723         aux_comps = platform['auxilliary_compilers']
724         for ac_lang in aux_comps:
725                 compname = aux_comps[ac_lang]
726                 comp = info['compilers'][compname]
727                 # Print pattern rule(s) for this compiler
728                 # ac should be a map from a language to a compiler..
729                 lang = filter(lambda l: l['name'] == ac_lang, info['languages'])[0]
730                 for ext in lang['extensions']:
731                         for abi in platform['abis']:
732                                 for o in comp['optimization']:
733                                         cto = fullspec_cto_component(comp, abi, o)
734                                         out.write("%%%s%s: ../src/%%%s\n"
735                                                           % (cto,
736                                                                  platform['filename_conventions']['object_suffix'],
737                                                                  ext))
738                                         # FIXME Make this read the parameter flags from the
739                                         # compiler tuple (output file parameter flag)
740                                         out.write("\t$(M_%s) %s -o $@ $<\n\n"
741                                                           % (comp['defstring'],
742                                                                  object_flag_string(platform, comp,
743                                                                                                         abi, o)))
744
745                                         if (module != None):
746                                                  out.write("%%%s%s: ../src/%s/%%%s\n"
747                                                                           % (cto, platform['filename_conventions']['object_suffix'],
748                                                                                   module, ext))
749                                         else:
750                                                  out.write("%%%s%s: ../src/%%%s\n"
751                                                                           % (cto, platform['filename_conventions']['object_suffix'],
752                                                                                   ext))
753                                         # FIXME Make this read the parameter flags from the
754                                         # compiler tuple (output file parameter flag)
755                                         out.write("\t$(M_%s) %s -o $@ $<\n\n"
756                                                           % (comp['defstring'],
757                                                                  object_flag_string(platform, comp,
758                                                                                                         abi, o)))
759
760
761 # Prints the footer for make.solo_mutatee.gen
762 def print_make_solo_mutatee_gen_footer(out, comps, platform, module):
763    compilers = info['compilers']
764    out.write("# And a rule to build all of the mutatees\n")
765    out.write(".PHONY: %s_solo_mutatees\n" % (module))
766    out.write("%s_solo_mutatees: " % (module))
767    for c in comps:
768       out.write("$(%sSOLO_MUTATEES_%s) " % (module, compilers[c]['defstring']))
769    out.write("\n\n")
770    out.write(".PHONY: clean_solo_mutatees\n")
771    out.write("%s_clean_solo_mutatees:\n" % (module))
772    for c in comps:
773       out.write("\t-$(RM) $(%s_SOLO_MUTATEES_%s)\n"
774               % (module, compilers[c]['defstring']))
775    # Get a list of optimization levels we're using and delete the mutatee
776    # objects for each of them individually
777    objExt = platform['filename_conventions']['object_suffix']
778    # FIXME Get the actual list of optimization levels we support
779    for o in ['none', 'low', 'high', 'max']:
780       out.write("\t-$(RM) *_%s%s\n" % (o, objExt))
781    out.write("\n\n")
782    out.write("%s_SOLO_MUTATEES =" % (module))
783    for c in comps:
784       out.write(" $(%s_SOLO_MUTATEES_%s)" % (module, compilers[c]['defstring']))
785    out.write("\n\n")
786
787    out.write("### COMPILER_CONTROL_DEFS is used to determine which compilers are present\n")
788    out.write("### when compiling the list of mutatees to test against\n")
789    out.write("COMPILER_CONTROL_DEFS =\n")
790    for c in comps:
791       if info['compilers'][c]['presencevar'] != 'true':
792          out.write("ifdef %s # Is %s present?\n" % (info['compilers'][c]['presencevar'], c))
793          out.write("COMPILER_CONTROL_DEFS += -D%s\n" % (info['compilers'][c]['presencevar']))
794          out.write("endif\n")
795    out.write('\n')
796
797 def format_test_info(test):
798    line = '  {"' + test + '", ' + test + '_mutatee, GROUPED, "' + test + '"}'
799    return line
800
801 def format_test_defines(test):
802    line = 'extern int ' + test + '_mutatee();\n'
803    return line
804
805 def write_group_mutatee_boilerplate_file(filename, group):
806    tests = group['tests']
807    out = open(filename, "w")
808    out.write("#ifdef __cplusplus\n")
809    out.write('extern "C" {\n')
810    out.write("#endif\n")
811    out.write('#include "../src/mutatee_call_info.h"\n\n')
812    map(lambda t: out.write(format_test_defines(t)), tests)
813    out.write("\n")
814    out.write("mutatee_call_info_t mutatee_funcs[] = {\n")
815    out.write(reduce(lambda s, t: s + ',\n' + t, map(format_test_info, tests)))
816    out.write("\n")
817    out.write("};\n")
818    out.write("\n")
819    out.write("int max_tests = %d;\n" % (len(tests)))
820    out.write("int runTest[%d];\n" % (len(tests)))
821    out.write("int passedTest[%d];\n" % (len(tests)))
822    out.write("#ifdef __cplusplus\n")
823    out.write("}\n")
824    out.write("#endif\n")
825    out.close()
826
827
828 def accumulate_groups_if_equal(acc, g):
829    if(acc == []):
830       return [g]
831    duplicates = filter(lambda x: x['mutatee'] == g['mutatee'] and x['tests'] == g['tests'], acc)   
832    if(duplicates == []):
833       acc.append(g)
834    return acc
835
836 def write_group_mutatee_boilerplate(filename_pre, filename_post, tuplefile):
837    read_tuples(tuplefile)
838    groups = filter(lambda g: len(g['tests']) > 25, info['rungroups'])
839    groups = reduce(accumulate_groups_if_equal, groups, [])
840    map(lambda g: write_group_mutatee_boilerplate_file(filename_pre + g['mutatee'] + filename_post, g), groups) 
841
842
843 # Main function for generating make.solo_mutatee.gen
844 def write_make_solo_mutatee_gen(filename, tuplefile):
845         read_tuples(tuplefile)
846         compilers = info['compilers']
847         mutatees = info['mutatees']
848         out = open(filename, "w")
849         print_mutatee_comp_defs(out)
850         comps = collect_mutatee_comps(mutatees)
851         pname = os.environ.get('PLATFORM')
852         platform = find_platform(pname)
853         ObjSuffix = platform['filename_conventions']['object_suffix']
854         modules = uniq(map(lambda t: t['module'], info['tests']))
855         for c in comps:
856                 # Generate a block of rules for mutatees produced by each compiler
857                 for m in modules:
858                         muts = filter(lambda x: x['compiler'] == c and get_module(x) == m, mutatees)
859                         if(len(muts) != 0):
860                                 print_mutatee_rules(out, muts, compilers[c], m)
861                 # Print rules for exceptional object files
862                 print_special_object_rules(c, out)
863
864                 for m in modules:
865                         print_patterns(c, out, m)
866                         print_patterns_wildcards(c, out, m)
867                 print_patterns_wildcards(c, out, None)
868
869                 out.write("# Rules for building the driver and utility objects\n")
870                 # TODO Replace this code generation with language neutral code
871                 # generation
872                 if 'c' in info['compilers'][c]['languages']:
873                         for abi in platform['abis']:
874                                 out.write("mutatee_driver_solo_%s_%s%s: ../src/mutatee_driver.c\n" % (info['compilers'][c]['executable'], abi, ObjSuffix))
875                                 out.write("\t$(M_%s) %s %s %s -o $@ -c $<\n"
876                                                   % (compilers[c]['defstring'],
877                                                          compilers[c]['flags']['std'],
878                                                          compilers[c]['flags']['mutatee'],
879                                                          compilers[c]['abiflags'][platform['name']][abi]))
880                                 out.write("mutatee_util_%s_%s%s: ../src/mutatee_util.c\n"
881                                                   % (info['compilers'][c]['executable'],
882                                                          abi, ObjSuffix))
883                                 out.write("\t$(M_%s) %s %s %s -o $@ -c $<\n\n"
884                                                   % (compilers[c]['defstring'],
885                                                          compilers[c]['flags']['std'],
886                                                          compilers[c]['flags']['mutatee'],
887                                                          compilers[c]['abiflags'][platform['name']][abi]))
888                 else:
889                         out.write("# (Skipped: driver and utility objects cannot be compiled with this compiler\n")
890
891         # Print pattern rules for this platform's auxilliary compilers
892
893         for m in modules:
894                 print_aux_patterns(out, platform, comps, m)
895         print_aux_patterns(out, platform, comps, None)
896         # Print footer (list of targets, clean rules, compiler presence #defines)
897         for m in modules:
898                 print_make_solo_mutatee_gen_footer(out, comps, platform, m)
899
900
901         out.close()
902
903 #
904 ##########
905
906 # --------------------------------------------------------
907 # --------------------------------------------------------
908 # BEGIN NT SPECIFIC PROCEDURES
909 # --------------------------------------------------------
910 # --------------------------------------------------------
911
912 # Return the name of the mutatee executable for this rungroup
913 # (Based on compiler name, NOT compiler executable name
914 def mutatee_filename_nt(rungroup, compilers):
915         if rungroup['mutatee'] == 'none':
916                 retval = ""
917         else:
918                 compiler = compilers[rungroup['compiler']]
919                 mutatee = rungroup['mutatee']
920                 bto = fullspec_cto_component_nt(compiler,
921                                                                          rungroup['abi'],
922                                                                          rungroup['optimization'])
923                 platform = find_platform(os.environ.get('PLATFORM'))
924                 es = platform['filename_conventions']['executable_suffix']
925                 retval = "%s_mutatee_solo%s%s" % (mutatee, bto, es)
926         return retval
927
928
929
930 # These functions are duplicated because the compiler NAME, not executable name,
931 # needs to be used for windows, since the exec. name is the same for both c and c++
932 def mutatee_cto_component_nt(mutatee):
933    compiler = info['compilers'][mutatee['compiler']]
934    return fullspec_cto_component_nt(compiler,
935                           mutatee['abi'],
936                           mutatee['optimization'])
937
938 def auxcomp_cto_component_nt(compiler, mutatee):
939    return fullspec_cto_component_nt(compiler,
940                           mutatee['abi'],
941                           mutatee['optimization'])
942
943 def fullspec_cto_component_nt(compiler, abi, optimization):
944    def reverse_lookup(dict, value):
945       for key in dict:
946          if dict[key] == value:
947             return key
948       raise ValueError
949
950    retval = "_%s_%s_%s" % (reverse_lookup(info['compilers'], compiler),
951                      abi,
952                      optimization)
953    return retval
954
955 def mutatee_binary_nt(mutatee):
956         # Returns standard name for the solo mutatee binary for this mutatee
957         # (for windows)
958         platform = find_platform(os.environ.get('PLATFORM'))
959         es = platform['filename_conventions']['executable_suffix']
960         return "%s_mutatee_solo%s%s" % (mutatee['name'],
961                 mutatee_cto_component_nt(mutatee),
962                 es)
963
964
965 def group_ok_for_module(g, m):
966         tests_in_group = filter(lambda t: t['mutatee'] == g['mutatee'], info['tests'])
967         if(filter(lambda t: m == t['module'], tests_in_group) == []):
968                 return 'false'
969         else:
970                 return 'true'
971
972 #TODO this function has literally one line differnet from the non _nt version.
973 #     merge?
974 def write_test_info_new_gen_nt(filename, tuplefile):
975         header = """/* This file automatically generated from test specifications.  See
976  * specification/spec.pl and specification/makemake.py
977  */
978
979 #include "test_info_new.h"
980 """
981         read_tuples(tuplefile)
982         compilers = info['compilers']
983         rungroups = info['rungroups']
984         out = open(filename, "w")
985         out.write(header)
986         modules = uniq(map(lambda t: t['module'], info['tests']))
987         for m in modules:
988                 out.write("void initialize_mutatees_%s(std::vector<RunGroup *> &tests);\n" % m)
989         out.write("void initialize_mutatees(std::vector<RunGroup *> &tests) {")
990         for m in modules:
991                 out.write("  initialize_mutatees_%s(tests);" % m)
992         out.write("}")
993         for m in modules:
994                 print_initialize_mutatees_nt(out, filter(lambda g: group_ok_for_module(g, m) == 'true', rungroups), compilers, m)
995         out.close()
996
997 def test_ok_for_module(test, module):
998         tests = info['tests']
999         if(len(filter (lambda t: t['name'] == test and t['module'] == module, tests)) > 0):
1000                 return 'true'
1001         return 'false'
1002
1003 def print_initialize_mutatees_nt(out, rungroups, compilers, module):
1004 # in visual studio 2003, exceeding 1920 'exception states' causes the compiler to crash.
1005 # from what I can tell, each instantation of an object creates an 'exception case,' so
1006 # the workaround is to instantiate dynamically
1007         header = """
1008 // Now we insert the test lists into the run groups
1009 void initialize_mutatees_%s(std::vector<RunGroup *> &tests) {
1010         unsigned int group_count = 0;
1011         // Keep track of which element each test is, for later use with the resumelog
1012         unsigned int test_count;
1013         RunGroup *rg;
1014 """ % module
1015         out.write(header)
1016         platform = find_platform(os.environ.get('PLATFORM'))
1017         LibSuffix = platform['filename_conventions']['library_suffix']
1018
1019         rungroup_params = []
1020         test_params = []
1021         tests = info['tests']
1022         # TODO Change these to get the string conversions from a tuple output
1023         for group in rungroups:
1024                 compiler = info['compilers'][group['compiler']]
1025                 if compiler['presencevar'] == 'true':
1026                         presencevar = 'true'
1027                 else:
1028                         presencevar = 'false'
1029                 mutatee_name = mutatee_filename_nt(group, compilers)
1030                 if group['start_state'] == 'stopped':
1031                         state_init = 'STOPPED'
1032                 elif group['start_state'] == 'running':
1033                         state_init = 'RUNNING'
1034                 else: # Assuming 'selfstart'
1035                         state_init = 'SELFSTART'
1036                 if group['run_mode'] == 'createProcess':
1037                         attach_init = 'CREATE'
1038                 else: # Assuming 'useAttach'
1039                         attach_init = 'USEATTACH'
1040                 if group['groupable'] == 'true':
1041                         ex = 'false'
1042                 else:
1043                         ex = 'true'
1044
1045                 group_empty = 'true'
1046                 for test in group['tests']:
1047                         if(test_ok_for_module(test, module) == 'false'):
1048                                 continue
1049                         group_empty = 'false'
1050                         # Set the tuple string for this test
1051                         # (<test>, <mutatee compiler>, <mutatee optimization>, <create mode>)
1052                         # I need to get the mutator that this test maps to..
1053                         mutator = test_mutator(test)
1054                         ts = build_label(test, mutator, group)
1055                         if test in ['test_serializable']:
1056                                 serialize_enable = 'true'
1057                         else:
1058                                 serialize_enable = 'false'
1059                         test_params.append({'test': test, 'mutator': mutator, 'LibSuffix': LibSuffix, 'serialize_enable' : serialize_enable, 'ts': ts, 'endrungroup': 'false'})
1060                 test_params[-1]['endrungroup'] = 'true'
1061                 if(group_empty == 'false'):
1062                         rungroup_params.append({'presencevar': presencevar, 'mutatee_name': mutatee_name, 'state_init': state_init, 
1063                                 'attach_init': attach_init, 'ex': ex, 'compiler': group['compiler'], 'optimization': group['optimization'],
1064                                 'abi': group['abi']})
1065
1066         body = """struct {
1067
1068     char * mutatee_name;
1069     start_state_t state_init;
1070     create_mode_t attach_init;
1071     bool ex;
1072     bool presencevar;
1073     char* module;
1074     char* compiler;
1075     char* optimization;
1076     char* abi;
1077   } rungroup_params[] = {"""
1078         out.write(body)
1079
1080         
1081         out.write(' {"%s", %s, %s, %s, %s, "%s", "%s", "%s", "%s"}' % (rungroup_params[0]['mutatee_name'], rungroup_params[0]['state_init'], rungroup_params[0]['attach_init'], rungroup_params[0]['ex'], rungroup_params[0]['presencevar'], module, rungroup_params[0]['compiler'], rungroup_params[0]['optimization'], rungroup_params[0]['abi']))
1082         for i in range(1, len(rungroup_params)):
1083                 out.write(',\n {"%s", %s, %s, %s, %s, "%s", "%s", "%s", "%s"}' % (rungroup_params[i]['mutatee_name'], rungroup_params[i]['state_init'], rungroup_params[i]['attach_init'], rungroup_params[i]['ex'], rungroup_params[i]['presencevar'], module, rungroup_params[i]['compiler'], rungroup_params[i]['optimization'], rungroup_params[i]['abi']))
1084         body = """ };
1085
1086   struct {
1087     bool endrungroup;
1088     const char * iname;
1089     const char * mrname;
1090     const char * isoname;
1091         bool serialize_enable;
1092     const char * ilabel;
1093   } test_params[] = {"""
1094
1095         out.write(body)
1096
1097         out.write(' {%s, "%s", "%s", "%s%s", %s, "%s"}' % (test_params[0]['endrungroup'], test_params[0]['test'], test_params[0]['mutator'], test_params[0]['mutator'], test_params[0]['LibSuffix'], test_params[i]['serialize_enable'], test_params[0]['ts']))
1098         for i in range(1, len(test_params)):
1099                 out.write(',\n {%s, "%s", "%s", "%s%s", %s, "%s"}' % (test_params[i]['endrungroup'], test_params[i]['test'], test_params[i]['mutator'], test_params[i]['mutator'], test_params[i]['LibSuffix'], test_params[i]['serialize_enable'], test_params[i]['ts']))
1100
1101 #TODO presencevar
1102         body = """ };
1103
1104   int tp_index = -1;
1105   for (int i = 0; i < %d; i++) {
1106     test_count = 0;
1107     rg = new RunGroup(rungroup_params[i].mutatee_name, rungroup_params[i].state_init, rungroup_params[i].attach_init, 
1108                         rungroup_params[i].ex, rungroup_params[i].module, rungroup_params[i].compiler, 
1109                         rungroup_params[i].optimization, rungroup_params[i].abi);
1110     
1111     do {
1112       tp_index++;
1113       rg->tests.push_back(new TestInfo(test_count++, test_params[tp_index].iname, test_params[tp_index].mrname, test_params[tp_index].isoname, test_params[tp_index].serialize_enable, test_params[tp_index].ilabel));
1114     } while (tp_index < %d && test_params[tp_index].endrungroup == false);
1115
1116     rg->index = group_count++;
1117     tests.push_back(rg);
1118   }
1119 }
1120 """
1121
1122         out.write(body % (len(rungroup_params), len(test_params)))
1123
1124 # ----------------------------
1125 # nmake.mutators.gen (windows)
1126 # ----------------------------
1127 def print_mutators_list_nt(out, mutator_dict, test_dict):
1128         platform = find_platform(os.environ.get('PLATFORM'))
1129         LibSuffix = platform['filename_conventions']['library_suffix']
1130         ObjSuffix = platform['filename_conventions']['object_suffix']
1131         module_list = []
1132         for t in test_dict:
1133                 module_list.append(t['module'])
1134         module_set = set(module_list)
1135
1136         out.write("######################################################################\n")
1137         out.write("# A list of all the mutators to be compiled\n")
1138         out.write("######################################################################\n\n")
1139         mutator_string = "mutators:"
1140         for mod in module_set:  
1141                 module_tests = filter(lambda t: mod == t['module'], test_dict)
1142                 out.write("%s_MUTATORS = " % (mod))
1143                 mutator_string = "%s $(%s_MUTATORS_SO)" % (mutator_string, mod)
1144                 for t in module_tests:
1145                         out.write("%s " % (t['mutator']))
1146                 out.write("\n\n")
1147                 out.write("%s_MUTATORS_SO = " % (mod))
1148                 for t in module_tests:
1149                         out.write("%s%s " % (t['mutator'], LibSuffix))
1150                 out.write("\n\n")
1151                 out.write("%s_OBJS_ALL_MUTATORS = " % (mod))
1152                 for t in module_tests:
1153                         out.write("%s%s " % (t['mutator'], ObjSuffix))
1154                 out.write("\n\n")
1155         out.write("%s\n\n" % mutator_string)
1156
1157         # Now we'll print out a rule for each mutator..
1158         for mod in module_set:
1159                 module_tests = filter(lambda t: t['module'] == mod, test_dict)
1160                 module_mutators = map(lambda t: t['mutator'], module_tests)
1161                 mutators_for_module = filter(lambda m: m['name'] in module_mutators, mutator_dict)
1162                 for m in mutators_for_module:
1163                         # FIXME Don't hardcode $(LIBTESTSUITE)
1164                         out.write("%s%s: " % (m['name'], LibSuffix))
1165                         # Loop through the files listed in this mutator's source list and
1166                         # add object files corresponding to each to the list of dependencies
1167                         objs = []
1168                         sourcefiles = []
1169                         for s in m['sources']:
1170                                 # Print out the object file for this source file
1171                                 objs.append('%s%s' % (s[0:-len(extension(s))], ObjSuffix))
1172                                 sourcefiles.append('../src/%s/%s' % (mod, s))
1173                                 # TODO proper dependencies
1174                                 out.write("%s $(LIBTESTSUITE)\n" % (reduce(lambda x, y: x + " " + y, objs)))
1175                                 # FIXME Make this one better too.  Right now it's copied straight from
1176                                 # make.module.tmpl
1177                                 out.write("\t$(LINK) $(LDFLAGS) -DLL -out:$@ %s $(MUTATOR_LIBS)\n\n" % (reduce(lambda x, y: x + " " + y, objs)))
1178                         for s, o in zip(sourcefiles, objs):
1179                                 out.write("%s: %s\n" % (o, s))
1180                                 out.write("\t$(CXX) $(CXXFLAGS_NORM) -DDLL_BUILD -c -Fo$@ $**\n\n")
1181
1182
1183
1184 def write_make_mutators_gen_nt(filename, tuplefile):
1185         read_tuples(tuplefile)
1186         mutator_dict = info['mutators']
1187         test_dict = info['tests']
1188         platform = find_platform(os.environ.get('PLATFORM'))
1189         LibSuffix = platform['filename_conventions']['library_suffix']
1190         header = """
1191 # This file is automatically generated by the Dyninst testing system.
1192 # For more information, see core/testsuite/src/specification/makemake.py
1193
1194 """
1195
1196         out = open(filename, "w")
1197         out.write(header)
1198         print_mutators_list_nt(out, mutator_dict, test_dict)
1199         out.close()
1200
1201 # --------------------------------
1202 # --------------------------------
1203 # nmake.solo_mutatee.gen (windows)
1204 # --------------------------------
1205 # --------------------------------
1206
1207 # Print makefile variable initializations for all the compilers used for
1208 # makefiles on this platform
1209 def print_mutatee_comp_defs_nt(out):
1210    out.write("# Define variables for our compilers\n")
1211    pname = os.environ.get('PLATFORM')
1212    # TODO Check that we got a string
1213    comps = filter(lambda c: c != ''
1214                          and pname in info['compilers'][c]['platforms'],
1215                info['compilers'])
1216    for c in comps:
1217       if info['compilers'][c]['presencevar'] != 'true':
1218          out.write("!ifdef %s\n" % (info['compilers'][c]['presencevar']))
1219       out.write('M_%s = %s\n' % (info['compilers'][c]['defstring'], info['compilers'][c]['executable']))
1220       if info['compilers'][c]['presencevar'] != 'true':
1221          out.write("!endif\n")
1222    out.write('\n')
1223
1224 def print_mutatee_rules_nt(out, mutatees, compiler, unique_target_dict, module):
1225         mutatees_for_module = filter(lambda x: get_module(x) == module, mutatees)
1226         mut_names = map(lambda x: mutatee_binary_nt(x), mutatees_for_module)
1227
1228         out.write("######################################################################\n")
1229         out.write("# Mutatees compiled with %s for %s\n" % (mutatees[0]['compiler'], module))
1230         out.write("######################################################################\n\n")
1231         if compiler['presencevar'] != 'true':
1232                 out.write("!ifdef %s\n" % (compiler['presencevar']))
1233                 out.write("# We only want to build these targets if the compiler exists\n")
1234         out.write("%s_SOLO_MUTATEES_%s = " % (module, compiler['defstring']))
1235         for m in mut_names:
1236                 out.write("%s " % (m))
1237         out.write('\n')
1238         if compiler['presencevar'] != 'true':
1239                 out.write("!endif\n")
1240         out.write("\n")
1241         out.write("# Now a list of rules for compiling the mutatees with %s\n\n"
1242                           % (mutatees[0]['compiler']))
1243
1244         pname = os.environ.get('PLATFORM')
1245         platform = find_platform(pname)
1246         ObjSuffix = platform['filename_conventions']['object_suffix']
1247
1248         # this variable is used to keep track of dependency targets. this must
1249         # be done for windows because nmake doesn't have % wildcard support.
1250         # note: this excludes a mutattee's ['preprocessed_sources'][0], since
1251         # this is a special case accounted for in print_patterns_nt
1252         dependency_sources = {}
1253
1254         groups = info['rungroups']
1255
1256         # Write rules for building the mutatee executables from the object files
1257         for (m, n) in zip(mutatees_for_module, mut_names):
1258                 out.write("%s: " % (n))
1259
1260                 group_mutatee_list = filter(has_multiple_tests, groups)
1261                 group_mutatee_list = filter(lambda g: g['mutatee'] == m['name'], group_mutatee_list)
1262                 group_boilerplates = uniq(map(lambda g: g['mutatee'] + '_group.c', group_mutatee_list))
1263                 for bp in group_boilerplates:
1264                         cto = mutatee_cto_component_nt(m)
1265                         out.write("%s " % (replace_extension(bp, "%s%s"
1266                                                          % (cto, ObjSuffix))))
1267
1268                 for f in m['preprocessed_sources']:
1269                         # List all the compiled transformed source files
1270                         # I need to futz with the compiler here to make sure it's correct..
1271                         # FIXME This next line may end up arbitrarily picking the first
1272                         # language from a list of more than one for an extension
1273                         lang = filter(lambda l: extension(f) in l['extensions'],
1274                                                   info['languages'])[0]['name']
1275                         if (lang in compiler['languages']):
1276                                 cto = mutatee_cto_component_nt(m)
1277                                 pps_name = replace_extension(f, "_solo%s%s"
1278                                                                                                         % (cto, ObjSuffix))
1279                                 out.write("%s " % (pps_name))
1280                                 # only add unique elements to the sources dictionary,
1281                                 # and don't add the first one, since it's rule is printed
1282                                 # in print_patterns_nt
1283 #                               if f != m['preprocessed_sources'][0]:
1284                                         # only insert this if it hasn't been accounted for in a
1285                                         # previous invocation of this procedure
1286 #                               try:
1287 #                                       unique_target_dict[pps_name]
1288 #                               except KeyError:
1289 #                                       # only insert it if it's not already in the list
1290 #                                       try:
1291 #                                               dependency_sources[pps_name]
1292 #                                       except KeyError:
1293 #                                               dependency_sources[pps_name] = {'src': f, 'abi': m['abi'],
1294 #                                                       'optimization': m['optimization'], 'suffix': ObjSuffix, 'compiler': compiler}
1295                         else: # Preprocessed file compiled with auxilliary compiler
1296                                 pname = os.environ.get('PLATFORM')
1297                                 # TODO Check that we got a string..
1298                                 platform = find_platform(pname)
1299                                 # TODO Check that we retrieved a platform object
1300                                 aux_comp = platform['auxilliary_compilers'][lang]
1301                                 # TODO Verify that we got a compiler
1302                                 cto = auxcomp_cto_component_nt(info['compilers'][aux_comp], m)
1303                                 out.write("%s " % (replace_extension(f, "_solo%s%s"
1304                                                                                                          % (cto, ObjSuffix))))
1305                                 # TODO
1306                                 # the same try/except block can be duplicated as above, but
1307                                 # I don't think windows ever has preprocessed files compiled
1308                                 # with auxilliary compiler. if it does though, the script
1309                                 # will die here
1310                                 makeshift_die
1311                 # TODO Let's grab the languages used in the preprocessed sources, and
1312                 # save them for later.  We use this to determine which raw sources get
1313                 # compiled with the same options as the preprocessed ones, in the case
1314                 # of a compiler that is used for more than one language (e.g. GCC in
1315                 # tests test1_35 or test_mem)
1316
1317                 # FIXME I'm doing this wrong: the compiler for preprocessed files might
1318                 # not be the compiler that we're testing..
1319                 # Get the compiler..
1320                 maincomp_langs = uniq(info['compilers'][m['compiler']]['languages'])
1321                 pp_langs = uniq(map(lambda x: get_file_lang(x)['name'], m['preprocessed_sources']))
1322                 # So we want to print out a list of object files that go into this
1323                 # mutatee.  For files that can be compiled with m['compiler'], we'll
1324                 # use it, and compile at optimization level m['optimization'].  For
1325                 # other files, we'll just use the appropriate compiler and not worry
1326                 # about optimization levels?
1327                 for f in m['raw_sources']:
1328                         # Figure out whether or not this file can be compiled with
1329                         # m['compiler']
1330                         lang = get_file_lang(f)
1331                         if type(lang) == type([]):
1332                                 lang = lang[0] # BUG This may cause unexpected behavior if more
1333                                                # than one language was returned, but more than
1334                                                            # one language should never be returned
1335                         if lang['name'] in maincomp_langs:
1336                                 # This file is compiled with the main compiler for this mutatee
1337                                 cto = mutatee_cto_component_nt(m)
1338                                 comp = compiler
1339                                 opt = m['optimization']
1340                                 rs_name = replace_extension(f, "%s%s"
1341                                                                                                         % (cto, ObjSuffix))
1342                         else:
1343                                 # This file is compiled with an auxilliary compiler
1344                                 # Find the auxilliary compiler for this language on this
1345                                 # platform
1346                                 # This assumes that there is only one possible auxilliary
1347                                 # compiler for a language ending with the extension of interest
1348                                 # on the platform.  This condition is enforced by sanity checks
1349                                 # in the specification file.
1350                                 aux_comp = platform['auxilliary_compilers'][lang['name']]
1351                                 comp = info['compilers'][aux_comp]
1352                                 opt = 'none'
1353                                 cto = fullspec_cto_component_nt(info['compilers'][aux_comp],
1354                                                                                          m['abi'], 'none')
1355                                 rs_name = replace_extension(f, '%s%s'
1356                                                                                                         % (cto, ObjSuffix))
1357                         out.write("%s " % (rs_name))
1358
1359                         # only insert if it hasn't been accounted for in a previous
1360                         # invocation of this function
1361                         try:
1362                                 unique_target_dict[rs_name]
1363                         except KeyError:
1364                                 try:
1365                                         dependency_sources[rs_name]
1366                                 except KeyError:
1367                                         dependency_sources[rs_name] = {'src': f, 'abi': m['abi'],
1368                                                         'optimization': opt, 'suffix': ObjSuffix, 'compiler': comp, 'groupable': m['groupable']}
1369                 # FIXME Check whether the current compiler compiles C files and if not
1370                 # then use the aux compiler for this platform for the mutatee driver
1371                 # object.
1372                 if 'c' in info['compilers'][m['compiler']]['languages']:
1373                         out.write("mutatee_driver_solo_%s_%s_%s%s\n"
1374                                           % (m['compiler'],
1375                                                  m['abi'], m['optimization'], ObjSuffix))
1376                 else:
1377                         # Get the aux compiler for C on this platform and use it
1378                         aux_c = find_platform(os.environ.get('PLATFORM'))['auxilliary_compilers']['c']
1379                         aux_c = info['compilers'][aux_c]['executable']
1380                         out.write("mutatee_driver_solo_%s_%s_%s%s\n"
1381                                           % (aux_c, m['abi'], m['optimization'], ObjSuffix))
1382                 # Print the actions used to link the mutatee executable
1383                 out.write("\t%s %s -out:$@ $** %s "
1384                                   % (platform['linker'] or "$(M_%s)" % compiler['defstring'],
1385                                          compiler['flags']['link'],
1386                                          compiler['abiflags'][platform['name']][m['abi']]))
1387                 # TODO: libraries
1388                 #for l in m['libraries']:
1389                 # Need to include the required libraries on the command line
1390                 # FIXME Use a compiler-specific command-line flag instead of '-l'
1391                 #       out.write("-l%s " % (l))
1392                 out.write('\n')
1393
1394                 # ***ADD NEW BUILD-TIME ACTIONS HERE***
1395
1396         # now write the individual preprocessed source targets
1397         for object, options in dependency_sources.iteritems():
1398                 ObjSuffix = options['suffix']
1399                 src = options['src']
1400                 abi = options['abi']
1401                 o = options['optimization']
1402                 comp = options['compiler']
1403
1404                 if src.startswith("mutatee_util"):
1405                         out.write("%s: ../src/%s\n" % (object, src))
1406                 else:
1407                         out.write("%s: ../src/%s/%s\n" % (object, module, src))
1408                 # FIXME -Dsnprintf=_snprintf is needed for c files that contain snprintf,
1409                 #       but not for .asm files. the masm compiler accepts the -D parameter,
1410                 #       but it's unnecessary
1411                 out.write("\t$(M_%s) %s -Dsnprintf=_snprintf -Fo$@ $**\n"
1412                                         % (comp['defstring'], object_flag_string(platform, comp, abi, o)))
1413
1414                 # now add the object to the unique target list. this prevents the same
1415                 # target from being specified in a different invocation of this function
1416                 unique_target_dict[object] = 1
1417
1418
1419 # Prints generic rules for compiling from mutatee boilerplate
1420 def print_patterns_nt(c, out, module):
1421         out.write("\n# Generic rules for %s's mutatees and varying optimization levels\n" % (c))
1422
1423         compiler = info['compilers'][c]
1424         platform = find_platform(os.environ.get('PLATFORM'))
1425         ObjSuffix = platform['filename_conventions']['object_suffix']
1426
1427         
1428         ng_sources = get_all_mutatee_sources('false', module)
1429
1430         g_sources = get_all_mutatee_sources('true', module)
1431
1432         groups = filter(lambda g: group_ok_for_module(g, module) == 'true', info['rungroups'])
1433         group_mutatee_list = filter(has_multiple_tests, groups)
1434         group_boilerplates = uniq(map(lambda g: g['mutatee'] + '_group.c', group_mutatee_list))
1435         for abi in platform['abis']:
1436                 for o in compiler['optimization']:
1437                         # Rules for compiling source files to .o files
1438                         cto = fullspec_cto_component_nt(compiler, abi, o)
1439
1440                         #FIXME this prints out one rule for every mutatee preprocessed source for EVERY optimization
1441                         #      I don't know whether the previous targets require every combination of source/opt
1442                         #      i.e. printing ALL of them may be superfluous
1443                         for sourcefile in ng_sources:
1444                                 ext = extension(sourcefile)
1445                                 boilerplate = "solo_mutatee_boilerplate" + ext
1446                                 basename = sourcefile[0:-len('_mutatee') - len(ext)]
1447
1448                                 out.write("%s_mutatee_solo%s%s: ../src/%s\n"
1449                                                 % (basename, cto, ObjSuffix, boilerplate))
1450                                 out.write("\t$(M_%s) %s -DTEST_NAME=%s -DGROUPABLE=0 -DMUTATEE_SRC=../src/%s/%s -Fo$@ $**\n"
1451                                                 % (compiler['defstring'],
1452                                                    object_flag_string(platform, compiler, abi, o),
1453                                                    basename, module, sourcefile))
1454
1455                         for sourcefile in g_sources:
1456                                 ext = extension(sourcefile)
1457                                 boilerplate = "solo_mutatee_boilerplate" + ext
1458                                 basename = sourcefile[0:-len('_mutatee') - len(ext)]
1459
1460                                 out.write("%s_mutatee_solo%s%s: ../src/%s\n"
1461                                                 % (basename, cto, ObjSuffix, boilerplate))
1462                                 out.write("\t$(M_%s) %s -DTEST_NAME=%s -DGROUPABLE=1 -DMUTATEE_SRC=../src/%s/%s -Fo$@ $**\n"
1463                                                 % (compiler['defstring'],
1464                                                    object_flag_string(platform, compiler, abi, o),
1465                                                    basename, module, sourcefile))
1466
1467
1468                         for sourcefile in group_boilerplates:
1469                                 ext = extension(sourcefile)
1470                                 basename = sourcefile[0:-len(ext)]
1471                                 out.write("%s%s%s: ../%s/%s\n" % (basename, cto, ObjSuffix, os.environ.get('PLATFORM'), sourcefile))
1472                                 out.write("\t$(M_%s) $(%s_SOLO_MUTATEE_DEFS) %s -DGROUPABLE=1 -Fo$@ $**\n" 
1473                                         % (compiler['defstring'], module, 
1474                                         object_flag_string(platform, compiler, abi, o)))
1475                         for l in compiler['languages']: 
1476                                 lang = find_language(l) # Get language dictionary from name
1477                                 for e in lang['extensions']:
1478                                         # FIXME This generates spurious lines for compilers that
1479                                         # aren't used for this part of the mutatee build system
1480                                         # like .s and .S files for gcc and Fortran files.
1481                                         out.write("%%%s%s: {../src/%s/}%%%s\n"
1482                                                           % (cto, ObjSuffix, module, e))
1483                                         out.write("\t$(M_%s) %s -Fo$@ $**\n"
1484                                                           % (compiler['defstring'], object_flag_string(platform, compiler, abi, o)))
1485         out.write("\n")
1486
1487 # Main function for generating nmake.solo_mutatee.gen
1488 def write_make_solo_mutatee_gen_nt(filename, tuplefile):
1489         read_tuples(tuplefile)
1490         compilers = info['compilers']
1491         mutatees = info['mutatees']
1492         out = open(filename, "w")
1493         print_mutatee_comp_defs_nt(out)
1494         # vvvvv This one isn't nt specific vvvvv
1495         comps = collect_mutatee_comps(mutatees)
1496         pname = os.environ.get('PLATFORM')
1497         platform = find_platform(pname)
1498         ObjSuffix = platform['filename_conventions']['object_suffix']
1499         unique_target_dict = {}
1500         modules = uniq(map(lambda t: t['module'], info['tests']))
1501         for c in comps:
1502                 # Generate a block of rules for mutatees produced by each compiler
1503                 muts = filter(lambda x: x['compiler'] == c, mutatees)
1504                 for m in modules:
1505                         print_mutatee_rules_nt(out, muts, compilers[c], unique_target_dict, m)
1506                 # Print rules for exceptional object files
1507                 # TODO: don't know if this needs to be done for windows
1508                 #print_special_object_rules(c, out)
1509 # TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO 
1510                 for m in modules:
1511                         print_patterns_nt(c, out, m)
1512                 out.write("# Rules for building the driver and utility objects\n")
1513                 # TODO Replace this code generation with language neutral code
1514                 # generation
1515                 if 'c' in info['compilers'][c]['languages']:
1516                         for abi in platform['abis']:
1517                                 for (opt_level, opt_flag) in compilers[c]['optimization'].items():
1518                                         out.write("mutatee_driver_solo_%s_%s_%s%s: ../src/mutatee_driver.c\n" % (c, abi, opt_level, ObjSuffix))
1519                                         out.write("\t$(M_%s) %s %s %s %s -Dsnprintf=_snprintf -Fo$@ -c $**\n"
1520                                                           % (compilers[c]['defstring'],
1521                                                                  compilers[c]['flags']['std'],
1522                                                                  compilers[c]['flags']['mutatee'],
1523                                                                  opt_flag,
1524                                                                  compilers[c]['abiflags'][platform['name']][abi]))
1525                                         # TODO: find where these files live in our data structures
1526                                         # and remove the hardcoding!
1527
1528                 else:
1529                         out.write("# (Skipped: driver and utility objects cannot be compiled with this compiler\n")
1530
1531         # Print pattern rules for this platform's auxilliary compilers
1532         #print_aux_patterns(out, platform, comps)
1533
1534         # Print footer (list of targets, clean rules, compiler presence #defines)
1535         for m in modules:
1536                 print_make_solo_mutatee_gen_footer(out, comps, platform, m)
1537         out.write("mutatees: ");
1538         for m in modules:
1539                 out.write("$(%s_SOLO_MUTATEES) " %(m));
1540         out.write("\n");
1541         out.close()