How do I build OpenSSL statically linked against Windows runtime?

c, openssl, static-libraries, static-linking, windows

Solution

To build 64-bit OpenSSL statically linked (which results in a single .exe file without any DLLs) with Visual Studio 2015, you will need the following prerequisites:

- Git for Windows. You can download it at https://git-scm.com/download/win. This guide uses version 2.11.0.3.

- Strawberry perl. You can download it at http://strawberryperl.com/ (Warning: ActivePerl is highly not recommended. It will give you strange errors during the process). This guide uses version 5.24.1.1.

- NASM assembler, which is available from http://www.nasm.us/. This guide uses version 2.12.03rc1.

You are expected to install all those tools system-wide and add them to your `%PATH%` environmental variable.

After you got everything we need, just follow this simple steps:

- Open VS2015 x64 Native Tools Command Prompt from your Start Menu. You will see command prompt.

Create `C:\build` directory and issue the following command in the command prompt:

- `cd c:\build`

Download latest zlib & OpenSSL source codes to your `build` dir by using the following commands:

- `git clone https://github.com/madler/zlib`

- `git clone https://github.com/openssl/openssl`

First we have to build static `zlib`. To do that first we will need to edit some configuration files:

- Navigate to the `zlib` source folder: `cd C:\build\zlib`

Edit the `win32\Makefile.msc` file:

- Find the line starting with `CFLAGS`

- Replace `-MD` with `-GL -MT -Zc:wchar_t-`

- Find the line starting with `LDFLAGS`

- Replace `-debug` with `-opt:icf -dynamicbase -nxcompat -ltcg /nodefaultlib:msvcrt`

Build `zlib` using the following command (should take less than a minute):

- `nmake -f win32/Makefile.msc AS=ml64 LOC="-DASMV -DASMINF -DNDEBUG -I." OBJA="inffasx64.obj gvmat64.obj inffas8664.obj"`

Copy resulting files to your `OpenSSL` directory:

- `xcopy zlib.h C:\build\openssl\`

- `xcopy zconf.h C:\build\openssl\`

- `xcopy zlib.lib C:\build\openssl\`

- `xcopy zlib.pdb C:\build\openssl\`

Navigate to `OpenSSL` source: `cd C:\build\openssl\` and configure it to use static zlib & read configuration files (`openssl.cnf`) from `C:\Windows\` directory.

- `perl Configure VC-WIN64A no-shared zlib no-zlib-dynamic threads --prefix=C:\Windows\`

Now make the following edits to the `C:\build\openssl\makefile`:

- Find the line that starts with: `CFLAG`

- Append: `/Zc:wchar_t- /GL /Zi`

- Find the line that starts with: `LDFLAGS`

- Replace `/debug` with `/incremental:no /opt:icf /dynamicbase /nxcompat /ltcg /nodefaultlib:msvcrt`

- Find the line that starts with: `EX_LIBS`

- Replace `ZLIB1` with `zlib.lib`

- Save changes

Build `OpenSSL` by issuing the `nmake` command (will take around 15 minutes).

The resulting ~3MB `openssl.exe` file will be located at `C:\build\openssl\apps\` directory. It is fully portable, since all DLLs are included. If you need to use custom configuration file, copy `C:\build\openssl\apps\openssl.cnf` to your `C:\Windows\` directory & edit it to your liking.

Problem

I'm working on a C++ application for Windows that uses OpenSSL 1.0.1e library. I'm on Visual Studio 2008. For portability reasons my application is statically linked against runtime libraries (`/MT` and `/MTd` options). And I don't ship runtime libs with my application. Per the OpenSSL FAQ, the library is by default linked against multithreaded DLL runtime (`/MDd`) which is obviously incompatible with my scenario. So to make my program work I've added `applink.c` to my project. On my dev machine and on most test computers the program works fine. But unfortunately I've located computers where the app doesn't start. Windows displays error: ``` The application failed to initialize properly (0xc0150002). Click on OK to terminate the application. ``` I've opened `libeay32.dll` in Dependency Walker and I see that `MSVCR90.dll` is not found. So the trick with `applink.c` doesn't really work for me. How do I build OpenSSL with `/MT` or `/MTd` option?

Original source