CMake version 2.8.6 or later
CMake now has all of this functionality built in.
You need to add the following to your CMake file:
include (GenerateExportHeader)
Then after you add your library using add_library(...)
you should also
do the following in your CMake file.
add_library(MyLibrary ${LIB_TYPE} ${srcs})
GENERATE_EXPORT_HEADER( MyLibrary
BASE_NAME MyLibrary
EXPORT_MACRO_NAME MyLibrary_EXPORT
EXPORT_FILE_NAME MyLibrary_Export.h
STATIC_DEFINE MyLibrary_BUILT_AS_STATIC
)
See the GenerateExportHeader
module documentation
for complete details.
CMake 2.8.5 and earlier
(Note: The remainder of this text is retained for historical interest, however it is extremely out of date and possibly incorrect. It is highly unlikely that anyone working with CMake today is using a version before 2.8.6 (or any pre-3.0 version), so it would be best to consult more current information.)
How to build a Windows DLL (for the NON-Windows developer); a short
introduction
Those folks coming from an environment like Linux, OS X or even MinGW may have some initial issues when trying to create a DLL on windows. Usually the problems involve the library symbols NOT getting exported. This article will try to walk you through what needs to be done in order for you to bring your code to an MS compiler successfully.
This short explanation was taken from a post to the cmake mailing list, and generally sums up the problem:
Visual Studio generates 2 files: one import library (.lib) and one - dynamic library (.dll). GCC (and mingw family) exports all symbols by default, VS doesn't export anything by default. And if your dll doesn't export anything, VS simply doesn't generate the import library (for example, if you generate resource-only dll). The only thing cmake knows is when you using VS generator, library extension to link with -- is .lib. And when you use
__declspec( dllexport )
, cl.exe puts special marks in objects indicating that this symbol should be exported or imported. Also, VS can tell linker to add some library, as boost does with#pragma
s.
So with all this information, how does all this work with CMake? There are a few pieces of code that you will need to add to your project.
Let us first consider the CMake code. In your CMakeLists.txt
file you will have something along the lines of:
# Allow the developer to select if Dynamic or Static libraries are built
OPTION (BUILD_SHARED_LIBS "Build Shared Libraries" OFF)
# Set the LIB_TYPE variable to STATIC
SET (LIB_TYPE STATIC)
IF (BUILD_SHARED_LIBS)
# User wants to build Dynamic Libraries,
# so change the LIB_TYPE variable to CMake keyword 'SHARED'
SET (LIB_TYPE SHARED)
ENDIF (BUILD_SHARED_LIBS)
# Create a target for the library
ADD_LIBRARY(MyLibrary ${LIB_TYPE} MyLibrary.cpp)
On MSVC platforms and when building a DLL, CMake will add the following preprocessor definition for you:
MyLibrary_EXPORTS
This is generated by concatenating the name of the target 'MyLibrary'
with '_EXPORTS'.
Now we have to exploit that definition in our code so we need to add
some c code into a header that will get included by every class or file
in the project. A Good name for this might be DLLDefines.h
.
Notice I did NOT call it Win32Exports.h
as GCC 4.x series has some of
these types of definitions that can be used and we should keep all this
in a single file (see GCC
Visibility ). So, what is the
contents of DLLDefines.h
you might ask?
// Contents of DLLDefines.h
#ifndef _MyLibrary_DLLDEFINES_H_
#define _MyLibrary_DLLDEFINES_H_
/* Cmake will define MyLibrary_EXPORTS on Windows when it
configures to build a shared library. If you are going to use
another build system on windows or create the visual studio
projects by hand you need to define MyLibrary_EXPORTS when
building a DLL on windows.
*/
// We are using the Visual Studio Compiler and building Shared libraries
#if defined (_WIN32)
#if defined(MyLibrary_EXPORTS)
#define MYLIB_EXPORT __declspec(dllexport)
#else
#define MYLIB_EXPORT __declspec(dllimport)
#endif /* MyLibrary_EXPORTS */
#else /* defined (_WIN32) */
#define MYLIB_EXPORT
#endif
#endif /* _MyLibrary_DLLDEFINES_H_ */
Ok. Now that we have that code, what do we do with it?
For every class or function that you want to be exported from your library you need to declare like the following:
class MYLIB_EXPORT SomeLibrary
{
// All your normal code here.
};
If you have some static functions then you will need something like the following:
class MyStaticFunctionClass
{
public:
static MYLIB_EXPORT void MyExportedFunction(int i);
};
After all this code is put in place then when you compile your library as a dll, Visual Studio should create the proper set of libraries.
But wait! I have an existing project that I am bringing to cmake
and it already has this type of code in place but the definition that
the project uses is different than what CMake produces, now what do I
do? Say that project uses COMPILING_DLL
as its definition, then
you can do the following in CMake:
SET_TARGET_PROPERTIES (MyLibrary PROPERTIES DEFINE_SYMBOL "COMPILING_DLL" )
I hope this helps explain what needs to be done when porting a linux, OS X or MinGW shared library to Windows.
This page was initially populated by conversion from its original location in another wiki.