Other languages: | English • Japanese • Brazilian Portuguese |
This section needs improvements: Please help us to
cleanup confusing sections and fix sections which contain a todo The build system has changed in KDE4. |
Contents
|
The easiest way is to use kdesdk/kapptemplate to generate the CMakeLists.txt. Or you can just copy a CMakeLists.txt from another app and install it in a new toplevel directory of existing KDE sources. Or you can start the old way, from scratch.
Check TechBase, especially the architecture documents. Check also the kde book.
Well, you are not forced to but it is a lot better. KPart allows powerful code reuse. Given how simple it is to use the technology and how widely it is deployed, it is a shame not to use it if you can.
Please follow this CMake tutorial.
Use make -f Makefile.cvs It will run all the Makefile generation steps
While hacking a program it might be useful to exclude certain directories from build that would otherwise be recompiled, but don't actually need to be. Also, if you checked out source code that didn't compile and you don't have the time or knowledge to fix the error you might want to turn off compilation of the directory alltogether. There are two cases. Toplevel directories, and subdirectories. For toplevel directories you can simply erase them (or not check them out).
If for some reason you don't want to do that, you can also set DO_NOT_COMPILE="someapp"
before calling configure, which will make configure skip "someapp". To only compile very few toplevel dirs, instead of using DO_NOT_COMPILE
to exclude most of them, you can list in a file named inst-apps, at the toplevel, the toplevel subdirs you want to compile.
To turn off compilation of any directory, including subdirectories, you have to modify the Makefile or Makefile.am files. Makefile.am is not recommended because that file is in KDE Subversion and you could accidentally commit your changes. So we'll modify the Makefile instead here:
Open the Makefile in the directory immediately above the directory you want to exclude in a text editor and look for a variable SUBDIRS
. It will often look somewhat like
SUBDIRS = share core ui . proxy taskmanager taskbar applets extensions data
Just remove the directory that you want to exclude and save your file. A new make will skip the directory you just removed.
Sometimes you'll have to look harder because the SUBDIRS variable consists of a number of other variables:
SUBDIRS = $(COMPILE_FIRST) $(TOPSUBDIRS) $(COMPILE_LAST)
Here you have to find the COMPILE_FIRST
, TOPSUBDIRS
and COMPILE_LAST
variables. One of those contains the dir you want to exclude. Remove the directory where you find it and save the Makefile again.
To undo your changes you can either regenerate the Makefile from scratch or revert to an older backup (you did make one, did you? :-).
To regenerate a Makefile, just make force-reedit.
You can also copy the original line in the file when editing and make it a comment by prefixing a '#' in front of it. Then undoing the change is as easy as making the modified line a comment and removing the comment in the original line.
--enable-debug
--disable-debug
--enable-final
This is a good thing to do at packaging time, but of course not for developers, since a change in one file means recompiling everything.
--disable-fast-perl
If you are a developer, you should definitely compile Qt and KDE with --enable-debug. You will then be able to debug your program even inside Qt and KDE function calls. If you are just a user, you can still use --enable-debug. KDE will occupy more space on your hard disk but it won't slow down your desktop. The advantage is that you get stack trace when an application crashes. If you can reproduce a crashing behaviour, go to bugs.kde.org, check that your bug doesn't exist yet and submit it. It will help us improve kde. For Qt, the compilation options are explained in qt-copy/README.qt-copy.
See --enable-final above :) . make final uses the all-in-one-file trick in the current directory even if --enable-final wasn't used, and make no-final does a normal compilation in the current directory even if --enable-final was used. Include your moc files! Header files declaring a QObject descendant have to be run through moc to produce a .moc file. This .moc file has to be compiled, for which two possibilities exists: compile it separately, or #include it in the C++ file implementing that above mentioned class. The latter is more efficient in term of compilation speed. BTW, kdesdk/scripts/includemocs does this automatically. Buy more ram, a faster machine and another processor. On a bi-PIII 866 MHz with 1GB of RAM, kde compiles at a decent speed :-)))
The strip is done at install. To use it, use "make install-strip" instead of "make install".
If you are working on an existing application, respect the author's indentation. Else, you can use whatever indentation you like.
If you do
QString translatedStuff = i18n("foobar");
translatedStuff will contain the translation of "foobar", while for const char *markedStuff = I18N_NOOP("foobar");
markedStuff will still contain literal "foobar", but translators will know you want "foobar" translated so you can later on do QString translatedStuff = i18n(markedStuff);
and get the translation of "foobar", which wouldn't work without that I18N_NOOP.
So, normally you want to just use i18n(), but in cases where you absolutely need to pass something untranslated, but still need to translate it later or in the case that you have something to be translated before the KInstance exists, use I18N_NOOP()
.
This often comes from the moc files not being in sync with the sources, or not linked at all. Check that you are running the right moc. 'which moc' will tell it. Regenerate your moc files (make force-reedit; make clean; make).
You need am_edit to reparse your Makefile.am to generate the correct Makefile. If it's the first Q_OBJECT you're using in this directory, you'll need to re-run Makefile.cvs or create_makefile from kdesdk/scripts. Otherwise, you can simply run "make force-reedit".
Hmm, don't do that, if some of the classes use the Q_OBJECT macro. Maybe METASOURCES=file.cpp might work for moc files though.
KDE searches its libraries in $KDEDIR/lib and in the lib directory of all the components of $KDEDIRS (note the additional 'S', this different from $KDEDIR). So, while you are still developing your library and don't want to install it, you can use this trick:
Now, KDE should find your library when using KTrader or KLibLoader.
If want to install your application privately, configure it with another prefix: for $HOME/kdeprefix, use configure --prefix=$HOME/kdeprefix
. Then let KDE know about this prefix: set KDEDIRS to $HOME/kdeprefix:$KDEDIR. To make KDE aware of new prefixes, one can also edit /etc/kderc and add
[Directories] prefixes=/the/new/prefix
but this doesn't answer this specific question ;-) Make sure to run "kbuildsycoca" after setting the new KDEDIRS.
The mimetype database must be rebuilt when you install new services (such as applications or parts). In theory this happens by itself (kded is watching those directories), but in doubt, run "kbuildsycoca".
The best way to debug trader-related problems is to use ktradertest: cd kdelibs/kio/tests; make ktradertest
, then run ./ktradertest
to see how to use it.
The solution is simple: start new apps from a command line, then they will use the new lib.
The reason is that applications started by other KDE applications (kicker, minicli, konqueror, etc.) are started via kdeinit, which loads the libs when KDE starts. So the "old" version of the libs keep being used. But if you want kdeinit to start using the new libs, simply restart it. This is done by typing kdeinit in a terminal.
This is necessary if you can't start things from the command line - e.g. for a kioslave. If you change something in kio, you need to restart kdeinit and kill the running kioslave, so that a new one is started.
Apps are often tempted to link to their part because they of course have much functionality in common. However this is wrong for the reasons below.
A lib is something you link to, a module is something you dlopen. You can't dlopen a lib ; you can't link to a module.
A lib has a version number and is installed in $libdir (e.g. $KDEDIR/lib) a module doesn't have a version number (in its name), it's more like a binary (we don't have konqueror-1.14.23 either :), and is installed into kde_moduledir (e.g. $KDEDIR/lib/kde3) (which means it's not in the search path for ld.so, so this breaks on systems without -rpath).
If you didn't understand the above, don't worry. The point is: you should NOT make your application link to your (or any other) KPart, nor any other kind of dlopened module.
The solutions:
Let the app dlopen the part. This is what KOffice does. However this limits the app to the very limited ReadOnlyPart/ReadWritePart API. Keep in mind that you can't call a non-virtual method whose implementation you don't link to. The solution is to define a ReadWritePart-derived class (like we have in koffice: KoDocument), with new virtual methods. Either this derived class has code (and you need a lib shared by the app and the part, see point 2 below), or an abstract interface (header file only) is enough. You can also use known interfaces to child objects of the part instead of changing the base class of the part itself - this is the solution used by e.g. KParts::BrowserExtension.
Define a common library with the common classes and let both the part and the app use it. That library can be noinst_ or lib_, both work. In the first case the compiled object code is duplicated, in the second case a real versioned lib will be installed. The idea here is that the part itself is not available to the app, but instead the part is a very thin wrapper around the same classes as the app uses. Only KParts-specific stuff remains in the part.
In KDE there are several ways to start other programs from within your application. Here is a short summary of your options with reasons why you should or should not use them.
You never want to use this unless you have a very good reason why it is impossible to use KProcess.
You want to use this if you need to start a new process which needs to be a child of your process, e.g. because you want to catch stdout/stderr or need to send it data via stdin. You should never use this to start other KDE applications unless your application is called kgdb :-)
Preferred way to launch desktop (KDE/Gnome/X) applications or KDE services. The application/service must have a .desktop file. It will make use of KDEinit for increased startup performance and lower memory usage. These benefits only apply to applications available as KDEinit loadable module (KLM)
Generic way to open documents/applications/shell commands. Uses startServiceBy.... where applicable. Offers the additional benefit of startup-notification.
KRun can start any application, from the binary or the desktop file, it will determine the mimetype of a file before running the preferred handler for it, and it can also start shell commands. This makes KRun the recommended way to run another program in KDE.
KToolInvocation::invokeBrowser launches a web browser. The difference with using the more generic KRun on the webpage URL is that KRun has to determine the mimetype of the URL first (which, for HTTP, involves starting a download to read the headers), so if you know that the URL is an HTML webpage, use invokeBrowser, it will be faster.
More details: the problem with KRun for webpages is that it delays the appearance of the browser window, and if the user's preferred browser is a non-kde application like firefox then it has to start a second download while konqueror which can reuse the kioslave started by KRun. On the other hand if the URL might be an image or anything else than html, then KRun is the right solution, so that the right application is started.
You have spotted a bug and you want to write the code to fix it. Or you want to code a specific feature. Sending a patch is very appreciated by developers. A tutorial is available but here is a description of how you should proceed: