Building DLLs and Shared Objects

from common source

Last updated: 31 May 2007

I recently had to remember how to build shared libraries across platforms and I didn't find any examples to jog my memory. I am publishing this tutorial and the accompanying source so I don't have to reconstruct it again the next time I need it.

The challenge is to build shared libraries from common source for three platforms: linux using gcc 4+; Windows XP using gcc 3+ and mingw (stuff you get from the Cygwin tools); and Windows XP using MSVC++.

The example

The example I will use is a simple library consisting of two object files, each of which implements a single class:

The Library Source

The only platform-specific code in the two library source files is in Testclass.cpp:

#ifdef EXPAND_DLLEXPORT
  #define DLLEXPORT(x) __declspec(dllexport)x
#else
  #define DLLEXPORT(x) x
#endif

 . . .

class DLLEXPORT(Testclass) {
 . . .
    

The __declspec(dllexport) attribute is used in MSVC to mark symbols that will be exported from a shared library. It is not the only way to do that, but the other methods depend on knowing the "decorated" form of C++ symbols, and as a practical matter that's too much trouble. A similar mechanism would be useful, but is not required for gnu. By default, all symbols are exported from shared libraries built by g++.

Building the Library and a Sample Program

The sample code includes a gnu makefile that builds for all three platforms discussed above. It selects the correct methods by testing the environment variable _TEST_PLATFORM_. If this variable is set to "msvc", the library and program are built using Microsoft Virtual C++; if it is set to "mingw", they are built using g++ from the Cygwin tools; otherwise they are built assuming a linux environment and g++.

Here is the output when the platform is set to "msvc" on windows. The makefile assumes that the MSVC++ binaries are in the PATH:  

>set _TEST_PLATFORM_=msvc

>make clean
rm Testclass.obj Hiddenclass.obj Testclass.dll testprog.exe Testclass.lib

>make
cl /c Testclass.cpp -DEXPAND_DLLEXPORT
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

Testclass.cpp
cl /c Hiddenclass.cpp -DEXPAND_DLLEXPORT
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

Hiddenclass.cpp
cl /LD Testclass.obj Hiddenclass.obj
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 8.00.50727.42
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:Testclass.dll
/dll
/implib:Testclass.lib
Testclass.obj
Hiddenclass.obj
   Creating library Testclass.lib and object Testclass.exp
cl /Fetestprog.exe main.cpp Testclass.lib
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

main.cpp
Microsoft (R) Incremental Linker Version 8.00.50727.42
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:testprog.exe
main.obj
Testclass.lib

>

When the platform is set to "mingw" on Windows, this is the output:  

>set _TEST_PLATFORM_=mingw

>make clean
rm Testclass.o Hiddenclass.o libTestclass.dll testprog.exe

>make
g++ -c Testclass.cpp
g++ -c Hiddenclass.cpp
g++ -shared -o libTestclass.dll Testclass.o Hiddenclass.o
g++ -o testprog.exe main.cpp libTestclass.dll

Finally, on linux, after making sure that _TEST_PLATFORM_ is not set to anything, the output is.  

$ make clean
rm Testclass.o Hiddenclass.o libTestclass.so testprog

$ make
g++ -c Testclass.cpp
g++ -c Hiddenclass.cpp
g++ -shared -o libTestclass.so Testclass.o Hiddenclass.o; chcon -t texrel_shlib_t libTestclass.so
g++ -o testprog main.cpp -L. -lTestclass

$

The invocation of chcon may be necessary if you are running Secure Linux. It's probably best to build without it first, then try to run the executable. If the executable load fails with a message about not being update to update relocatable address, run chcon and try again.

You can download a zipped archive of the source and the makefile: http://www.oocities.org/~bblair/dlldso.zip