Hello all. It's been a long time since I've posted to this mailing list. In the past, I made some contributions to libtool, where it concerned Cygwin and MinGW.
I haven't used these environments for a while, but I am using them once again. I see that the support for these targets has been updated quite a bit. However, I now see some new issues that I'd like to discuss. I'm going to focus on only one issue in this email, since it's very detailed. I'll post another email about another issue. I tried to make a pass at searching the mailing list archives, but there does not seem to be a sophisticated search mechanism, so I didn't find much. The issue: DLL_EXPORT. It appears that this macro is defined by 'libtool' as a PIC flag for Cygwin and/or MinGW. It seems that the intent of this macro is to aid developers who are building shared objects. A developer can use this macro in the preprocessing of his header files. It's to be an indicator that the header is being included in a source file that is getting compiled as a shared object that will be part of the DLL. This scheme is flawed for a few different reasons. First of all, the intent of DLL_EXPORT is to enable the developer to use the __declspec(dllexport) directive. For libtool, this directive is superfluous. This is because libtool goes through the trouble of generating an .exp file, which is fed to the linker. The final DLL will have the correct exports with or without this directive being declared. Secondly, even if someone could convince me that using __declspec(dllexport) was necessary, the DLL_EXPORT macro is too generic. DLL_EXPORT preprocessed in a header for the library being built might be fine, but when a header outside of the library is being included, this can cause problems. Consider an example. Say I am building a shared library called libexample.dll, whose one and only object file is example.o. Suppose this was example.h: /* * I'm not going to bother with __declspec(dllimport) * since it's irrelevant to the example */ #ifdef DLL_EXPORT # define EXTERN extern __declspec(dllexport) #else # define EXTERN extern #endif EXTERN int myfunc(void); Suppose this was example.c: #include "ltdl.h" #include "example.h" int myfunc(void) { lt_dlmalloc = 0; /* just for fun */ return 0; } Now, if I use libtool to compile this file (using say MinGW gcc): $ libtool --mode=compile gcc -I/usr/local/include -c example.c rm -f .libs/example.lo gcc -I/usr/local/mingw/include -c example.c -DDLL_EXPORT -DPIC -o .libs/example.lo gcc -I/usr/local/mingw/include -c example.c -o example.o >/dev/null 2>&1 mv -f .libs/example.lo example.lo I believe that I have used DLL_EXPORT in a manner that is intended. In this manner, it indicates to the compiler that myfunc() is being exported. But here's the GOTCHA: Because I have included ltdl.h, it ALSO indicates that lt_dlmalloc is being exported from the resulting object file. This is because ltdl.h uses DLL_EXPORT for various symbols (like the variable lt_dlmalloc) exactly the same way that I that used it for myfunc(). Since lt_dlmalloc is not ever defined in my source file, the compiler never actually exports it. However, it was a flaw for it to believe that it ever would export it. In fact, if I KNOW that I'm going to link my library with the dynamic version of libltdl, then I should REALLY be defining LIBLTDL_DLL_IMPORT in my compilation line. If I don't do this, I will not really end up setting a value for lt_dlmalloc. The problem, however, is that ltdl.h I get a warning about LT_SCOPE to being redefined: $ libtool --mode=compile gcc -DLIBLTDL_DLL_IMPORT -I/usr/local/mingw/include -c example.c rm -f .libs/example.lo gcc -DLIBLTDL_DLL_IMPORT -I/usr/local/mingw/include -c xample.c -DDLL_EXPORT -DPIC -o .libs/example.lo In file included from example.c:1: /usr/local/mingw/include/ltdl.h:134: warning: `LT_SCOPE' redefined /usr/local/mingw/include/ltdl.h:131: warning: this is the location of the previous definition gcc -DLIBLTDL_DLL_IMPORT -I/usr/local/mingw/include -c example.c -o example.o >/dev/null 2>&1 mv -f .libs/example.lo example.lo Part of the problem here is the way that ltdl.h handles the order of preprocessing LIBLTDL_DLL_IMPORT and DLL_EXPORT. However, the bigger problem is the fact that DLL_EXPORT cannot act as a generic "export" macro for header files. It's fine for headers that are part of the library, but not for headers of other libraries that will be imported. Conclusion ========== DLL_EXPORT can and should be eliminated altogether. It should absolutely be taken out of libtool.m4 as the PIC flag for Cygwin and MinGW. If someone is going to insist that it remain when libltdl gets built, then the macro should at least be changed to LIBLTDL_DLL_EXPORT in ltdl.h. It's really up to the developer to figure out how to make his header file intelligent about using __declspec directives. In libraries that I have developed, I never use __declspec(dllexport). As for importing, I define EXTERN to __declspec(dllimport) by default UNLESS a macro whose name matches the library's name is defined. For me, this model has worked without a hitch. Jon _______________________________________________ Libtool mailing list [EMAIL PROTECTED] http://mail.gnu.org/mailman/listinfo/libtool