[CMake] import/export and DLL's

Michael Wild themiwi at gmail.com
Wed Dec 7 01:40:54 EST 2011


On 12/07/2011 01:49 AM, Totte Karlsson wrote:
>> Well, then just use add_definitions(-DIMPORT_X_DLL). If 
>> -DEXPORT_X_DLL is present, it will override your export/import 
>> header definitions for the import case, and everything should be 
>> fine.
> 
> Not sure what you mean by override. If both symbols are defined, 
> MTK_COMMON will be defined as __declspec(dllexport) and not 
> __declspec(dllimport), since my headers have #elif, #not elses.

*That's* what I meant by _override_...

> Using add_definitions makes sense however. I just started using CMake
> two days ago and was not aware of that command.

Well, then you got a lot of RTFM'ing before you ;-)

> 
>>> CMake will only
>>>> add the DEFINE_SYMBOL when *building* the specified target, and
>>>> otherwise just leave it away.
>> 
>> When CMake invokes the compiler to *build* the DLL it adds 
>> -DEXPORT_X_DLL. If the DLL is being *used* it doesn't do anything.
> 
> That is the problem. When you say it does not do anything,(in the 
> 'use' case) it is in fact defining the dllimport flag (after your 
> #else).
> 
> The way my define structure looks, that does not happen.

Yes, and that is broken. Simple as that.

> 
>>>> So, in your code you do something like this:
>>>> 
>>>> #ifdef EXPORT_A_DLL #define A_API __declspec(dllexport) #else 
>>>> #define A_API __declspec(dllimport) #endif
> No, I'm not doing that in my code. But I tried it, and together with
>  target_link_library everything compiles fine. In my opinion, 
> however, those #defines gives you something defined, without
> defining anything.. that is a little too clever in my opinion. But
> practical.

Not too clever; Common practice and actually recommended by Microsoft:
http://msdn.microsoft.com/en-us/library/8fskxacy.aspx

> 
>>> I'll try to see if that works. Right now I do have an 
>>> exporter/importer header and it is more complex and looks like 
>>> (for a target "COMMON"): #if defined(EXPORT_COMMON_DLL) #define 
>>> MTK_COMMON __declspec(dllexport) #elif defined(IMPORT_COMMON_DLL)
>>> #define MTK_COMMON __declspec(dllimport) #elif
>>> defined(EXPORT_COMMON_PKG) #define MTK_COMMON __declspec(package)
>>> #elif defined(IMPORT_COMMON_PKG) #define MTK_COMMON
>>> __declspec(package) #else #define MTK_COMMON #endif
>> 
>> Is this for embarcadero c++? in which case do you define 
>> EXPORT_COMMON_DLL, and when do you use EXPORT_COMMON_PKG?
> 
> The package spec is a embarcadero flavor of a dll (that can be 
> installed in the IDE). That is why I need elseifs, and not just an 
> else.
> 

So, __declspec(package) is used exactly when? Only when building the
DLL, only when using the DLL or in both cases? Assuming you only need it
when building, you could do the following in your CMakeLists.txt:

-----------------------------------------------------------------------
# loads of stuff...

# possibly detect this automatically using the BORLAND variable?
option(BUILD_EMBARCADERO_PACKAGE "Build a bpl package" OFF)

if(BUILD_EMBARCADERO_PACKAGE)
  set(SYMBOL_SUFFIX PACKAGE)
else()
  set(SYMBOL_SUFFIX DLL)
endif()

add_library(A SHARED a.cpp a.h)
add_library(B SHARED b.cpp b.h)
add_library(C SHARED c.cpp c.h)

target_link_libraries(B A)
target_link_libraries(C B)

foreach(t A B C)
  set_target_properties(${t} PROPERTIES
    DEFINE_SYMBOL ${t}_BUILD_${SYMBOL_SUFFIX})
endforeach()

# more stuff...
-----------------------------------------------------------------------

This defines <TARGET_NAME>_BUILD_{DLL,PACKAGE} when the target
<TARGET_NAME> is built, and otherwise nothing is defined. In your
headers you can then do something like the following (here for a.h, the
others are analogous):

-----------------------------------------------------------------------
#ifndef A_H
#define A_H

#if defined(A_BUILD_DLL)
#define A_API __declspec(dllexport)
#elif defined(A_BUILD_PACKAGE)
#define A_API __declspec(package)
#else
#define A_API __declspec(dllimport)
#endif

class A_API SuperDuperClass
{
   // some stuff goes here...
};

#endif
-----------------------------------------------------------------------

HTH

Michael



More information about the CMake mailing list