From: James Yonan Date: Thu, 22 Apr 2010 12:53:31 +0000 (+0000) Subject: Added Python-based build system for Windows in X-Git-Tag: v2.2-beta1~21 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=059739e9341781d9019e07fc5119367c1630b012;p=thirdparty%2Fopenvpn.git Added Python-based build system for Windows in win directory. Fixed minor issue in TAP driver DEBUG builds where non-null-terminated unicode strings were being printed incorrectly. Version 2.1.1g git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@5577 e7ae566f-a301-0410-adde-c780ea21d3b5 --- diff --git a/INSTALL b/INSTALL index 961fbd608..4c756d296 100644 --- a/INSTALL +++ b/INSTALL @@ -15,9 +15,8 @@ QUICK START: Windows MinGW, using MSYS bash shell: ./domake-win (see comments in the script for more info) - Windows MSVC using Visual Studio 2008 Command Prompt window: - python msvc\config.py - nmake /f msvc\msvc.mak + Windows Visual Studio: + python win\build_all.py ************************************************************************* diff --git a/install-win32/settings.in b/install-win32/settings.in index 643ef99b5..edebd4435 100644 --- a/install-win32/settings.in +++ b/install-win32/settings.in @@ -35,15 +35,15 @@ # tapinstall.exe source code. # Not needed if DRVBINSRC is defined # (or if using pre-built mode). -!define TISRC "../tapinstall" +!define TISRC "../tapinstall/5600" # TAP Adapter parameters. Note that PRODUCT_TAP_ID is # defined in version.m4. !define PRODUCT_TAP_DEVICE_DESCRIPTION "TAP-Win32 Adapter V9" !define PRODUCT_TAP_PROVIDER "TAP-Win32 Provider V9" !define PRODUCT_TAP_MAJOR_VER 9 -!define PRODUCT_TAP_MINOR_VER 6 -!define PRODUCT_TAP_RELDATE "06/22/2009" +!define PRODUCT_TAP_MINOR_VER 7 +!define PRODUCT_TAP_RELDATE "04/19/2010" # TAP adapter icon -- visible=0x81 or hidden=0x89 !define PRODUCT_TAP_CHARACTERISTICS 0x81 @@ -58,7 +58,7 @@ # Code Signing. # If undefined, don't sign any files. -!define SIGNTOOL "../signtool" +!define SIGNTOOL "../signtool.old" !define PRODUCT_SIGN_CN "openvpn" # -j parameter passed to make diff --git a/install-win32/winconfig b/install-win32/winconfig index 9beaca383..9d686c94c 100644 --- a/install-win32/winconfig +++ b/install-win32/winconfig @@ -13,3 +13,6 @@ for g in "h" "sh" "nsi" "in" ; do done cat /dev/null >autodefs/guidefs.nsi + +echo '#include "autodefs/defs.h"' >autodefs.h +echo '#include "config.h"' >>autodefs.h diff --git a/tap-win32/SOURCES.in b/tap-win32/SOURCES.in index 58e4c59c9..b7f0e1828 100755 --- a/tap-win32/SOURCES.in +++ b/tap-win32/SOURCES.in @@ -8,7 +8,7 @@ TARGETNAME=@@PRODUCT_TAP_ID@@ TARGETTYPE=DRIVER TARGETPATH=. TARGETLIBS=$(DDK_LIB_PATH)\ndis.lib $(DDK_LIB_PATH)\ntstrsafe.lib -INCLUDES=$(DDK_INCLUDE_PATH) +INCLUDES=$(DDK_INCLUDE_PATH) .. # The TAP version numbers here must be >= # TAP_WIN32_MIN_x values defined in @@ -53,7 +53,7 @@ MSC_OPTIMIZATION=/Od /Oi /Fc !ENDIF # Generate a linker map file just in case we need one for debugging -LINKER_FLAGS=$(LINKER_FLAGS) /MAP /MAPINFO:EXPORTS /MAPINFO:LINES +LINKER_FLAGS=$(LINKER_FLAGS) /INCREMENTAL:NO /MAP /MAPINFO:EXPORTS # Generate a browser information file for use in IDE development #BROWSER_INFO=1 diff --git a/tap-win32/common.h b/tap-win32/common.h index c8dcd5d76..7ec344045 100755 --- a/tap-win32/common.h +++ b/tap-win32/common.h @@ -28,15 +28,7 @@ // common to both. //=============================================== -#if defined(HAVE_CONFIG_H) -#include "config.h" -#else -#if defined(_MSC_VER) && !defined(TAP_DRIVER_MAJOR_VERSION) -#include "config-win32.h" -#else -#include "../config.h" -#endif -#endif +#include "autodefs.h" //============= // TAP IOCTLs diff --git a/tap-win32/resource.rc b/tap-win32/resource.rc index d7f25a8b9..84884cf1d 100755 --- a/tap-win32/resource.rc +++ b/tap-win32/resource.rc @@ -2,7 +2,6 @@ #include /* get VERSION */ -#include "../config-win32.h" #include "common.h" /* VER_FILETYPE, VER_FILESUBTYPE, VER_FILEDESCRIPTION_STR @@ -36,7 +35,7 @@ #define VER_COMPANYNAME_STR "The OpenVPN Project" #define VER_FILEDESCRIPTION_STR "TAP-Win32 Virtual Network Driver" #define VER_ORIGINALFILENAME_STR TAP_COMPONENT_ID ".sys" -#define VER_LEGALCOPYRIGHT_YEARS "2003-2009" +#define VER_LEGALCOPYRIGHT_YEARS "2003-2010" #define VER_LEGALCOPYRIGHT_STR "OpenVPN Technologies, Inc." @@ -46,7 +45,7 @@ #define XSTR(s) STR(s) #define STR(s) #s -#define VSTRING VERSION " " XSTR(TAP_DRIVER_MAJOR_VERSION) "/" XSTR(TAP_DRIVER_MINOR_VERSION) +#define VSTRING PACKAGE_VERSION " " XSTR(TAP_DRIVER_MAJOR_VERSION) "/" XSTR(TAP_DRIVER_MINOR_VERSION) #ifdef DBG #define VER_PRODUCTVERSION_STR VSTRING " (DEBUG)" diff --git a/tap-win32/tapdrvr.c b/tap-win32/tapdrvr.c index 2c6af4853..49fc3b297 100755 --- a/tap-win32/tapdrvr.c +++ b/tap-win32/tapdrvr.c @@ -35,7 +35,7 @@ // TAP_IOCTL_CONFIG_TUN ioctl. //====================================================== -#include "../../autodefs/defs.h" +#include "common.h" #ifndef DDKVER_MAJOR #error DDKVER_MAJOR must be defined as the major number of the DDK Version #endif @@ -78,7 +78,6 @@ #include "lock.h" #include "constants.h" -#include "common.h" #include "proto.h" #include "error.h" #include "endian.h" @@ -209,7 +208,7 @@ DriverEntry (IN PDRIVER_OBJECT p_DriverObject, TAP_DRIVER_MINOR_VERSION, __DATE__, __TIME__)); - DEBUGP (("Registry Path: '%S'\n", p_RegistryPath->Buffer)); + DEBUGP (("Registry Path: '%.*S'\n", p_RegistryPath->Length/2, p_RegistryPath->Buffer)); break; } @@ -414,7 +413,9 @@ NDIS_STATUS AdapterCreate { if (parm->ParameterType == NdisParameterString) { - DEBUGP (("[TAP] NdisReadConfiguration (MiniportName=%S)\n", parm->ParameterData.StringData.Buffer)); + DEBUGP (("[TAP] NdisReadConfiguration (MiniportName=%.*S)\n", + parm->ParameterData.StringData.Length/2, + parm->ParameterData.StringData.Buffer)); if (RtlUnicodeStringToAnsiString ( &l_Adapter->m_NameAnsi, diff --git a/version.m4 b/version.m4 index e7f1d5832..5723d3c50 100644 --- a/version.m4 +++ b/version.m4 @@ -1,5 +1,5 @@ dnl define the OpenVPN version -define(PRODUCT_VERSION,[2.1.1f]) +define(PRODUCT_VERSION,[2.1.1g]) dnl define the TAP version define(PRODUCT_TAP_ID,[tap0901]) define(PRODUCT_TAP_WIN32_MIN_MAJOR,[9]) diff --git a/win/__init__.py b/win/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/win/autodefs.h.in b/win/autodefs.h.in new file mode 100644 index 000000000..2edd9b6e9 --- /dev/null +++ b/win/autodefs.h.in @@ -0,0 +1,31 @@ +#ifndef AUTODEFS_H +#define AUTODEFS_H + +/* + * Minimum TAP-Win32 version number expected by userspace + * + * The TAP-Win32 version number is defined in tap-win32/SOURCES + */ +#define TAP_ID "@PRODUCT_TAP_ID@" +#define TAP_WIN32_MIN_MAJOR @PRODUCT_TAP_WIN32_MIN_MAJOR@ +#define TAP_WIN32_MIN_MINOR @PRODUCT_TAP_WIN32_MIN_MINOR@ + +/* Friendly name for TAP driver */ +#define PRODUCT_TAP_DEVICE_DESCRIPTION "@PRODUCT_TAP_DEVICE_DESCRIPTION@" + +/* Version number of DDK/WDK used to build TAP driver */ +#define DDKVER_MAJOR @DDKVER_MAJOR@ + +/* Name of package */ +#define PACKAGE "@PRODUCT_UNIX_NAME@" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "@PRODUCT_NAME@" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "@PRODUCT_UNIX_NAME@" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "@PRODUCT_VERSION@" + +#endif diff --git a/win/build.py b/win/build.py new file mode 100644 index 000000000..f42715bce --- /dev/null +++ b/win/build.py @@ -0,0 +1,15 @@ +import os +from wb import system, config, home_fn, cd_home + +os.environ['PATH'] += ";%s\\VC" % (os.path.normpath(config['MSVC']),) + +def build_vc(cmd): + system('cmd /c "vcvarsall.bat x86 && %s"' % (cmd,)) + +def main(): + cd_home() + build_vc("nmake /f %s" % (home_fn('msvc.mak'),)) + +# if we are run directly, and not loaded as a module +if __name__ == "__main__": + main() diff --git a/win/build_all.py b/win/build_all.py new file mode 100644 index 000000000..92d2bf42c --- /dev/null +++ b/win/build_all.py @@ -0,0 +1,18 @@ +from config_all import main as config_all +from build import main as build_openvpn +from build_ddk import main as build_ddk +from sign import main as sign +from make_dist import main as make_dist + +def main(config): + config_all(config) + build_openvpn() + build_ddk(config, 'tap', 'all') + build_ddk(config, 'tapinstall', 'all') + sign(config, 'all') + make_dist(config) + +# if we are run directly, and not loaded as a module +if __name__ == "__main__": + from wb import config + main(config) diff --git a/win/build_ddk.py b/win/build_ddk.py new file mode 100644 index 000000000..ca68e81d1 --- /dev/null +++ b/win/build_ddk.py @@ -0,0 +1,50 @@ +import os +from wb import system, home_fn, choose_arch + +def build_ddk(config, dir, x64): + setenv_bat = os.path.realpath(os.path.join(config['DDK_PATH'], 'bin/setenv.bat')) + ddk_major = int(config['DDKVER_MAJOR']) + debug = 'PRODUCT_TAP_DEBUG' in config + target = 'chk' if debug else 'fre' + if x64: + target += ' x64' + else: + target += ' x86' + if ddk_major >= 7600: + if x64: + target += ' wlh' # vista + else: + target += ' wnet' # server 2003 + else: + if x64: + target += ' wnet' # server 2003 + else: + target += ' w2k' # 2000 + + system('cmd /c "%s %s %s && cd %s && build -cef"' % ( + setenv_bat, + os.path.realpath(config['DDK_PATH']), + target, + dir + )) + +def main(config, proj, arch): + if proj == 'tap': + dir = home_fn('tap-win32') + elif proj == 'tapinstall': + dir = home_fn('tapinstall') + else: + raise ValueError("unknown project: %s" % (proj,)) + + for x64 in choose_arch(arch): + build_ddk(config, dir, x64) + +# if we are run directly, and not loaded as a module +if __name__ == "__main__": + import sys + from wb import config + if len(sys.argv) >= 3: + main(config, sys.argv[1], sys.argv[2]) + else: + print "usage: build " + sys.exit(2) diff --git a/win/config.py b/win/config.py new file mode 100644 index 000000000..67c1d82e2 --- /dev/null +++ b/win/config.py @@ -0,0 +1,17 @@ +from wb import preprocess, autogen, mod_fn, home_fn, build_autodefs, make_headers_objs, dict_def + +def main(config): + build_autodefs(config, mod_fn('autodefs.h.in'), home_fn('autodefs.h')) + ho = make_headers_objs(home_fn('Makefile.am')) + + preprocess(dict_def(config, [('HEADERS_OBJS', ho)]), + in_fn=mod_fn('msvc.mak.in'), + out_fn=home_fn('msvc.mak'), + quote_begin='@', + quote_end='@', + head_comment='# %s\n\n' % autogen) + +# if we are run directly, and not loaded as a module +if __name__ == "__main__": + from wb import config + main(config) diff --git a/win/config_all.py b/win/config_all.py new file mode 100644 index 000000000..268678083 --- /dev/null +++ b/win/config_all.py @@ -0,0 +1,13 @@ +from config import main as config_main +from config_tap import main as config_tap +from config_ti import main as config_ti + +def main(config): + config_main(config) + config_tap(config) + config_ti(config) + +# if we are run directly, and not loaded as a module +if __name__ == "__main__": + from wb import config + main(config) diff --git a/win/config_tap.py b/win/config_tap.py new file mode 100644 index 000000000..e69ee9b8c --- /dev/null +++ b/win/config_tap.py @@ -0,0 +1,35 @@ +import os +from wb import preprocess, home_fn, autogen, dict_def + +def main(config): + preprocess(config, + in_fn=home_fn('tap-win32/SOURCES.in'), + out_fn=home_fn('tap-win32/SOURCES'), + quote_begin='@@', + quote_end='@@', + head_comment='# %s\n\n' % autogen) + + preprocess(config, + in_fn=home_fn('tap-win32/i386/OemWin2k.inf.in'), + out_fn=home_fn('tap-win32/i386/OemWin2k.inf'), + quote_begin='@@', + quote_end='@@', + if_prefix='!', + head_comment='; %s\n\n' % autogen) + + try: + os.mkdir(home_fn('tap-win32/amd64')) + except: + pass + preprocess(dict_def(config, [('AMD64', '1')]), + in_fn=home_fn('tap-win32/i386/OemWin2k.inf.in'), + out_fn=home_fn('tap-win32/amd64/OemWin2k.inf'), + quote_begin='@@', + quote_end='@@', + if_prefix='!', + head_comment='; %s\n\n' % autogen) + +# if we are run directly, and not loaded as a module +if __name__ == "__main__": + from wb import config + main(config) diff --git a/win/config_ti.py b/win/config_ti.py new file mode 100644 index 000000000..4facaff1d --- /dev/null +++ b/win/config_ti.py @@ -0,0 +1,18 @@ +import os, shutil +from wb import preprocess, home_fn, autogen + +def main(config): + src = os.path.join(home_fn(config['TISRC']), config['DDKVER_MAJOR']) + dest = home_fn('tapinstall') + shutil.rmtree(dest, ignore_errors=True) + shutil.copytree(src, dest) + preprocess(config, + in_fn=os.path.join(dest, 'sources.in'), + out_fn=os.path.join(dest, 'sources'), + if_prefix='!', + head_comment='# %s\n\n' % autogen) + +# if we are run directly, and not loaded as a module +if __name__ == "__main__": + from wb import config + main(config) diff --git a/win/js.py b/win/js.py new file mode 100644 index 000000000..c5158246f --- /dev/null +++ b/win/js.py @@ -0,0 +1,10 @@ +import json + +# usage: +# print JSON().encode(kv) + +class JSON(json.JSONEncoder): + def __init__(self, **kwargs): + args = dict(sort_keys=True, indent=2) + args.update(kwargs) + json.JSONEncoder.__init__(self, **args) diff --git a/win/make_dist.py b/win/make_dist.py new file mode 100644 index 000000000..301127984 --- /dev/null +++ b/win/make_dist.py @@ -0,0 +1,54 @@ +import os +from wb import home_fn, rm_rf, mkdir, cp_a, cp + +def main(config): + dist = config['DIST'] + assert dist + dist = home_fn(dist) + bin = os.path.join(dist, 'bin') + i386 = os.path.join(dist, 'i386') + amd64 = os.path.join(dist, 'amd64') + + # build dist and subdirectories + rm_rf(dist) + mkdir(dist) + mkdir(bin) + mkdir(i386) + mkdir(amd64) + + # copy openvpn.exe and manifest + cp(home_fn('openvpn.exe'), bin) + cp(home_fn('openvpn.exe.manifest'), bin) + + # copy DLL dependencies + cp(home_fn(config['LZO_DIR']+'/bin/lzo2.dll'), bin) + cp(home_fn(config['OPENSSL_DIR']+'/bin/libeay32.dll'), bin) + cp(home_fn(config['OPENSSL_DIR']+'/bin/ssleay32.dll'), bin) + + # copy MSVC CRT + cp_a(home_fn(config['MSVC_CRT']), bin) + + # copy TAP drivers + for dir_name, dest in (('amd64', amd64), ('i386', i386)): + dir = home_fn(os.path.join('tap-win32', dir_name)) + for dirpath, dirnames, filenames in os.walk(dir): + for f in filenames: + root, ext = os.path.splitext(f) + if ext in ('.inf', '.cat', '.sys'): + cp(os.path.join(dir, f), dest) + break + + # copy tapinstall + dest = {'amd64' : amd64, 'i386' : i386} + for dirpath, dirnames, filenames in os.walk(home_fn('tapinstall')): + for f in filenames: + if f == 'tapinstall.exe': + dir_name = os.path.basename(dirpath) + src = os.path.join(dirpath, f) + if dir_name in dest: + cp(src, dest[dir_name]) + +# if we are run directly, and not loaded as a module +if __name__ == "__main__": + from wb import config + main(config) diff --git a/win/msvc.mak.in b/win/msvc.mak.in new file mode 100644 index 000000000..3f8102af1 --- /dev/null +++ b/win/msvc.mak.in @@ -0,0 +1,52 @@ +# This makefile builds the user-mode component +# of OpenVPN for Windows in the Visual Studio 2008 environment. + +# To build: +# python win\config.py +# nmake /f msvc.mak + +# Each of the OPENSSL and LZO dirs should have 'lib' and 'include' +# directories under them. + +OPENSSL = @OPENSSL_DIR@ +OPENSSL_DYNAMIC = libeay32.lib ssleay32.lib + +LZO = @LZO_DIR@ +LZO_DYNAMIC = lzo2.lib + +INCLUDE_DIRS = -I$(OPENSSL)/include -I$(LZO)/include + +LIBS = $(OPENSSL_DYNAMIC) $(LZO_DYNAMIC) ws2_32.lib crypt32.lib iphlpapi.lib winmm.lib user32.lib gdi32.lib advapi32.lib wininet.lib + +LIB_DIRS = -LIBPATH:$(OPENSSL)\lib -LIBPATH:$(LZO)\lib + +EXE = openvpn.exe + +CPP=cl.exe +CPP_ARG_COMMON=/nologo /W3 /O2 -DWIN32 -DWIN32_LEAN_AND_MEAN -D_CONSOLE -D_MBCS -D_CRT_SECURE_NO_DEPRECATE $(INCLUDE_DIRS) /FD /c +# release: +CPP_PROJ=$(CPP_ARG_COMMON) /MD -DNDEBUG +# debug: +#CPP_PROJ=$(CPP_ARG_COMMON) /MDd /Zi /Od -D_DEBUG + +LINK32=link.exe +# release: +LINK32_FLAGS=/nologo /subsystem:console /incremental:no /out:"$(EXE)" +# debug: +#LINK32_FLAGS=/nologo /subsystem:console /incremental:no /debug /out:"$(EXE)" + +# HEADERS and OBJS definitions, automatically generated +@HEADERS_OBJS@ + +openvpn : $(OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LIB_DIRS) $(LIBS) $(OBJS) +<< + +clean : + del /Q $(OBJS) $(EXE) *.idb *.pdb + +.c.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< diff --git a/win/settings.in b/win/settings.in new file mode 100644 index 000000000..044834ab5 --- /dev/null +++ b/win/settings.in @@ -0,0 +1,62 @@ +# Version numbers, settings, and dependencies +# for Windows OpenVPN installer. + +# Branding +!define PRODUCT_NAME "OpenVPN" +!define PRODUCT_UNIX_NAME "openvpn" +!define PRODUCT_FILE_EXT "ovpn" + +# Allow --askpass and --auth-user-pass passwords to be read from a file +;!define ENABLE_PASSWORD_SAVE + +# Include the OpenVPN GUI exe in the installer. +# May be undefined. +!define OPENVPN_GUI_DIR "../openvpn-gui" +!define OPENVPN_GUI "openvpn-gui-1.0.3.exe" + +# Prebuilt libraries. DMALLOC is optional. +!define OPENSSL_DIR "../openssl" +!define LZO_DIR "../lzo" + +# write output files here +!define DIST "dist" + +# tapinstall.exe source code. +# Not needed if DRVBINSRC is defined +# (or if using pre-built mode). +!define TISRC "../tapinstall" + +# TAP Adapter parameters. Note that PRODUCT_TAP_ID is +# defined in version.m4. +!define PRODUCT_TAP_DEVICE_DESCRIPTION "TAP-Win32 Adapter V9" +!define PRODUCT_TAP_PROVIDER "TAP-Win32 Provider V9" +!define PRODUCT_TAP_MAJOR_VER 9 +!define PRODUCT_TAP_MINOR_VER 7 +!define PRODUCT_TAP_RELDATE "04/19/2010" + +# TAP adapter icon -- visible=0x81 or hidden=0x89 +!define PRODUCT_TAP_CHARACTERISTICS 0x81 + +# Build debugging version of TAP driver +;!define PRODUCT_TAP_DEBUG + +# DDK path -- currently Windows 7 WDK +!define DDK_PATH "c:/winddk/7600.16385.1" +;!define DDK_PATH "c:/winddk/6001.18002" + +# Visual studio path +!define MSVC "C:/Program Files/Microsoft Visual Studio 9.0" + +# Visual studio C run-time library path +!define MSVC_CRT "../Microsoft.VC90.CRT" + +# Code Signing. +# If undefined, don't sign any files. +!define SIGNTOOL "../signtool" +!define PRODUCT_SIGN_CN "openvpn" + +; DEBUGGING -- set to something like "-DBG2" +!define OUTFILE_LABEL "" + +; DEBUGGING -- set to something like "DEBUG2" +!define TITLE_LABEL "" diff --git a/win/show.py b/win/show.py new file mode 100644 index 000000000..9558c8738 --- /dev/null +++ b/win/show.py @@ -0,0 +1,10 @@ +from wb import get_config +from js import JSON + +def main(): + kv = get_config() + print JSON().encode(kv) + +# if we are run directly, and not loaded as a module +if __name__ == "__main__": + main() diff --git a/win/sign.py b/win/sign.py new file mode 100644 index 000000000..ee4ae72dd --- /dev/null +++ b/win/sign.py @@ -0,0 +1,19 @@ +import sys +from wb import config, choose_arch, home_fn + +if 'SIGNTOOL' in config: + sys.path.append(home_fn(config['SIGNTOOL'])) + +def main(conf, arch): + from signtool import SignTool + st = SignTool(conf) + for x64 in choose_arch(arch): + st.sign_verify(x64=x64) + +# if we are run directly, and not loaded as a module +if __name__ == "__main__": + if len(sys.argv) >= 2: + main(config, sys.argv[1]) + else: + print "usage: sign " + sys.exit(2) diff --git a/win/wb.py b/win/wb.py new file mode 100644 index 000000000..7c2c8b9ff --- /dev/null +++ b/win/wb.py @@ -0,0 +1,185 @@ +# 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()