OpenVPN is a great project.  It's a shame that their Windows compilation is this painful.  After spending hours trying to compile OpenVPN 2.1_rc7 on Windows using Visual C++, I thought I'd document the process for the benefit of others, and for my own future reference.

Prerequisites:

Build steps:

Extract all of the source packages somewhere in their own directories.  I assume that you're extracting everything in C:.

Compile OpenSSL

The following steps should be sufficient:

cd C:\openssl-0.9.8g
perl Configure VC-WIN32 --prefix=c:/openssl
ms\do_masm
nmake -f ms\nt.mak && nmake -f ms\nt.mak test && nmake -f ms\nt.mak install

This will create the OpenSSL binaries as well as header and libraries needed to compile other applications against OpenSSL in C:\openssl.

Compile LZO

Compiling LZO is significantly straightforward:

cd C:\lzo-2.03b\win32\vc.bat

Compile OpenVPN

This should be easy according to the OpenVPN documentation.  We're only supposed to edit makefile.w32-vc, to adjust the path to our OpenSSL and LZO directories, and then run nmake -f makefile.w32-vc.  But doing so would result in a stream of compiler errors:

C:\openvpn-2.1_rc7>nmake -f makefile.w32-vc

Microsoft (R) Program Maintenance Utility Version 9.00.21022.08
Copyright (C) Microsoft Corporation.  All rights reserved.

cl.exe @C:\Users\Ehsan\AppData\Local\Temp\nm4DF1.tmp
cl : Command line warning D9002 : ignoring unknown option '/G5'
base64.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
buffer.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
crypto.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
cryptoapi.c
cryptoapi.c(104) : warning C4996: 'strdup': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strdup. See online help for details.
        C:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE\string.h(207) : see declaration of 'strdup'
error.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
event.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
fdmisc.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
forward.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
fragment.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
gremlin.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
helper.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
init.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
interval.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
list.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
lzo.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
manage.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
mbuf.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
misc.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
mroute.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
mss.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
Generating Code...
Compiling...
mtcp.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
mtu.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
mudp.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
multi.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
ntlm.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
occ.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
pkcs11.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
openvpn.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
options.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
otime.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
packet_id.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
perf.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
ping.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
plugin.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
pool.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
proto.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
proxy.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
push.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
reliable.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
route.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
Generating Code...
Compiling...
schedule.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
session_id.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
shaper.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
sig.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
socket.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
socks.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
ssl.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
status.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
thread.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
tun.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
lladdr.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
win32.c
c:\openvpn-2.1_rc7\config-win32.h(38) : fatal error C1083: Cannot open include file: 'autodefs/defs.h': No such file or directory
Generating Code...
NMAKE : fatal error U1077: '"C:\Program Files\Microsoft Visual Studio 9.0\VC\BIN\cl.exe"' : return code '0x2'
Stop.

The cause of these errors is line 38 in config-win32.h, which is included in OpenVPN's source package:

#include "autodefs/defs.h"

The autodefs/defs.h file does not exist in the source distribution, hence the compiler errors cited above.  Upon further investigation, it seems like config-win32.h is supposed to be automatically generated from config-win32.h.in, by replacing @VERSION@ with OpenVPN's current version.  I tried taking a diff between the two files, and I noted that several places in the two files are different.  It seems to me that config-win32.h is being manually maintained in the project, and the autodefs/defs.h file has been excluded from the source distribution by mistake.  So, what to do now?  After a small amount of trial and error, I came up with a patch which enables hassle-free compilation of OpenVPN on windows by the promised nmake -f makefile.w32-vc command.  With this patch applied, the compiler errors can be reduced to:

C:\openvpn-2.1_rc7>nmake -f makefile.w32-vc

Microsoft (R) Program Maintenance Utility Version 9.00.21022.08
Copyright (C) Microsoft Corporation.  All rights reserved.

cl.exe @C:\Users\Ehsan\AppData\Local\Temp\nm66BE.tmp
cl : Command line warning D9002 : ignoring unknown option '/G5'
pkcs11.c
pkcs11.c(35) : fatal error C1083: Cannot open include file: 'pkcs11-helper-1.0/pkcs11h-certificate.h': No such file or directory
NMAKE : fatal error U1077: '"C:\Program Files\Microsoft Visual Studio 9.0\VC\BIN\cl.exe"' : return code '0x2'
Stop.

It seems like OpenVPN depends on another library (and this is not documented!): pkcs11-helper.  Their latest package as of this writing can be found here.  You should download and extract this library, and edit makefile.w32-vc to point to the path where you've extracted this library.  Now, you should compile pkcs11-helper.

Compile pkcs11-helper

You can use the following commands to build pkcs11-helper.

cd C:\pkcs11-helper
cd lib
nmake -f Makefile.w32-vc OPENSSL=1 OPENSSL_HOME=C:\openssl-0.9.8g

Note that OPENSSL_HOME should point to the directory where the source files for OpenSSL had been extracted, not the directory where binaries have been installed.

Back to compiling OpenVPN

Now that pkcs11-helper has been built, running nmake -f makefile.w32-vc will succeed, and will produce the OpenVPN binary.  See below if you encounter more errors.

Final notes

At the end, I got some errors from the linker regarding not found libraries.  I had to adjust the names and paths of some libraries in order to make the linker happy.  Some of these changes were expected (for example, I used LZO 2 instead of LZO 1, which uses the new library name lzo2.lib instead of lzo.lib) and some others may be due to changes in the build parameters of the dependencies.

Also, if you get errors regarding multiple defined symbols from the linker in MSVCRT.lib, your dependencies may be mixing the /MD and /MT compiler options.  Make sure you're using the same option in the makefiles for all of the dependencies, as well as OpenVPN itself.  For example, I used /MT every where to make the final OpenVPN binary not depend on the Visual C++ runtime library.

Update

After I managed to compile OpenVPN using the above instructions, someone on the OpenVPN users list mentioned that the Windows build procedure has been changed since 2.1_rc4.  I'm not sure why this is not documented anywhere I looked, but the interested readers can check out the new instructions.  I have not tried them myself, but they look promising!