|Note: This page deals with content related to KDE 3. If you are developing for KDE 4, this information might not be valid anymore.|
Original Author: David Faure (firstname.lastname@example.org)
This is the Makefile.am HOWTO (English version). Makefile.am is a file used to describe how to build KDE programs. Usually each subdirectory in a KDE module has a Makefile.am. As you may guess from the name, it is supposed to be similar to a Makefile, but it processed first by the KDE build system, then by the autotools to generate the final Makefile.
This is the build system for KDE 3. KDE 4 uses a different build system, CMake.
# Notice the bin_ prefix. bin_PROGRAMS = kdialog kdialog_SOURCES = kdialog.cpp widgets.cpp kdialog_LDADD = $(LIB_KIO) kdialog_LDFLAGS = $(all_libraries) $(KDE_RPATH) AM_CPPFLAGS = $(all_includes) METASOURCES = AUTO
bin means that you want to create something that will install into the bin directory of KDE. *_PROGRAMS means you want to compile a program. Use _SCRIPTS for scripts, etc. Then you can see the name of the program, which is what is used in the lines below to define what has to be done to create that program.
You list all of the source files that need to be compiled for each of the PROGRAMS you have listed. Don't include header files or other files that don't need processed in the build procedure.
This variable is used for each program to define the libraries that the program links to. You can use three types of libraries references:
If a library (A) depends on another library (B), you don't need to specify the dependency library (B). But if you do, (e.g. because the dependencies on A might change), make sure you specify A before B. So usually libtool .la libraries are first, then $(LIB_*), then -lfoo if any.
This defines any flags that need to be passed to the linker. Note that the flags do not get passed to the linker by using _LDADD! These can be -L flags (to change the library search path, usually set by configure into a variable). $(all_libraries) contains all the -L flags necessary to find Qt and KDE, so you must have it there. For programs you should also add $(KDE_RPATH), it helps to get installed programs to find their libraries without having to set LD_LIBRARY_PATH.
|Insert -I directives before $(all_includes). This ensures that your own headers will be used, not some older installed version.|
Note that $(srcdir) and . (the build directory) are always included automatically. You may find that Makefile.am files in KDE still use INCLUDES (the old name for AM_CPPFLAGS), but AM_CPPFLAGS is the recommended way to add include paths and other compilation flags.
KDE_CXXFLAGS = $(USE_EXCEPTIONS)
METASOURCES = AUTO is the magic line that makes the KDE build system take care of the moc files automatically. It is the recommended way if all your .cpp/.cc files include their .moc file (this is the best way since it gives faster compilation), or if you are compiling a single binary/library.In case you have multiple binaries/libraries in the same directory, you might need to use the longer form of
libfoo_la_METASOURCES = myfile.moc myotherfile.moc mybinary_METASOURCES = someotherfile.moc
Here is an example Makefile.am for a simple library.
AM_CPPFLAGS = $(all_includes) lib_LTLIBRARIES = libkonq.la libkonq_la_LIBADD = $(LIB_KPARTS) libkonq_la_LDFLAGS = $(all_libraries) -version-info 6:0:2 -no-undefined libkonq_la_SOURCES = popupmenu.cc knewmenu.cpp ... METASOURCES = AUTO
The lib_ prefix means that the library will be installed in /lib. Then comes the name of the library, always followed by .la (which stands for Libtool archive). Note that this becomes _la in the lines that refer to it.
means "LibTool libraries". In other words, it lets the autotools know that libraries should be handled using the libtool program. You should always use this for libraries.
This is the list of libraries that this library depends on. Note that it is LDADD for programs and LIBADD for libraries, since it's not exactly the same thing. A library only remembers which other libraries it depends on, it doesn't link them into the final library. See LDADD for recommendations about how to order dependencies.
This contains the list of flags passed to the linker. $(all_libraries) is required as usual, but also the version number of the library (see [info:/libtool/Libtool%20versioning info:/libtool/Libtool versioning (Konqueror link only)] for more details). The -no-undefined flag is strongly recommended, as it allows the build system to check at link time that the library has no undefined symbols. If any undefined symbols show up, it means that you either forgot to implement a method, or that a dependant library is missing in the LIBADD line.
The rest of the lines are similar to the compiling a binary case.
All dynamically opened pieces of code (including plugins, KParts, kdeinit modules, Kicker applets and KIOSlaves) can be called a "DSO" (Dynamic Shared Object) or more simply for our purposes, a module.All modules should be installed into the "kde_module" directory, which is usually $KDEPREFIX/lib/kde3. Therefore the main difference with a shared library is that one should use
kde_module_LTLIBRARIES = something.la
If you are compiling the same source file with the same option into two shared libraries, or into two programs, which are in the same directory, and using the same compilation options, then that's fine, you can list it in both _SOURCES lines. It will in fact be compiled only once, and the object file will be used by both targets.
However, if you are using the same source file in a library and a program, or if you are sharing it between different directories, then you can't list it in both _SOURCES lines. This is because a library and a program need different compilation options (-fPIC), and in case of different directories, because automake doesn't support source files in other dirs. Instead, you should put the shared source files in either a shared library (installed) or in a convenience library. The latter is a static library (*.a on Unix), which isn't installed as is. The targets (shared libs or programs) that "link" to the convenience library will in fact incorporate the object files from it.
To define a convenience library:
# Just as bin_ means install to /bin and lib_ means # install to lib/, noinst_ means not to install at all. noinst_LTLIBRARIES = libcommon.la libcommon_la_SOURCES = dirk.cpp coolo.cpp ... # no need for LIBADD or LDFLAGS, strictly speaking, but it can help # if e.g. this code needs $(LIBJPEG), all users of this convenience # lib won't have to specify it. # Then you can use the convenience lib: mylib_la_LIBADD = libcommon.la myprogram_LDADD = libcommon.la
foo_SOURCES = subdir/bar.cc
You have to define a convenience library inside of subdir, and use that from the toplevel directory.
This is an example Makefile.am for an automated test program.
METASOURCES = AUTO check_PROGRAMS = mytestprog.cpp TESTS = mytestprog mytestprog_SOURCES = mytestprog.cpp mytestprog_LDFLAGS = $(all_libraries) $(KDE_RPATH) mytestprog_LDADD = ../libcommon.la AM_CPPFLAGES = -I$(srcdir)/.. $(all_includes)
A common way of adding automated tests to your application is to create a subdirectory called tests. Add tests to the SUBDIRS line in parent Makefile.am and create a Makefile.am in the new tests directory. Use create_makefile (from kdesdk/scripts) to create the new Makefile, and now when you type make check the test program will be compiled (due to check_PROGRAMS) and run (due to TESTS). If the test program returns a non-zero value, make prints out an error message and stops. If the test program shouldn't run automatically (e.g. because it's interactive), omit the TESTS line.
Note that the test program needs to link to a library (either shared or convenience lib) containing the code it's testing. Don't link to a program, KPart, plugin (or other module).
In case your test program needs command-line arguments, use a check-local target to launch it instead of TESTS:
check-local: mytestprog ./mytestprog $(srcdir)/datafile
This is Makefile syntax, the second line needs to start with a tab.
To install header files:
include_HEADERS = foo.h bar.h
If the class uses a namespace, e.g. KParts, then the header file should be installed into kparts/foo.h
To do that:
kpartsincludedir = $(includedir)/kparts kpartsinclude_HEADERS = foo.h bar.h
The first line defines a new directory, the second line installs the files into it. The name before dir and _HEADERS must be the same, but other than that it doesn't matter much what it is.
To install data files into a standard directory (not a directory path, see below for that), use dirname_DATA.
For instance a Type=Service .desktop file should go into $(kde_servicesdir), therefore you should write:
kde_services_DATA = foo.desktop
To install data files into a custom directory, you must first define it, then you can use it:
myappfoodir = $(kde_datadir)/kmyapp myappfoo_DATA = bar.desktop
This installs bar.desktop into $KDEPREFIX/share/apps/kmyapp.For a K Menu entry use:
xdg_apps_DATA = kmyapp.desktop
KDE_ICON = AUTO
However, if you only need to use icons in one application, you should install the icons into the application's specific directory by doing the following:
appicondir = $(kde_datadir)/myapp/icons appicon_ICON = AUTO
For AUTO to work (and for the icon loading to work), you need to follow this icon naming convention: themesize-type-name.png (extension can also be .svgz, see below).
You can find the same icon types in the icon chooser dialog as well.
|This convention applies to the source files only. Upon installation, the icon will be copied to the right directory, simply named name.png|
If you rename or delete a .desktop file, you might want to "uninstall" the old file, i.e. to overwrite it at install time with a file that says "deleted" in order to provide a smoother migration for people installing from sources.
The first step is to add a file called uninstall.desktop to your sources. It can be shared among subdirectories if needed. It should contain the following lines:
[Desktop Entry] Encoding=UTF-8 Hidden=true
Now you should edit Makefile.am and add:
install-data-local: uninstall.desktop $(mkinstalldirs) $(DESTDIR)/$(kde_datadir)/kmyapp $(INSTALL_DATA) $(srcdir)/uninstall.desktop $(DESTDIR) $(kde_datadir)/kmyapp/oldfilename.desktop
where $(kde_datadir)/kmyapp is just an example, it should be replaced with the directory where the .desktop was installed to. Don't forget to prepend $(DESTDIR).
|The Makefile.am sample is another instance of Makefile formatting, therefore the lines under install-data-local: need to start with tabs|
foo_SOURCES = mydialog.ui
foo_SOURCES = client.stub obj.skel
This works if the header file is in the current directory. Otherwise you need to specify where it is, for example:
KDesktopIface_DIR = $(top_srcdir)/kdesktop foo_SOURCES = KDesktopIface.stub
To generate sources yourself (e.g. with a Perl script), use
generated.cpp $(srcdir)/myscript $(srcdir)/mydata $(PERL) $(srcdir)/myscript $(srcdir)/mydata -o $@ CLEANFILES = generated.cpp
target_COMPILE_FIRST = myheader.h
In case there are a large number of compiled files, you can still use variables, to list them only once in CLEANFILES and target_COMPILE_FIRST, but you still need to write a two-line rule for each file.
In the normal case you need only list the subdirectories to add to the build:
SUBDIRS = foo bar
SUBDIRS = mylib . myplugins
SUBDIRS = $(AUTODIRS)
To compile a subdirectory optionally, you need to use the Automake Conditional feature. The Makefile.am will look like this:
if compile_KOPAINTER KOPAINTERDIR = kopainter endif SUBDIRS = foo bar $(KOPAINTERDIR)
test "$foo" = "yes"
Normally you would have run the test in question in the configure.in.in to define the value of foo before setting the AM_CONDITIONAL. An abbreviated example from kdemultimedia/juk:
have_musicbrainz=no KDE_CHECK_HEADER(tunepimp/tp_c.h, have_musicbrainz=yes) AM_CONDITIONAL(link_lib_MB, test "x$have_musicbrainz" = xyes)
The previous section is only for subdirectories of toplevel directories (toplevel directories are like kdebase/libkonq or kdenetwork/kopete, i.e. a directory below the module). The toplevel directories of a KDE source module are handled in a special way: they are automatically detected, so you don't need a SUBDIRS line there. However you might want to have some control on the ordering, in case of dependencies, so you can write something like this in the Makefile.am.in file for the module:
COMPILE_AFTER_kcontrol = kdm kdesktop COMPILE_BEFORE_konqueror = libkonq
DO_NOT_COMPILE = "$DO_NOT_COMPILE foobar"
|This is also useful to skip toplevel directories locally at configure time. Simply export DO_NOT_COMPILE with the list of dirs to skip|
KDE_LANG = en
KDE_DOCS = AUTO
KDE_DOCS = kcontrol/mouse
To make your application translatable, you must use i18n() in the code, around the English strings that appear to the user. You must also define a messages target in your toplevel Makefile.am. A script runs every night, and calls all messages targets as they are, to create the .pot files that end up in the l10n module. Then translators can create .po files that contain the translations of those messages.For applications not in SVN, run
make -f admin/Makefile.common package-messages
|You need to use a patched gettext program, available from ftp.kde.org for proper support of contextual translations and plural handling.|
The messages target in the Makefile.am should simply call xgettext on the sources that contain translatable text. This is not the same as the _SOURCES value, since _SOURCES contains .ui and .skel files that do not work with xgettext. This is why you usually use something like *.cpp *.h instead (make sure to include sub-directories, if any). So in the simple case a messages target will look like:
messages: $(XGETTEXT) *.cpp *.h -o $(podir)/mypotfile.pot
|Just as with other Makefile rules, the second line must begin with a tab. Also, the name of the .pot file must be unique across KDE, so it is best to use an application name or module name as the prefix, such as kofficefilters.pot.|
The file name you use for the .pot file is the name of your main KInstance (for a application, it is the first argument passed to KAboutData, and for components/modules it's the name of the KInstance that you create).If you have .ui (Qt Designer), .rc (XML-GUI) or .kcfg (KConfigXT) files, add
$(EXTRACTRC) */*.rc >> rc.cpp
Another special case is the "tips" file — an XML file containing tips shown to the user. In this case, use something like
messages: perl ./preparetips > tips.cc $(XGETTEXT) *.cpp *.h tips.cc -o $(podir)/mypotfile.pit rm -f tips.cc
You can find the preparetips script under kdebase/ktip, for instance. The name of the temporary tips.cc file doesn't matter.The last matter is the compilation and installation of .po files. Inside l10n, Makefile.am files contain
KDE_LANG = language
POFILES = AUTO
POFILES = AUTO
In that case, the .po files are copied depending on their name as $(PACKAGE).mo (for instance, de.po is installed under de/LC_MESSAGES/$(PACKAGE).mo).
KDE_OPTIONS = qtonly
make no-final ; make no-final-install
KDE_OPTIONS = nofinal
Do NOT use the following constructs:
When you change a Makefile.am, if there is already a Makefile generated from it you can simply run make and the Makefile will automatically be re-generated.
If there is no Makefile created yet, you have two choices.
If you're still stuck, there's several things you can do: