(Answer) (Category) OpenLDAP Faq-O-Matic : (Category) Trash : (Answer) Development Notes for OpenLDAP in Mingw32/Cygwin
Author: Jon Leichter, jon@symas.com
Edited by Howard Chu, October 27, 1999

This document summarizes the set of changes that were necessary to port OpenLDAP 2.X-devel to the Mingw32/Cygwin environment.

 'configure'
 -----------
The 'configure.in' (and 'configure') script was updated to support the Mingw32 environment. This included checking for files and functions that are particular to Mingw32. The other major change to this script was the addition of macros that help Makefiles determine how they need to build components. The following is a summary of the new macros:

- PLAT: This macro evaluates to 'NT' or 'UNIX' at configuration time. It is used in Makefile templates, as @PLAT@, to configure the platform that OpenLDAP is being built on.

- LIB_LINKAGE: This macro evaluates to 'DYN' or 'STAT' at configuration time. It is used in Makefile templates, as @LIB_LINKAGE@, to configure whether the OpenLDAP libraries (liblber, libldap, libldap_r) will be built as dynamic or static libraries, respectively.

- LT_LIB_LINKAGE: This macro, similar to LIB_LINKAGE, evalutates to 'shared' or 'static' at configuration time. It is used in Makefile templates, as @LT_LIB_LINKAGE@, to configure the correct argument to 'libtool'.

- DYN_EXT: This macro evaluates to 'so' or 'dll' at configuration time. It is used in Makefile templates, as @DYN_EXT@, to configure the extension of dynamic libraries.

 Headers and Defines
 -------------------
Various header files had to be updated to work correctly in the Mingw32 environment. The primary change was the addition of macros that expand to use the 'dllimport' and 'dllexport' keywords appropriately.

One of the major differences between Windows and UNIX is that Windows requires special keywords to be recognized at compile-time so that the object files 'know' that symbols are being externally imported and/or exported. Thus, the 'dllimport' keyword must be used when an object file 'knows' that a symbol will come from a DLL or other executable binary. Likewise, the 'dllexport' keyword should (but does not have to) be specified if an object file 'knows' that a symbol that it implements is going to be exported from a DLL or other executable binary, for the purpose of being imported by some other entity.

In the MSVC NT port of OpenLDAP, an attempt was made to compensate for this kind of dependency. However, the attempt was not done correctly. In ldap_cdefs.h, the LDAP_F_IMPORT and LDAP_F_EXPORT macros are defined to use these keywords on the conditions that _WIN32 and _DLL are defined. Furthermore, the LDAP_F_xxPORT macros are integrated into the LDAP_F and LDAP_F_PRE macros. The LDAP_F macro has been used with MANY functions within the various header files in OpenLDAP. When used, a function will expand out with the appropriate 'dll' keyword.

The problem with this implementation is inherent in the _DLL dependency. The _DLL macro is defined by MSVC when a project has been configured to use the dynamic C run-time library. However, whether or not a source file is importing symbols from the dynamic C run-time library is completely independent from whether or not the source file will import a symbol from one or more of OpenLDAP's dynamic libraries (e.g. liblber).

To fix this correctly, I have updated ALL of the header files that use the LDAP_F macro. In each header, prior to the first LDAP_F macro usage, a section of preprocessing has been added to re-define the LDAP_F_PRE macro. The macro will be re-defined based on whether or not the functions in the header file are really being imported, exported, or neither. In each header file, the macro LIBxxxx_DECL is analyzed. 'xxxx' will always be one of: LBER, LDAP, AVL, LDBM, LDIF, or LUTIL. If the macro is defined, then its value should be defined as 'dllimport' or 'dllexport', in which case the LDAP_F macro will be appropriately expanded. This approach allows the same header file to be used in different contexts, without having to implement some constant rule. For instance, if the libldap library is being built as a dynamic library, all of the functions that libldap implements should be defined with the 'dllexport' keyword during compilation. Likewise, any other component in OpenLDAP planning to use the dynamic libldap library should be specifying the 'dllimport' keyword during compilation. Note also that just because the libldap library uses 'dllexport' when it compiles its own symbols should not suggest that every object that it compiles should be exported as well. As a perfect example, consider the fact that the libldap library makes use of symbols from liblber. For this very reason, when the dynamic libldap library is being built, it must 'dllexport' the symbols that it implements, but it must 'dllimport' symbols from liblber.

This may all seem very confusing, and it can be. The point is that if these keywords are not specified correctly, the Windows binaries are susceptible to segmentation faults.

In addition to fixing the 'dll' keyword issue, the other main set of changes occurred in portable.h.in. In this file, macros were added to support the macros added to 'configure'. Furthermore, the intent was to get it so that after 'configure' runs in Mingw32, the portable.h file is as functionally equivalent as possible to the portable.nt file. While going through this exercise, I found some items in the portable.nt file that were either wrong or belonged in different files. Thus, although portable.nt is used to build in MSVC and not Mingw32, I still made some minor adjustments to the file to make things right. The adjustments should still allow the MSVC project to build without any problems.

Note that matching portable.h.in to portable.nt is accomplished by tailoring configure.in, with some support added to acconfig.h.

 Makefiles
 ---------
Makefiles are generated at configuration time by the 'configure' script. They are built from template files and the configuration settings dynamically determined by 'configure'. Thus, the new macros introduced into 'configure' are used by various Makefile templates to configure the proper actions while building OpenLDAP. When OpenLDAP is built in NT as opposed to UNIX, some things need to be built and some things don't. (Another way to say it is that I've implemented support for some components and not others). Likewise, some build settings need to be specified (or not) based on whether or not the OpenLDAP libraries are being built statically or dynamically, e.g. the LIBxxxx_DECL macro specifications. Thus, the need to get Makefile parameters configured correctly is precisely the kind of things that I've updated in the Makefile templates. Furthermore, I found that I needed to add special treatment for .exe files that wasn't there before.

 Slapd
 -----
One of the other biggest changes was in how 'slapd' gets built. Currently, 'slapd' onlys supports the LDBM static backend. The reason that it does not support any other backends (neither static or module) is because I haven't taken the time to update any other Makefile templates.

Furthermore, although 'slapd' does not support any particular module backend, it DOES support the framework to use module backends. This means that 'slapd' must export its symbols so that a backend module could pick them up and use them at run-time.

Thus, when 'slapd' is built in NT, a few things happen:

- An import library for 'slapd' is generated. A backend module would specify this library at link time.

- 'slapd' exports every symbol that it knows about. This means that 'slapd' not only exports the symbols that it implements, but it also exports symbols that it may import from elsewhere, like the dynamic libldap library. This allows the backend modules to link with the 'slapd' import library only and no others. Any other method would be too complicated to implement in the Makefile templates. Note that in order for 'slapd' to export symbols that it 'can' use but does not already use, a dummy stubs function has been defined in nt_svc.c. This function makes bogus references to the symbols that 'slapd' can export but does not already normally use. The set of symbols that 'slapd' exports is not generated automatically. Rather, the symbols have been specified statically in the slapd.syms file.

One other trait about 'slapd' for NT is that it needs to attach some Windows resources at link time. In the MSVC project, the resources are built from the slapdmsg.mc file (found in the liblutil directory). This file is a Windows 'message' file that gets compiled by MSVC's mc.exe (message compiler) tool. This tool generates the following files: slapdmsg.h, slapdmsg.rc, and MSG00001.bin. Because the Mingw32 environment does not provide a message compiler or an equivalent tool, I have manually constructed the needed header, resource, and bin files. They are called slapdmsg.h, slapdmsg.rc, and slapdmsg.bin, respectively, and they have been checked into the source tree as new files, which are only used when building OpenLDAP in the Mingw32 environment. Note that the resulting resources are built when liblutil is built. However, since the resources are going into a static library, they are not pulled out automatically. Thus, when 'slapd' is built, it explicitly pulls in the resources.

NOTE: The MSVC version of 'slapd' does NOT pull in the resources. The resulting 'slapd' binary does NOT contain the resources. This is a bug that should probably be fixed.
hyc@highlandsun.com, Kurt@OpenLDAP.org

[Append to This Answer]
This document is: http://www.openldap.org/faq/index.cgi?file=303
[Search] [Appearance]
This is a Faq-O-Matic 2.721.test.
© Copyright 1998-2013, OpenLDAP Foundation, info@OpenLDAP.org