Guest
Public paste!

MHordecki

By: a guest | Jan 16th, 2008 | Syntax: Python | Size: 7.42 KB | Hits: 40 | Expires: Never
Copy text to clipboard
  1. #!/usr/bin/python
  2. # $Id: build.py 21 2008-01-16 13:08:31Z mhordecki $
  3. # $Author: mhordecki $
  4. # $LastChangedDate: 2008-01-16 13:08:31 +0000 (Wed, 16 Jan 2008) $
  5. # $LastChangedRevision: 21 $
  6. # $LastChangedBy: mhordecki $
  7. #
  8. #######################################
  9. #
  10. #             Build.py v. 0.3beta
  11. #
  12. # Copyright (c) 2008 Michal Hordecki
  13. #    Licensed under GNU GPLv3
  14. #
  15. #######################################
  16.  
  17. from optparse import OptionParser
  18. import sys
  19. import os
  20. import shutil
  21. import pickle
  22. import hashlib
  23.  
  24.  
  25. def _pkgconfig_check():
  26.         global PKGCONFIG_LIBS
  27.         if len(PKGCONFIG_LIBS)==0: return true
  28. def _pkgconfig_cflags():
  29.         if len(PKGCONFIG_LIBS)==0: return ''
  30.         pkgc='`pkg-config --cflags '
  31.         for i in PKGCONFIG_LIBS:
  32.                 pkgc+=i+' '
  33.         pkgc+='` '
  34.         return pkgc
  35.  
  36. def _pkgconfig_libs():
  37.         if len(PKGCONFIG_LIBS)==0: return ''
  38.         pkgc='`pkg-config --libs '
  39.         for i in PKGCONFIG_LIBS:
  40.                 pkgc+=i+' '
  41.         pkgc+='` '
  42.         return pkgc
  43.  
  44. #### BUILDFILE MACROS
  45. X=0
  46. ACT_TARGET=''
  47. EXT={}
  48. FILES={}
  49. DATA=[]
  50. LINKER=''
  51. PKGCONFIG_LIBS=[]
  52. PREFIX='/usr'
  53. _SHAREDIR=''
  54. STEP=''
  55. FLAGS={}
  56. INCLUDE={}
  57. LIBS=[]
  58. #private
  59. LOG=[]
  60. LOCLOG={}
  61. def _save_progress():
  62.         global LOCLOG
  63.         f=open('.buildpy.tmp','w+')
  64.         pickle.dump(LOCLOG,f)
  65.         f.close()
  66. def _load_progress():
  67.         global LOCLOG
  68.         if not os.path.exists('.buildpy.tmp'):
  69.                 LOCLOG={}
  70.                 return
  71.         f=open('.buildpy.tmp')
  72.         LOCLOG=pickle.load(f)
  73.         f.close()
  74. def _file_calc_hash(p):
  75.         f=open(p)
  76.         return hashlib.md5(f.read()).hexdigest()
  77. def _fmt_libs():
  78.         global LIBS
  79.         ret=''
  80.         for l in LIBS:
  81.                 ret+='-l'+l+' '
  82.         return ret
  83. def _fmt_include(c):
  84.         global INCLUDE
  85.         ret=''
  86.         if not c in INCLUDE: return ''
  87.         for l in INCLUDE[c]:
  88.                 ret+='-I'+l+' '
  89.         return ret
  90. def target(t):
  91.         TARGET='target_'+t
  92.         eval(TARGET)()
  93. def clean(t):
  94.         CLEAN='clean_'+t
  95.         target(t)
  96.         eval(CLEAN)()
  97. def build(t):
  98.         BUILD='build_'+t
  99.         target(t)
  100.         eval(BUILD)()
  101. def install(t):
  102.         INSTALL='install_'+t
  103.         target(t)
  104.         eval(INSTALL)()
  105. def remove(t):
  106.         REMOVE='remove_'+t
  107.         target(t)
  108.         eval(REMOVE)()
  109. def assign_c(c):
  110.         EXT['c']=c
  111.         FILES[c]=[]
  112. def assign_cxx(c):
  113.         EXT['cpp']=c
  114.         EXT['cxx']=c
  115.         FILES[c]=[]
  116. def add_dir_recursively(c,d):
  117.         if not os.path.exists(d):
  118.                 warning('Given path '+d+' does not exist.')
  119.         if c=='source':
  120.                 for root, dirs, files in os.walk(d):
  121.                         for file in files:
  122.                                 if root.find('/.')!=-1: continue #checking against hidden folders
  123.                                 ext=os.path.splitext(file)[1][1:]
  124.                                 if not EXT.has_key(ext):
  125.                                         print 'Found ',root+os.sep+file,'- ommitting'
  126.                                 else:
  127.                                         print 'Found ',root+os.sep+file
  128.                                         FILES[EXT[ext]].append(root+os.sep+file)
  129.         elif c=='data':
  130.                 for root, dirs, files in os.walk(d):
  131.                         for file in files:
  132.                                 if root.find('/.')!=-1: continue #checking against hidden folders
  133.                                 print 'Found data file',root+os.sep+file
  134.                                 DATA.append(root+os.sep+file)
  135.  
  136.         else:
  137.                 warning('Unrecongized add_dir_recursively category.')
  138.  
  139. def process_build():
  140.         global OBJ,LOCLOG,FLAGS,LIBS
  141.         OBJ=[]
  142.         libstr=_fmt_libs()
  143.         print "Building.."
  144.         _load_progress()
  145.         if not os.path.exists('obj'):
  146.                 os.mkdir('obj')
  147.         if not os.path.exists('bin'):
  148.                 os.mkdir('bin')
  149.         for c in FILES:
  150.                 print 'Using',c
  151.                 incstr=_fmt_include(c)
  152.                 for f in FILES[c]:                     
  153.                         objpath=os.path.splitext(f)[0]+'.o '
  154.                         if f in LOCLOG:
  155.                                 if LOCLOG[f]==_file_calc_hash(f):
  156.                                         OBJ.append(objpath)
  157.                                         continue
  158.                         cmd=c+' '+incstr
  159.                         if c in FLAGS:
  160.                                 cmd+=FLAGS[c]+' '
  161.                         cmd+=' -c '
  162.                         cmd+=f+' '
  163.                         cmd+='-o'
  164.                         cmd+=objpath
  165.                         cmd+=_pkgconfig_cflags()
  166.                         print cmd
  167.                         if os.system(cmd)!=0:
  168.                                 _save_progress()
  169.                                 error('Build error, stopping.')
  170.                         OBJ.append(objpath)
  171.                         LOCLOG[f]=_file_calc_hash(f)
  172.  
  173.         # linking
  174.  
  175.         print 'Linking'
  176.         cmd=LINKER+' '+libstr
  177.         cmd+='-obin/'+ACT_TARGET+' '
  178.         for c in OBJ:
  179.                 cmd+=c+' '
  180.         cmd+=_pkgconfig_libs()
  181.         print cmd
  182.         if os.system(cmd)!=0:
  183.                 error('Linking error, stopping.')
  184.         _save_progress()
  185.         print "Finished building",ACT_TARGET
  186.  
  187. def start_install():
  188.         global SHAREDIR,_SHAREDIR,LOG
  189.         _SHAREDIR=SHAREDIR
  190.         print 'Installing',ACT_TARGET
  191.         SHAREDIR=os.path.join(SHAREDIR,ACT_TARGET)
  192.         LOG=[]
  193.  
  194. def end_install():
  195.         global SHAREDIR,_SHAREDIR,LOG
  196.         LOG.append(SHAREDIR)
  197.         print 'Creating log file'
  198.         f=open(os.path.join(SHAREDIR,'.buildpy.log'),'w+')
  199.         pickle.dump(LOG,f)
  200.         f.close()
  201.         SHAREDIR=_SHAREDIR
  202.         print 'Finshed',ACT_TARGET
  203.  
  204. def copy(s,dest):
  205.         global DATA,SHAREDIR,LOG
  206.         if s=='data':
  207.                 for d in DATA:
  208.                         destdir=os.path.join(dest,os.path.split(d)[0])
  209.                         if not os.path.exists(destdir):
  210.                                 os.makedirs(destdir)
  211.                         cmd='install '+d+' '+destdir+os.sep
  212.                         print cmd
  213.                         LOG.append(os.path.join(destdir,os.path.basename(d)))
  214.                         os.system(cmd)
  215.         else:
  216.                 warning('Bad copy() target.')
  217. def copy_bin(dest,symlink=''):
  218.         global LOG,ACT_TARGET
  219.         cmd='install bin'+os.sep+ACT_TARGET+' '+dest+os.sep
  220.         LOG.append(os.path.join(dest,ACT_TARGET))
  221.         print cmd
  222.         os.system(cmd)
  223.         if symlink!='':
  224.                 cmd='ln -s '+dest+os.sep+ACT_TARGET+' '+symlink+os.sep+ACT_TARGET
  225.                 LOG.append(os.path.join(symlink,ACT_TARGET))
  226.                 print cmd
  227.                 os.system(cmd)
  228.                
  229. def _recursive_del(d):
  230.         if not os.path.exists(d): return
  231.         for root, dirs, files in os.walk(d, topdown=False):
  232.                 for name in files:
  233.                         os.remove(os.path.join(root, name))
  234.                 for name in dirs:
  235.                         os.rmdir(os.path.join(root, name))
  236.         os.rmdir(d)
  237.  
  238. def process_clean():
  239.         _recursive_del('bin')
  240.         if os.path.exists('.buildpy.tmp'):
  241.                 os.remove('.buildpy.tmp')
  242.  
  243.         for c in FILES:
  244.                 for f in FILES[c]:
  245.                         objpath=os.path.splitext(f)[0]+'.o'
  246.                         if os.path.exists(objpath):
  247.                                 print objpath
  248.                                 os.remove(objpath)
  249.  
  250.         print 'Finished cleaning'
  251.  
  252. def process_remove(dir):
  253.         global ACT_TARGET
  254.         dir=os.path.join(dir,ACT_TARGET,'.buildpy.log')
  255.         print 'Removing',ACT_TARGET
  256.         f=open(dir)
  257.         log=pickle.load(f)
  258.         f.close()
  259.         for f in log:
  260.                 if os.path.isdir(f):
  261.                         _recursive_del(f)
  262.                 else:
  263.                         os.remove(f)
  264.         print 'Finished removing',ACT_TARGET
  265.  
  266.  
  267. #### BUILD.PY CODE
  268.  
  269. def die(text):
  270.         print text
  271.         exit()
  272. def error(text):
  273.         print 'ERROR :',text
  274.         exit()
  275. def warning(text):
  276.         print 'WARNING :',text
  277.  
  278.  
  279.  
  280. opts=OptionParser(version='%prog 0.1', usage="%prog [TARGET] [OPTIONS]", description='Simple build tool written in Python. Useful in small projects where overbloated features of make, jam & co are unnecessary. build.py uses external configuration files called buildfiles, similar to Makefiles and Jamfiles. See docs for more info.')
  281.  
  282. opts.set_defaults(file='Buildfile')
  283. opts.add_option('-f','--file',dest='file',help='set buildfile path. Default : \'buildfile\'')
  284.  
  285. """opts.add_option('-G','--Get',action='store_const',const='G',dest='mode',help='Get mangas from server')
  286. opts.add_option('-Q','--Query',action='store_const',const='Q',dest='mode',help='Query info about mangas from server')
  287. opts.add_option('-m','--manga',dest='manga',help='Select manga which has NAME as a keyword (See also -Q option)',metavar='NAME')
  288. opts.add_option('-c','--chapter',dest='chapter',help='Query/get manga from chapter specified by NUM',metavar="NUM")
  289. opts.add_option('-r','--range',dest='range',help='Query/get range of chapters specified by RANGE (format: START-END)',metavar="RANGE")
  290. opts.add_option('-a','--all',action="store_true",dest='all',help='Query/get all chapters of manga')
  291. """
  292. TARGETS=[]
  293.  
  294. opt=opts.parse_args(sys.argv[1:])
  295. opt=opt[0]
  296.  
  297. for a in sys.argv[1:]:
  298.         if a[0]=='-': break
  299.         TARGETS.append(a)
  300.  
  301. if len(TARGETS)==0:
  302.         TARGETS=['build']
  303.  
  304. if not os.path.exists(opt.file):
  305.         error('Buildfile '+opt.file+' does not exist.')
  306.  
  307. execfile(opt.file)
  308. for t in TARGETS:
  309.         target(t)