Compiling OpenVPN on Windows

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!

Posted in Blog Tagged with: ,
14 comments on “Compiling OpenVPN on Windows
  1. Abolfazl says:

    Hello Ehsan
    Thanks for your helpful post
    I have problem in using of this patch :
    http://ehsanakhgari.org/wp-content/uploads/file/openvpn-2_1_rc7-windows-compile.patch
    How Can I Use That to remove errors?

  2. m.h.salehi says:

    salam aqa ehsan
    az rahnamayi hayi besyar mofid shoma dar in post besyar motshakeram , vaqean ali bud.
    shoma komake shayani be pishborde yeki az mohemtarin marahele projeam nemudid …
    barayetan doaye kheir mikonam , omidvaram hamishe Movafaq o Sarboland bashid.
    ;)

  3. Ehsan Akhgari says:

    خوشحالم که نوشته‌ام توانست به شما کمک کند.  موفق باشید!

  4. pfeffer says:

    SSL doesn’t compile MS VC 9 Express, because ml.exe (the assembler compiler) is not included in the free MS Visual C Express Edition :-(

    Mabe using the precompiler SSL could work.

  5. Ehsan Akhgari says:

    Yes, I think you can compile non-assembly based source code of OpenSSL.  OpenSSL can be configured not to use optimized assembly-based routines during the compilation stage.  The resulting library is a bit slower, but at least it works for your situation.

  6. Shahrooz says:

    Hey there Ehsan,
    Thanks for posting this saved my weekend ;) it’s very nice to see that Iranians are starting to contribute to open source community as well.
    keep up the good work bro ;)
    Peace

  7. Visitor says:

    Hi!
    please tell me, do you used vesion of VC ++??

  8. Ehsan Akhgari says:

    I used Visual C++ 2008, as described in the article.

  9. Visitor says:

    I used VC++ 2008 express but it but it fails when buil lzo and pkcs11-helper.

    When it lzo buil error as follows:

    cl: Command line error D8022: can not open ‘b \ src.rsp’

    please, you can help me?

    PS: if possible can you send the document you have written after build openvpn successful?

    thanks you very much

  10. jean lannes says:

    don’t use C:\lzo-2.03\b\win32>vc.bat
    correct is C:\lzo-2.03>b\win32\vc.bat

  11. Visitor says:

    C:\lzo-2.03\b\win32>vc.bat
    // Copyright (C) 1996-2008 Markus F.X.J. Oberhumer
    //
    // Windows 32-bit
    // Microsoft Visual C/C++
    //
    The system cannot find the path specified.

    C:\lzo-2.03\b\win32>set CC=cl -nologo -MD

    C:\lzo-2.03\b\win32>set CF=-O2 -GF -W3

    C:\lzo-2.03\b\win32>set LF=

    C:\lzo-2.03\b\win32>cl -nologo -MD -O2 -GF -W3 -c @b\src.rsp
    cl : Command line error D8022 : cannot open ‘b\src.rsp’
    ERROR during build!
    The system cannot find the path specified.

    I hope you can help me! thank you

  12. Ehsan Akhgari says:

    Sorry, I have not encountered such errors.  But have you also tried reading this article?  It might be helpful.

  13. Shawn says:

    Hi,
    I followed your excellent tutorial and worked fine on every step.I downloaded the makefile.w32-vc from your blog and editted it to some extent and tried compiling openvpn.I got some linker errors.

    link.exe @C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\nm5C4.tmp
    forward.obj : error LNK2019: unresolved external symbol _dhcp_extract_router_msg referenced in function _process_ipv4_header
    init.obj : error LNK2019: unresolved external symbol _pkcs11_addProvider referenced in function _context_init_1
    init.obj : error LNK2019: unresolved external symbol _pkcs11_initialize referenced in function _context_init_1
    init.obj : error LNK2019: unresolved external symbol _pkcs11_terminate referenced in function _uninit_static
    init.obj : error LNK2019: unresolved external symbol _pkcs11_forkFixup referenced in function _possibly_become_daemon
    init.obj : error LNK2019: unresolved external symbol _set_lladdr referenced in function _do_open_tun
    manage.obj : error LNK2019: unresolved external symbol _pkcs11_management_id_count referenced in function _man_pkcs11_id_count
    manage.obj : error LNK2019: unresolved external symbol _pkcs11_management_id_get referenced in function _man_pkcs11_id_get
    options.obj : error LNK2019: unresolved external symbol _show_pkcs11_ids referenced in function _add_option
    proxy.obj : error LNK2019: unresolved external symbol __imp__InternetQueryOptionA@16 referenced in function _get_windows_proxy_settings
    ssl.obj : error LNK2019: unresolved external symbol _pkcs11_logout referenced in function _ssl_purge_auth
    ssl.obj : error LNK2019: unresolved external symbol _SSL_CTX_use_pkcs11 referenced in function _init_ssl
    libeay32.lib(cryptlib.obj) : error LNK2019: unresolved external symbol __imp__GetUserObjectInformationW@20 referenced in function _OPENSSL_isservice
    libeay32.lib(cryptlib.obj) : error LNK2019: unresolved external symbol __imp__GetProcessWindowStation@0 referenced in function _OPENSSL_isservice
    libeay32.lib(cryptlib.obj) : error LNK2019: unresolved external symbol __imp__GetDesktopWindow@0 referenced in function _OPENSSL_isservice
    libeay32.lib(cryptlib.obj) : error LNK2019: unresolved external symbol __imp__MessageBoxA@16 referenced in function _OPENSSL_showfatal
    openvpn.exe : fatal error LNK1120: 16 unresolved externals

    Any ideas?
    Appreciate your time and effort.

  14. I’m wondering why would you compile it under Windows.
    Windows security is not as tough as Linux.
    And why would you waste your time to compile it on Windows, if it is just works on Linux.
    But anyway, i appreciate your hard work with this article.
    The OpenVPN community need someone like you.