Difference between revisions of "Projects/KDE on Windows/Porting Guidelines"

Jump to: navigation, search
(General notes)
(Replaced content with "{{Moved To Community|Windows/Imported From TechBase/{{#titleparts:{{PAGENAME}}||3}}}}")
 
(10 intermediate revisions by 4 users not shown)
Line 1: Line 1:
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.
+
{{Moved To Community|Windows/Imported From TechBase/{{#titleparts:{{PAGENAME}}||3}}}}
 
+
 
+
==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:
+
 
+
<code c>
+
  if (path[0]=='/')
+
</code>
+
or:
+
 
+
<code cppqt>
+
  if (path.startsWith('/'))
+
</code>
+
with:
+
 
+
<code cppqt>
+
  if (!QDir::isRelativePath(path))
+
</code>
+
(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
+
<code c>
+
  #ifdef Q_WS_X11
+
  ....
+
#endif
+
</code>
+
for any C++ code that looks like X11-only.
+
 
+
Use
+
<code c>
+
  #ifdef Q_OS_UNIX
+
  ....
+
#endif
+
</code>
+
for any C++ code that looks like UNIX-only, for example uses UNIX-specific OS features.
+
 
+
Use
+
<code c>
+
  #ifdef Q_WS_WIN
+
  ....
+
#endif
+
</code>
+
for any C++ code that is MSWindows-only.
+
 
+
===C code===
+
Note that qglobal.h is C++-only, so instead use
+
<code c>
+
  #ifdef _WINDOWS
+
  ....
+
#endif
+
</code>
+
 
+
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)====
+
<code cpp>
+
  #ifdef _MSC_VER
+
  ....//msvc code
+
#endif
+
</code>
+
 
+
====MS Visual C++ - Qt code====
+
<code cpp>
+
  #ifdef Q_CC_MSVC
+
  ....//msvc code
+
#endif
+
</code>
+
 
+
====Borland C++ - Qt-independent code (especially, C code)====
+
<code cpp>
+
  #ifdef __BORLANDC__
+
  ....//borland code
+
#endif
+
</code>
+
 
+
====Borland C++ - Qt code====
+
<code cpp>
+
  #ifdef Q_CC_BOR
+
  ....//borland code
+
#endif
+
</code>
+
 
+
===General notes===
+
In many places using #ifdef Q_OS_UNIX / #else / #endif is more readable than separate #ifdefs.
+
 
+
'''NOTE!!!''' if you must ifdef parts of the code, which contain complete features, please file a bug report against kde-windows target in kde's bugzilla, so that those can be fixed later.
+
 
+
===Related links===
+
* [http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_predir_predefined_macros.asp| msvc++ Predefined Macros]
+
 
+
==Header files==
+
===Common header file===
+
Unless there is are any header file from kdelibs included in your header file, you need to add:
+
<code c>
+
#include <kdemacros.h>
+
</code>
+
or
+
<code c>
+
#include <kdecore_export.h>
+
</code>
+
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 [http://lists.kde.org/?l=kde-core-devel&m=105154800130902&w=2|discussed] 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:
+
 
+
<code cpp>
+
class KDEFOO_EXPORT FooClass {
+
...
+
};
+
</code>
+
 
+
'''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:
+
 
+
<code cpp>
+
#define KDE_NO_EXPORT __attribute__ ((visibility("hidden")))
+
#define KDE_EXPORT __attribute__ ((visibility("default")))
+
</code>
+
 
+
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:
+
<code cpp>
+
  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)
+
</code>
+
 
+
===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:
+
<code cpp>
+
namespace Foo {
+
KDEFOO_EXPORT int publicFunction();
+
}
+
</code>
+
 
+
===What not to export?===
+
* methods inside classes (no matter static or not)
+
* inline functions
+
* template classes, e.g.:
+
 
+
<code cpp>
+
template <class T>
+
class KGenericFactoryBase
+
</code>
+
 
+
 
+
 
+
===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:
+
 
+
<code cpp>
+
class KDEFOO_EXPORT KDE_DEPRECATED FooClass { //< - bad for moc!
+
...
+
};
+
</code>
+
 
+
..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):
+
 
+
<code cpp>
+
# ifndef KABC_EXPORT_DEPRECATED
+
#  define KABC_EXPORT_DEPRECATED KDE_DEPRECATED KABC_EXPORT
+
# endif
+
</code>
+
 
+
So, we have following example of deprecated class:
+
 
+
<code cpp>
+
class KABC_EXPORT_DEPRECATED FooClass { //<- ok for moc
+
...
+
};
+
</code>
+
 
+
.. 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==
+
 
+
{{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:
+
<code cpp>
+
extern "C" {void *init_libname() { return new factory; } };
+
</code>
+
...because the former way is more portable (contains proper export macro, which ensures visiblility of "init_libname" symbol).
+
 
+
Examples:
+
<code cpp>
+
K_EXPORT_COMPONENT_FACTORY( ktexteditor_insertfile,
+
    GenericFactory<InsertFilePlugin>( "ktexteditor_insertfile" ) )
+
K_EXPORT_COMPONENT_FACTORY( libkatepart, KateFactoryPublic )
+
</code>
+
 
+
===More complex case===
+
 
+
Sometimes you need to declare a factory which defined as a template with multiple arguments, eg.:
+
 
+
<code cpp>
+
extern "C"
+
{
+
  void* init_resourcecalendarexchange()
+
  {
+
    return new KRES::PluginFactory<ResourceExchange,ResourceExchangeConfig>();
+
  }
+
}
+
</code>
+
 
+
... but compiler complains about too many arguments passed to K_EXPORT_COMPONENT_FACTORY. To avoid this, you can use __typedef__:
+
 
+
<code bash>
+
typedef KRES::PluginFactory<ResourceExchange,ResourceExchangeConfig>  MyFactory;
+
K_EXPORT_COMPONENT_FACTORY(resourcecalendarexchange, MyFactory)
+
</code>
+
 
+
The same trick can be used if the constructor of the factory takes multiple arguments.
+
 
+
==Application icons==
+
Windows keeps icon data within .exe binaries. For KDE applications use CMake's KDE4_ADD_APP_ICON(appsources pattern) macro in automatically assign to add .png images for .exe files. [[Development/CMake/Addons for KDE#Macros|More information on KDE4_ADD_APP_ICON() macro...]]
+

Latest revision as of 14:18, 11 March 2016

This page is now on the community wiki.


This page was last modified on 11 March 2016, at 14:18. Content is available under Creative Commons License SA 4.0 unless otherwise noted.