win/wb.py
059739e9
 # Python module containing general build functions
 # for OpenVPN on Windows
 
 import os, re, shutil
 
 autogen = "Automatically generated by OpenVPN Windows build system"
 
 def get_config():
     kv = {}
     parse_version_m4(kv, home_fn('version.m4'))
     parse_settings_in(kv, mod_fn('settings.in'))
 
     # config fixups
     kv['DDKVER'] = os.path.basename(kv['DDK_PATH'])
     kv['DDKVER_MAJOR'] = re.match(r'^(\d+)\.', kv['DDKVER']).groups()[0]
 
     if 'VERSION_SUFFIX' in kv:
         kv['PRODUCT_VERSION'] += kv['VERSION_SUFFIX']
 
     return kv
 
 def mod_fn(fn, src=__file__, real=True):
     p = os.path.join(os.path.dirname(src), os.path.normpath(fn))
     if real:
         p = os.path.realpath(p)
     return p
 
 def home_fn(fn, real=True):
     return mod_fn(os.path.join('..', fn), real=real)
 
 def cd_home():
     os.chdir(os.path.join(os.path.dirname(__file__), '..'))
 
 def system(cmd):
     print "RUN:", cmd
     os.system(cmd)
 
 def parse_version_m4(kv, version_m4):
     r = re.compile(r'^define\((\w+),\[(.*)\]\)$')
     f = open(version_m4)
     for line in f:
         line = line.rstrip()
         m = re.match(r, line)
         if m:
             g = m.groups()
             kv[g[0]] = g[1]
     f.close()
 
 def parse_settings_in(kv, settings_in):
     r = re.compile(r'^!define\s+(\w+)(?:\s+"?(.*?)"?)?$')
     f = open(settings_in)
     for line in f:
         line = line.rstrip()
         m = re.match(r, line)
         if m:
             g = m.groups()
             kv[g[0]] = g[1] or ''
     f.close()
 
 def dict_def(dict, newdefs):
     ret = dict.copy()
     ret.update(newdefs)
     return ret
 
 def build_autodefs(kv, autodefs_in, autodefs_out):
     preprocess(kv,
                in_fn=autodefs_in,
                out_fn=autodefs_out,
                quote_begin='@',
                quote_end='@',
                head_comment='/* %s */\n\n' % autogen)
 
 def preprocess(kv, in_fn, out_fn, quote_begin=None, quote_end=None, if_prefix=None, head_comment=None):
     def repfn(m):
         var, = m.groups()
         return kv.get(var, '')
 
     re_macro = re_ifdef = None
 
     if quote_begin and quote_end:
         re_macro = re.compile(r'%s(\w+)%s' % (re.escape(quote_begin), re.escape(quote_end)))
 
     if if_prefix:
         re_ifdef = re.compile(r'^\s*%sifdef\s+(\w+)\b' % (re.escape(if_prefix),))
         re_else = re.compile(r'^\s*%selse\b' % (re.escape(if_prefix),))
         re_endif = re.compile(r'^\s*%sendif\b' % (re.escape(if_prefix),))
 
     if_stack = []
     fin = open(in_fn)
     fout = open(out_fn, 'w')
     if head_comment:
         fout.write(head_comment)
     for line in fin:
         if re_ifdef:
             m = re.match(re_ifdef, line)
             if m:
                 var, = m.groups()
                 if_stack.append(int(var in kv))
                 continue
             elif re.match(re_else, line):
                 if_stack[-1] ^= 1
                 continue
             elif re.match(re_endif, line):
                 if_stack.pop()
                 continue
         if not if_stack or min(if_stack):
             if re_macro:
                 line = re.sub(re_macro, repfn, line)
             fout.write(line)
     assert not if_stack
     fin.close()
     fout.close()
 
 def print_key_values(kv):
     for k, v in sorted(kv.items()):
         print "%s%s%s" % (k, ' '*(32-len(k)), repr(v))
 
 def get_sources(makefile_am):
     c = set()
     h = set()
     f = open(makefile_am)
     state = False
     for line in f:
         line = line.rstrip()
         if line == 'openvpn_SOURCES = \\':
             state = True
         elif not line:
             state = False
         elif state:
             for sf in line.split():
                 if sf.endswith('.c'):
                     c.add(sf[:-2])
                 elif sf.endswith('.h'):
                     h.add(sf[:-2])
                 elif sf == '\\':
                     pass
                 else:
                     print >>sys.stderr, "Unrecognized filename:", sf
     f.close()
     return [ sorted(list(s)) for s in (c, h) ]
 
 def output_mak_list(title, srclist, ext):
     ret = "%s =" % (title,)
     for x in srclist:
         ret += " \\\n\t%s.%s" % (x, ext)
     ret += '\n\n'
     return ret
 
 def make_headers_objs(makefile_am):
     c, h = get_sources(makefile_am)
     ret = output_mak_list('HEADERS', h, 'h')
     ret += output_mak_list('OBJS', c, 'obj')
     return ret
 
 def choose_arch(arch_name):
     if arch_name == 'x64':
         return (True,)
     elif arch_name == 'x86':
         return (False,)
     elif arch_name == 'all':
         return (True, False)
     else:
         raise ValueError("architecture ('%s') must be x86, x64, or all" % (arch_name,))
 
 def rm_rf(dir):
     print "REMOVE", dir
     shutil.rmtree(dir, ignore_errors=True)
 
 def mkdir(dir):
     print "MKDIR", dir
     os.mkdir(dir)
 
 def cp_a(src, dest, dest_is_dir=True):
     if dest_is_dir:
         dest = os.path.join(dest, os.path.basename(src))
     print "COPY_DIR %s %s" % (src, dest)
     shutil.copytree(src, dest)
 
 def cp(src, dest, dest_is_dir=True):
     if dest_is_dir:
         dest = os.path.join(dest, os.path.basename(src))
     print "COPY %s %s" % (src, dest)
     shutil.copyfile(src, dest)
 
 config = get_config()