Projects/KDE on Windows/Porting Guidelines

    From KDE TechBase
    Revision as of 09:23, 25 March 2008 by Jstaniek (talk | contribs) (K_PLUGIN_FACTORY)

    This document contains rules useful when you are porting a KDE library to win32. Most of these rules are also valid for porting external libraries code, like application's libraries and even application's private code.


    Before you start

    • Make sure (ask KDElibs/win32 maintainer) that the library you selected for porting is not ported, but just not committed yet.
    • You can ask the maintainer for proposals, what can be useful for porting.
    • You will need KDE svn account for your work.
    • Download most current (HEAD) of the KDE libraries.

    Absolute directory checking

    Look for '/' and "/" and change every single code like:

     if (path[0]=='/')
    

    or:

     if (path.startsWith('/'))
    

    with:

     if (!QDir::isRelativePath(path))
    

    (or "QDir::isRelativePath(path)" if there was used path[[0]!='/').

    Ifdefs

    C++ code

    Macros for C++ code are defined in qglobal.h file. If you've got included at least one Qt header, you probably have qglobal.h included already, otherwise, include it explicity.

    Use

     #ifdef Q_WS_X11
     ....
    
    1. endif

    for any C++ code that looks like X11-only.

    Use

     #ifdef Q_OS_UNIX
     ....
    
    1. endif

    for any C++ code that looks like UNIX-only, for example uses UNIX-specific OS features.

    Use

     #ifdef Q_WS_WIN
     ....
    
    1. endif

    for any C++ code that is MSWindows-only.

    C code

    Note that qglobal.h is C++-only, so instead use

     #ifdef _WINDOWS
     ....
    
    1. endif

    for any C code that is MSWindows-only (regardless to compiler type). In fact, you could use built-in _WIN32 but it's not defined on incoming 64bit MS Windows platform (_WIN64 is used there). So, there's a global rule for kdelibs/win32 defined globally in your build system (you don't need to include any file for this).

    Rare cases: How to check in Windows-only code which compiler is used?

    MS Visual C++ - Qt-independent code (especially, C code)

     #ifdef _MSC_VER
     ....//msvc code
    
    1. endif

    MS Visual C++ - Qt code

     #ifdef Q_CC_MSVC
     ....//msvc code
    
    1. endif

    Borland C++ - Qt-independent code (especially, C code)

     #ifdef __BORLANDC__
     ....//borland code
    
    1. endif

    Borland C++ - Qt code

     #ifdef Q_CC_BOR
     ....//borland code
    
    1. endif

    General notes

    In many places using #ifdef Q_OS_UNIX / #else / #endif is more readable than separate #ifdefs.

    Related links

    Header files

    Common header file

    Unless there is are any header file from kdelibs included in your header file, you need to add:

    #include <kdemacros.h> 
    

    or

    #include <kdecore_export.h> 
    

    at the beginning of your header file to have some necessary system-independent macros defined.

    Export macros

    For win32 world, symbols are "hidden by default" (not visible by default as e.g. on unix). This has already been [1] on the kde mailing list.

    For every library's code (not for standalone code), you need to make symbols exported for win32. Do this by adding ***_EXPORT macro (win32 export macro) after "class" keyword within any public class (and structure) declaration. You may also decide to put this macro even for non-public class, if you think that the class could be used somewhere outside your library.

    Example:

    class KDEFOO_EXPORT FooClass { ... };

    Note: For kdelibs, ***_EXPORT macros for are defined in kdelibs_export_win.h file (in kdelibs/win/ directory). You can study this file to see how the macros are defined. This file is simply included by kdelibs_export.h, for win32 target.

    Note2: Recently we're prepared to gcc's export capatibilities, probably in versions newer than 3.4, just like these in win32's msvc compiler. In kdemacros.h file (included by kdelibs_export.h) there are defines prepared for this functionality:

    1. define KDE_NO_EXPORT __attribute__ ((visibility("hidden")))
    2. define KDE_EXPORT __attribute__ ((visibility("default")))

    For gcc <= 3.4, KDE_EXPORT and KDE_NO_EXPORT macros are just empty. Note that we're not using KDE_NO_EXPORT for non-public symbols: in the future probably it will be better to use command line switch to turn hidding by default (as win32 compiler has).

    Note3: *_EXPORT macros depend on MAKE_{LIBRARYNAME}_LIB macro. In KDE4 buildsystem (cmake) the latter is defined automatically by reusing {LIBRARYNAME}, for example MAKE_KATEINTERFACES_LIB is constructed when KATEINTERFACES library is compiled. The logic behind it is implemented in kdelibs/cmake/modules/KDE4Macros.cmake:

      if (WIN32)
         # for shared libraries/plugins a -DMAKE_target_LIB is required
         string(TOUPPER ${_target_NAME} _symbol)
         set(_symbol "MAKE_${_symbol}_LIB")
         set_target_properties(${_target_NAME} PROPERTIES DEFINE_SYMBOL ${_symbol})
    

    endif (WIN32)

    Exporting global functions

    Also add the same ***_EXPORT at the beginning of public functions' declaration and definition (just before function's type). This also includes functions defined within a namespace.

    Example: namespace Foo {

    KDEFOO_EXPORT int publicFunction();
    

    }

    What not to export?

    • methods inside classes (no matter static or not)
    • inline functions
    • template classes, e.g.:

    template <class T> class KGenericFactoryBase


    Visibility

    There are classes or functions that are made "internal", by design. If you really decided anybody could neven need to link against these classes/functions, you don't need to add **_EXPORT macro for them.

    Deprecated classes

    Before porting KDElibs to win32, I realized that deprecated classes already use KDE_DEPRECATED macro. We're unable to add another macro like this:

    class KDEFOO_EXPORT KDE_DEPRECATED FooClass { //< - bad for moc! ... };

    ..because moc'ing will fail for sure. We've defined special macros like that in kdelibs_export.h file (fell free to add your own if needed):

    1. ifndef KABC_EXPORT_DEPRECATED
    2. define KABC_EXPORT_DEPRECATED KDE_DEPRECATED KABC_EXPORT
    3. endif

    So, we have following example of deprecated class:

    class KABC_EXPORT_DEPRECATED FooClass { //<- ok for moc ... };

    .. which is ok for __moc__. Note that sometimes KDE_DEPRECATED is also used at the end of functions. You don't need to change it for win32 in any way.

    Loadable KDE modules/plugins

    noframe
    noframe
     
    TODO
    This is deprecated section; we should use K_PLUGIN_FACTORY and K_EXPORT_PLUGIN macros

    K_EXPORT_COMPONENT_FACTORY macro

    Use K_EXPORT_COMPONENT_FACTORY( libname, factory ), defined in klibloader.h, instead of hardcoding:

    extern "C" {void *init_libname() { return new factory; } };
    

    ...because the former way is more portable (contains proper export macro, which ensures visiblility of "init_libname" symbol).

    Examples: K_EXPORT_COMPONENT_FACTORY( ktexteditor_insertfile,

       GenericFactory<InsertFilePlugin>( "ktexteditor_insertfile" ) ) 
    

    K_EXPORT_COMPONENT_FACTORY( libkatepart, KateFactoryPublic )

    More complex case

    Sometimes you need to declare a factory which defined as a template with multiple arguments, eg.:

    extern "C" {

     void* init_resourcecalendarexchange()
     {
       return new KRES::PluginFactory<ResourceExchange,ResourceExchangeConfig>();
     }
    

    }

    ... but compiler complains about too many arguments passed to K_EXPORT_COMPONENT_FACTORY. To avoid this, you can use __typedef__:

    typedef KRES::PluginFactory<ResourceExchange,ResourceExchangeConfig> MyFactory; K_EXPORT_COMPONENT_FACTORY(resourcecalendarexchange, MyFactory)

    The same trick can be used if the constructor of the factory takes multiple arguments.