Advertisement
ebak32

doit source generator 2

Mar 4th, 2016
94
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.84 KB | None | 0 0
  1. #!/usr/bin/python
  2. import os
  3. import subprocess
  4. import hashlib
  5. from doit import create_after
  6. from doit.action import CmdAction
  7. from doit.tools import result_dep, create_folder
  8. from doit.task import clean_targets
  9. from fnmatch import fnmatch
  10.  
  11. DOIT_CONFIG = {
  12.     'verbosity': 2,
  13.     'default_tasks': ['All']}
  14.  
  15. CPPFLAGS = '-Wall -std=c++11 -Iinc'    # common for all .cpp related rules
  16. LDFLAGS = ''
  17.  
  18. def getCppSources(srcPath):
  19.     res = []
  20.     for dirPath, dirNames, fileNames in os.walk(srcPath):
  21.         for fileName in fileNames:
  22.             if fnmatch(fileName, '*.cpp'):
  23.                 res.append(os.path.join(dirPath, fileName))
  24.     return res
  25.  
  26. def getObjPath(cppPath, objDir):
  27.     name, _ = os.path.splitext(os.path.basename(cppPath))
  28.     return os.path.join(objDir, name + '.o')
  29.  
  30. CPP_SOURCES = getCppSources('src')
  31. RELEASE_OBJS = [getObjPath(src, 'obj/release') for src in CPP_SOURCES]
  32. DEBUG_OBJS = [getObjPath(src, 'obj/debug') for src in CPP_SOURCES]
  33. GEN_CPP_SOURCES = []
  34. GEN_RELEASE_OBJS = []
  35. GEN_DEBUG_OBJS = []
  36.  
  37.  
  38. def createLinkCommand(target, objs, ldFlags=LDFLAGS):
  39.     return 'g++ {flags} {objs} -o {target}'.format(
  40.         flags=ldFlags, objs=' '.join(objs), target=target)
  41.  
  42. PreProcDict = {}    # {sourcePath: preprocessed_output} TODO: make it thread safe
  43.  
  44.  
  45. def cppUpToDate(task, values, source, flags):
  46.     def save_now():
  47.         return {'inputHash': inputHash}
  48.     # print 'cppUpToDate\ntask:{}\nvalues:{}\ntask.values:{}\nsource:{}'.format(task, values, task.values, source)
  49.     # -P makes clean preprocessor output
  50.     # content = cppPreprocess(task.name, source, flags)
  51.     content = subprocess.check_output(
  52.         'g++ -E {} {}'.format(flags, source), shell=True)
  53.     m = hashlib.md5()
  54.     m.update(content)
  55.     inputHash = m.hexdigest()
  56.     task.value_savers.append(save_now)
  57.     oldHash = values.get('inputHash', None)
  58.     # print '{} {} <- {}'.format(task.name, inputHash, oldHash)
  59.     if os.path.exists(task.name) and inputHash == oldHash:
  60.         return True
  61.     PreProcDict[task.name] = content
  62.     return False
  63.  
  64. def cppBuildAction(flags, targets):
  65.     obj = targets[0]
  66.     create_folder(os.path.dirname(obj))
  67.     content = PreProcDict[obj]
  68.     proc = subprocess.Popen(
  69.         'g++ -c {flags} -o {obj} -x c++-cpp-output -'.format(flags=flags, obj=obj), shell=True, stdin=subprocess.PIPE)
  70.     proc.stdin.write(content)
  71.     proc.stdin.close()
  72.     proc.wait()
  73.     PreProcDict[obj] = None
  74.     return proc.returncode == 0
  75.  
  76.  
  77. def createCompileRule(obj, source, flags):
  78.     allFlags = CPPFLAGS + ' ' + flags
  79.     return {
  80.         'basename': obj,
  81.         'actions': [
  82.             (cppBuildAction, [allFlags])],
  83.         'uptodate': [(cppUpToDate, [source, allFlags])],
  84.         'targets': [obj],
  85.         'file_dep': [source],
  86.         'clean': True}
  87.  
  88.  
  89. def task_objs():
  90.     for debugObj, releaseObj, source in zip(DEBUG_OBJS, RELEASE_OBJS, CPP_SOURCES):
  91.         yield createCompileRule(debugObj, source, '-g')
  92.         yield createCompileRule(releaseObj, source, '-O2')
  93.  
  94.  
  95. @create_after(executed='generator')
  96. def task_generatedObjs():
  97.     print 'task_generatedObjs() started'
  98.     for debugObj, releaseObj, source in zip(GEN_DEBUG_OBJS, GEN_RELEASE_OBJS, GEN_CPP_SOURCES):
  99.         print '{} {}'.format(debugObj, releaseObj)
  100.         yield createCompileRule(debugObj, source, '-g')
  101.         yield createCompileRule(releaseObj, source, '-O2')
  102.        
  103.  
  104. def task_generator():
  105.  
  106.     def generateAction():
  107.         global GEN_CPP_SOURCES
  108.         global GEN_RELEASE_OBJS
  109.         global GEN_DEBUG_OBJS
  110.         print 'generator running'
  111.         with open('cfg/sample.cfg') as f:
  112.             cfg = f.read()
  113.         GEN_CPP_SOURCES = []
  114.         for i, line in enumerate(cfg.splitlines()):
  115.             fName, str = line.split(':')
  116.             fPath = 'gen/{}.cpp'.format(fName)
  117.             GEN_CPP_SOURCES.append(fPath)
  118.             with open(fPath, 'w') as f:
  119.                 f.write('const char * const str{} = "{}";'.format(i, str))
  120.         GEN_RELEASE_OBJS = [getObjPath(src, 'obj/release') for src in GEN_CPP_SOURCES]
  121.         GEN_DEBUG_OBJS = [getObjPath(src, 'obj/debug') for src in GEN_CPP_SOURCES]
  122.         return True
  123.                
  124.     # uptodate is not yet implemented
  125.     return {
  126.         'basename': 'generator',
  127.         'actions': [(create_folder, ['gen']), generateAction],
  128.         'targets': ['generator'],
  129.         'clean': True}
  130.    
  131.  
  132. def task_generatedDep():
  133.    
  134.     def getDep(kind):
  135.         print 'getDep({})'.format(kind)
  136.         fileDep = GEN_RELEASE_OBJS if kind == 'release' else GEN_DEBUG_OBJS
  137.         print 'fileDep={}'.format(fileDep)
  138.         return {
  139.             'file_dep': fileDep,
  140.             'task_dep': ['generatedObjs']}
  141.    
  142.     for kind in ('release', 'debug'):
  143.         yield {
  144.             'name': kind,
  145.             'setup': ['generator'],
  146.             'actions': [(getDep,[kind])],
  147.             'clean': True}
  148.  
  149.  
  150. def linkAction(task):
  151.     print "linkAction(targets:{}, file_dep:{}".format(task.targets, task.file_dep)
  152.     retVal = subprocess.call(
  153.         createLinkCommand(target=task.targets[0], objs=task.file_dep), shell=True)
  154.     return retVal == 0
  155.  
  156.  
  157. def task_link():
  158.     for kind, objs in (('release', RELEASE_OBJS), ('debug', DEBUG_OBJS)):
  159.         target = kind + '.bin'
  160.         yield {
  161.             'basename': target,
  162.             'actions': [linkAction], #[CmdAction(createLinkCommand(target=target, objs=objs))],
  163.             'targets': [target],
  164.             # 'task_dep': ['generator'],
  165.             'file_dep': objs,
  166.             'calc_dep': [ 'generatedDep:' + kind],
  167.             'clean': True}
  168.  
  169.  
  170. def task_main():
  171.     yield {
  172.         'basename': 'All',
  173.         'actions': [],
  174.         # 'task_dep': ['generator'],
  175.         'file_dep': ['release.bin', 'debug.bin'],
  176.         'clean': True}
  177.  
  178.  
  179. if __name__ == '__main__':
  180.     import doit
  181.     doit.run(globals())
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement