Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python
- import os
- import subprocess
- import hashlib
- from doit import create_after
- from doit.action import CmdAction
- from doit.tools import result_dep, create_folder
- from doit.task import clean_targets
- from fnmatch import fnmatch
- DOIT_CONFIG = {
- 'verbosity': 2,
- 'default_tasks': ['All']}
- CPPFLAGS = '-Wall -std=c++11 -Iinc' # common for all .cpp related rules
- LDFLAGS = ''
- def getCppSources(srcPath):
- res = []
- for dirPath, dirNames, fileNames in os.walk(srcPath):
- for fileName in fileNames:
- if fnmatch(fileName, '*.cpp'):
- res.append(os.path.join(dirPath, fileName))
- return res
- def getObjPath(cppPath, objDir):
- name, _ = os.path.splitext(os.path.basename(cppPath))
- return os.path.join(objDir, name + '.o')
- CPP_SOURCES = getCppSources('src')
- RELEASE_OBJS = [getObjPath(src, 'obj/release') for src in CPP_SOURCES]
- DEBUG_OBJS = [getObjPath(src, 'obj/debug') for src in CPP_SOURCES]
- GEN_CPP_SOURCES = []
- GEN_RELEASE_OBJS = []
- GEN_DEBUG_OBJS = []
- def createLinkCommand(target, objs, ldFlags=LDFLAGS):
- return 'g++ {flags} {objs} -o {target}'.format(
- flags=ldFlags, objs=' '.join(objs), target=target)
- PreProcDict = {} # {sourcePath: preprocessed_output} TODO: make it thread safe
- def cppUpToDate(task, values, source, flags):
- def save_now():
- return {'inputHash': inputHash}
- # print 'cppUpToDate\ntask:{}\nvalues:{}\ntask.values:{}\nsource:{}'.format(task, values, task.values, source)
- # -P makes clean preprocessor output
- # content = cppPreprocess(task.name, source, flags)
- content = subprocess.check_output(
- 'g++ -E {} {}'.format(flags, source), shell=True)
- m = hashlib.md5()
- m.update(content)
- inputHash = m.hexdigest()
- task.value_savers.append(save_now)
- oldHash = values.get('inputHash', None)
- # print '{} {} <- {}'.format(task.name, inputHash, oldHash)
- if os.path.exists(task.name) and inputHash == oldHash:
- return True
- PreProcDict[task.name] = content
- return False
- def cppBuildAction(flags, targets):
- obj = targets[0]
- create_folder(os.path.dirname(obj))
- content = PreProcDict[obj]
- proc = subprocess.Popen(
- 'g++ -c {flags} -o {obj} -x c++-cpp-output -'.format(flags=flags, obj=obj), shell=True, stdin=subprocess.PIPE)
- proc.stdin.write(content)
- proc.stdin.close()
- proc.wait()
- PreProcDict[obj] = None
- return proc.returncode == 0
- def createCompileRule(obj, source, flags):
- allFlags = CPPFLAGS + ' ' + flags
- return {
- 'basename': obj,
- 'actions': [
- (cppBuildAction, [allFlags])],
- 'uptodate': [(cppUpToDate, [source, allFlags])],
- 'targets': [obj],
- 'file_dep': [source],
- 'clean': True}
- def task_objs():
- for debugObj, releaseObj, source in zip(DEBUG_OBJS, RELEASE_OBJS, CPP_SOURCES):
- yield createCompileRule(debugObj, source, '-g')
- yield createCompileRule(releaseObj, source, '-O2')
- @create_after(executed='generator')
- def task_generatedObjs():
- print 'task_generatedObjs() started'
- for debugObj, releaseObj, source in zip(GEN_DEBUG_OBJS, GEN_RELEASE_OBJS, GEN_CPP_SOURCES):
- print '{} {}'.format(debugObj, releaseObj)
- yield createCompileRule(debugObj, source, '-g')
- yield createCompileRule(releaseObj, source, '-O2')
- def task_generator():
- def generateAction():
- global GEN_CPP_SOURCES
- global GEN_RELEASE_OBJS
- global GEN_DEBUG_OBJS
- print 'generator running'
- with open('cfg/sample.cfg') as f:
- cfg = f.read()
- GEN_CPP_SOURCES = []
- for i, line in enumerate(cfg.splitlines()):
- fName, str = line.split(':')
- fPath = 'gen/{}.cpp'.format(fName)
- GEN_CPP_SOURCES.append(fPath)
- with open(fPath, 'w') as f:
- f.write('const char * const str{} = "{}";'.format(i, str))
- GEN_RELEASE_OBJS = [getObjPath(src, 'obj/release') for src in GEN_CPP_SOURCES]
- GEN_DEBUG_OBJS = [getObjPath(src, 'obj/debug') for src in GEN_CPP_SOURCES]
- return True
- # uptodate is not yet implemented
- return {
- 'basename': 'generator',
- 'actions': [(create_folder, ['gen']), generateAction],
- 'targets': ['generator'],
- 'clean': True}
- def task_generatedDep():
- def getDep(kind):
- print 'getDep({})'.format(kind)
- fileDep = GEN_RELEASE_OBJS if kind == 'release' else GEN_DEBUG_OBJS
- print 'fileDep={}'.format(fileDep)
- return {
- 'file_dep': fileDep,
- 'task_dep': ['generatedObjs']}
- for kind in ('release', 'debug'):
- yield {
- 'name': kind,
- 'setup': ['generator'],
- 'actions': [(getDep,[kind])],
- 'clean': True}
- def linkAction(task):
- print "linkAction(targets:{}, file_dep:{}".format(task.targets, task.file_dep)
- retVal = subprocess.call(
- createLinkCommand(target=task.targets[0], objs=task.file_dep), shell=True)
- return retVal == 0
- def task_link():
- for kind, objs in (('release', RELEASE_OBJS), ('debug', DEBUG_OBJS)):
- target = kind + '.bin'
- yield {
- 'basename': target,
- 'actions': [linkAction], #[CmdAction(createLinkCommand(target=target, objs=objs))],
- 'targets': [target],
- # 'task_dep': ['generator'],
- 'file_dep': objs,
- 'calc_dep': [ 'generatedDep:' + kind],
- 'clean': True}
- def task_main():
- yield {
- 'basename': 'All',
- 'actions': [],
- # 'task_dep': ['generator'],
- 'file_dep': ['release.bin', 'debug.bin'],
- 'clean': True}
- if __name__ == '__main__':
- import doit
- doit.run(globals())
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement