|[software] [catdoc] [tcl] [geography] [old things]|
Building OpenSSL for Windows with Mingw32
This page is about outdated version of OpenSSL and is kept for historical purposes only. OpenSSL 1.x.x supports cross-compiling out of the box
If you want to get OpenSSL libraries (either .dll or static libraries), usable by native Windows compilers, you can use entirely free GNU compiler, downloadable from internet.
OpenSSL is written on plain old C, which means that as long as compilers use common object file format, you can easily link object files and static libraries, produced by one compiler, with another.
GNU MinGW32 compiler uses COFF object format, same as Microsoft Visual studio. It just has different naming convention. Rename libssl.a, produced with MinGW to ssl.lib, and you can use it in MSVC.
OpenSSL distribution includes file mingw.bat to build dll version with MinGW. Forget about it. It is outdated, unsupported and soon to be removed.
Better to use unix style configure-make-make install approach. For this approach you'll need unix-like shell, perl and some utilities.
There are three possible choices for the build environment:
Building static version
Download and unpack sources of openssl. It comes in the tar.gz archive. Any build environment mentioned above includes tar program which is used to unpack archives.
Open command window (or terminal window on Unix), make sure that cygwin (or all of msys, mingw and ActiveState perl) directories are in your PATH (on Unix cross compiler automatically installed into PATH and perl is already there), change into top-level directory of unpacked source.
Open Configure script with text editor, find line
$IsMK1MF=1 if ($target eq "mingw" && $^O ne "cygwin" && !is_msys());
and comment it out (or delete altogether). If you are using Cygwin perl, you can omit this step. Condition would be false anyway. But function is_msys() might not work properly, and of course it wouldn't work when cross-compiling for Unix.Configure script. On *nix you can just start
With cygwin or ActiveState perl you'll have to feed this script to perl
perl Configure mingw
Soon you get message "Configured for mingw".
Now, you are ready to run make. In the cygwin or msys environment just type make. On unix, if you type just make, native compiler would be invoked. You have to specify crosscompiler in the CC makefile variable:
make CC=i586-mingw32msvc-gcc RANLIB=i586-mingw32msvc-ranlib
With current stable (0.9.8d) verything should go fine until rehash target would be invoked. With development branch (0.9.9) you can go into some trouble - it is development version, it supposed to be buggy. See Troubleshooting section below for some hints.
When make tells "Doing certs" it would probably complain about 'openssl' program not found in msys and about inability to run program on Unix. You can safely ignore that for a while.
After build is finished you should have openssl.exe file in the apps directory, and two library files libssl.a and libcrypto.a in the toplevel directory.
If you are on native Win32 system, you may run test suite typing
If you are doing build on Unix and want to run test, you have to find windows system to do so. This system should have MSYS and perl installed.
Doing shared build
You are probably not interesting in static build. Probably you want to have OpenSSL dlls which can be used with some native Win32 application such as Miranda IM.
To achieve this, you have to add shared parameter to Configure.
perl Configure mingw shared
But there bad thing happens:
everything is compiled, cryptoeay32-0.9.8.dll is built, but when it comes to building something that depends on this dll (such as ssleay32-0.9.8.dll), you get lot of complaints about unresolved symbols.
If you examine dll with dumpbin tool from MSVC you'll see that it doesn't export anything.
Fix is quite simple:
Open Configure script with text editor, find line with mingw configuration option:
"mingw","gcc:-mno-cygwin -DL_ENDIAN....Find fragment which defines options for dll building (it lloks like
:-mno-cygwin -shared:and add there -Wl,--export-all, so section would look like:
:-mno-cygwin -Wl,--export-all -shared:Then rerun Configure mingw shared and make. Anything should run fine except certificate rehash.
Defining openssl directory
There is some things, which OpenSSL searches in the compiled-in directory - configuration files and certificates. Path for openssl directory can be seen by issuing a command:
openssl version -d
Typically, it is unix-style path /usr/local/ssl. It is evident that there is little use of such path on Windows system. But it is not absolutely useless - if you have just one logical drive in your Windows machine, you can create there c:\usr\local\ssl directory there, and OpenSSL would find its configuration file as long as current working directory of your OpenSSL application is on the C: drive.
But it is better to define actual path during Configure stage. This is done via Configure option --openssldir.
perl Configure mingw shared --openssldir=c:/OpenSSL
There is another option - --prefix which is taken into account during make install, and used for search for dynamically loadable engine modules. But if you have working configuration file, you can always write dynamic_path there.
There is a method to override location of configuration file. You can specify exact filename (not just directory name, but filename) in the OPENSSL_CONF environment variable.
Installing runtime modules of OpenSSL
There is no need to use make install under Windows. You just cope openssl.exe and two dlls (in case of shared build) into some dir in the your PATH. On Unix shared libraries go into prefix/lib directory, and executable files into prefix/bin and only bin has to be added to PATH. So does standard OpenSSL installation procedure.
On Windows application search for DLLs using the same PATH as system uses to find executable files, but prepends directory where program itself resides. So if you throw executable and the dlls into same directory, it is guaranteed, that application would find those dlls.
Compiling 3rd party applications with OpenSSL
Typically, one compiles OpenSSL in order to use it in some programs. This can be windows-only programs, such as Miranda IM, or ports of Unix software such as PostgreSQL.
In both cases you need to have include files and import libraries for DLLs available for you compiler. (you may choose to use static libraries, but DLLs are better - they allow to quickly upgrade OpenSSL in case of security update without recompiling all the applications).
After you have built OpenSSL, there is include directory with openssl subdirectory. Copy this subdirectory with all its content into include directory of your compiler.
Then, copy libssl.dll.a and libcrypto.dll.a to the library directory of your compiler. Now you can use -lssl.dll -lcrypto.dll command line options for you Mingw32 compiler to link with OpenSSL libraries.
Typically, windows applications expect something other than these names. For instance, PostgreSQL build system expects these libraries to be named libeay32.a for libcrypto and libssleay32.a for libssl. You can just rename libraries appropriately, or copy them (they are quite small because contains just references to DLL, not actual code).
If you want to use openssl with Microsoft Visual Studio, you can just rename libcrypto.dll.a into libeay32.lib, and libssl.dll.a into ssleay32.lib. Microsoft .lib files are really ar archives and are compatible with mingw static libraries.
Case 1. ws2tcpip incompatible with winsock
With OpenSSL cvs of Oct-20-2006 I've encountered problems that compilation fails with message "ws2tcpip.h is not compatible with winsock.h".
Problem is that Windows has two versions of its TCPIP code winsock.h and winsock2.h. If you want to use newer version, you have to use winsock2.h. If your include winsock2.h, and then winsock.h everything is good - winsock.h sees if you have included winsock2 and does nothing. So you can use IPV6 functions declared in ws2tcpip.h etc.
But windows.h file which comes with Mingw32 runtime includes winsock.h for some constants and types. So, if you haven't included winsock2.h prior to first inclusion of windows.h, and than want to include ws2tcpip.h, compilation fails.
OpenSSL includes winsock2.h and ws2tcpip.h via local include file e_os.h. But windows.h is included not only via this file, but also via rand.h. So, if some code file includes rand.h (directly, or indirectly, via engine.h for example), prior to e_os.h, you are in trouble.
Solution is simple - find out where offending file is included, and add #include "e_os.h" on the previous line. I've found three such files - ssl/ssl_sess.c, apps/apps.c and test/randtest.c.
Hopefully OpenSSL core team would fix this problem soon.
Case 2. Duplicate extern
I've also found than compilation fails on the file engines/ccgost/gost_eng.c with message "Duplicate extern". Solution is very simple. Just remove offending __declspec(dllexport) declartions exactly where compiler reports error.
Since I'm author of ccgost code, I can tell you exact story how this error crawl into OpenSSL.
There is macros IMPLEMENT_DINAMIC_CHECK_FUNCTION and IMPLEMENT_DYNAMIC_BIND_FUNCTION intended for use by engine writers.
Before June 2006 these macros don't have any win32 specific things. Probably people just didn't use engines on Win32. So, we have to add export declarations in order to OpenSSL to be able to load our engine on Win32.
Then we forget about it for a while and haven't tested development version on Win32.
Meanwhile core developers have added OPENSSL_EXPORT to definitions of these macros (this happened on 0.9.8b in stable and nearly at the same time in development branch). We've fixed it in our engine for stable version (available at www.cryptocom.ru, but have forgotte to check development version. Then our engine was accepted into development distribution, and nobody cares to test it under Win32 until Oct 20.