[CMake] import/export and DLL's

David Cole david.cole at kitware.com
Wed Dec 7 07:57:55 EST 2011


On Wed, Dec 7, 2011 at 1:40 AM, Michael Wild <themiwi at gmail.com> wrote:
> 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
>
> --
>
> Powered by www.kitware.com
>
> Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html
>
> Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ
>
> Follow this link to subscribe/unsubscribe:
> http://www.cmake.org/mailman/listinfo/cmake

See also the "new in 2.8.6" module GenerateExportHeader:

  http://cmake.org/cmake/help/cmake-2-8-docs.html#module:GenerateExportHeader

  cmake --help-module GenerateExportHeader


HTH,
David


More information about the CMake mailing list