[CMake-Promote] request for proofreading
Alexander Neundorf
a.neundorf-work at gmx.net
Wed Jan 11 17:30:56 EST 2006
Hi,
I want to blog how to compile KDE3 software using cmake. But since I'm
not used to writing longer texts in english, it would be nice if you
could proofread it before and let me know if it's ok or if I should
change some things. Is the spelling and grammar ok, is everything clear
or are there logical gaps ?
(I plan to write another article as documentation about the FindKDE3
module, where the commands will be explained one by one).
Here comes the text:
-----8<---------------8<-------------8<--------------------
Using cmake for building KDE 3 software...
some weeks ago I blogged how I managed to compile kpager using cmake.
In the meantime the am2cmake script was a bit fine tuned and now even
more works.
You can get the script and the KDE 3 support files for cmake from here:
http://websvn.kde.org/trunk/KDE/kdesdk/cmake/
So here we go:
<b>How to build an application:</b>
Checkout kpager and run the am2cmake script, this will produce a
CMakeLists.txt.
Just run "cmake ." in this directory, followed by make, and it will
produce a working kpager binary without any manual tweaking. You can find
more details about the generated CMakeLists.txt here:
http://www.kdedevelopers.org/node/1668
So let's proceed with something new...
<b>How to build an KDE ioslave and a KPart:</b>
Checkout kdebase/kioslave/man, the man-page ioslave.
As before, run the am2cmake script and try to compile it. This time it
won't work,
it can't find config.h. This means, the man-ioslave needs a config.h with
defines figured out by a configure script. kio_man contains ifdefs for
HAVE_UNISTD_H and HAVE_STRING_H. Creating this file is the job of
autoconf/configure when using the autotools.
How to do this with cmake ? It's easy:
<pre>
INCLUDE(CheckIncludeFiles)
CHECK_INCLUDE_FILES( unistd.h HAVE_UNISTD_H)
CHECK_INCLUDE_FILES( string.h HAVE_STRING_H)
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/config.h.cmake
${CMAKE_BINARY_DIR}/config.h)
</pre>
CheckIncludeFiles is a script file (in cmake language a <i>module</i>)
which contains the function "CHECK_INCLUDE_FILES(filename
outputVariable)".
This function is called once to check for the existance of unistd.h and
once for string.h, and the results are stored respectively on
HAVE_UNISTD_H and HAVE_STRING_H. If they were found, they are set to "1",
if not they are set to an invalid state. Finally the line
CONFIGURE_FILE() creates a config.h from a config.h.cmake (similar as
configure creates a config.h from a config.h.in).
How does the config.h.cmake look?
<pre>
#ifndef CONFIG_H
#define CONFIG_H
#cmakedefine HAVE_UNISTD_H
#cmakedefine HAVE_STRING_H
#endif
</pre>
The CONFIGURE_FILE() command will read this file and replace
"#cmakedefine HAVE_UNISTD_H" with "#define HAVE_UNISTD_H 1" if unistd.h
was found, or "#undef HAVE_UNISTD_H" if not (and respectively for
string.h).
Now run make again and it should compile without problems. After "make
install" as root you will have a cmake-compiled version of the
man-ioslave on your system :-)
This means, if everything was installed in the correct directory. By
default cmake uses /usr/local as install prefix, just as the autotools
do. To change this, start "ccmake ." (yes, double c make). This opens a
ncurses "GUI" where you can adjust the cmake variables, among them
CMAKE_INSTALL_PREFIX. Set this to the directory where your KDE is
installed.<br>
Ok, and now let's have a look at the generated CMakeLists.txt:
<pre>
FIND_PACKAGE(KDE3 REQUIRED)
SET(CMAKE_VERBOSE_MAKEFILE ON)
ADD_DEFINITIONS(${QT_DEFINITIONS} ${KDE3_DEFINITIONS})
LINK_DIRECTORIES(${KDE3_LIB_DIR})
INCLUDE_DIRECTORIES( ${KDE3_INCLUDE_DIR} ${QT_INCLUDE_DIR}
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} )
</pre>
The part upto here has changed slightly since the last version, now the
FindKDE3.cmake module doesn't actively set the values, it justs sets the
variables, which can then be used with ADD_DEFINITIONS(),
INCLUDE_DIRECTORIES() and LINK_DIRECTORIES(). This is more conform to
standard cmake-behaviour.
<pre>
INCLUDE(CheckIncludeFiles) # module for testing for headers coming with
cmake
CHECK_INCLUDE_FILES( unistd.h HAVE_UNISTD_H)
CHECK_INCLUDE_FILES( string.h HAVE_STRING_H)
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/config.h.cmake
${CMAKE_BINARY_DIR}/config.h)
</pre>
These lines were added manually, configure checks are not converted by
am2cmake.
<pre>
########### next target ###############
SET(kio_man_test_SRCS
kio_man_test.cpp
)
KDE3_AUTOMOC(${kio_man_test_SRCS})
IF(KDE3_BUILD_TESTS)
KDE3_ADD_EXECUTABLE(kio_man_test ${kio_man_test_SRCS})
TARGET_LINK_LIBRARIES(kio_man_test ${QT_AND_KDECORE_LIBS} )
ENDIF(KDE3_BUILD_TESTS)
########### next target ###############
SET(man2html_SRCS
dummy.cpp
)
KDE3_AUTOMOC(${man2html_SRCS})
FILE(WRITE dummy.cpp "//autogenerated file by cmake\n")
IF(KDE3_BUILD_TESTS)
KDE3_ADD_EXECUTABLE(man2html ${man2html_SRCS})
TARGET_LINK_LIBRARIES(man2html ${QT_AND_KDECORE_LIBS} )
ENDIF(KDE3_BUILD_TESTS)
</pre>
This Makefile.am contained two test binaries, this is translated
correctly to cmake. They will only be built if the cmake option
"KDE3_BUILD_TESTS" is enabled. This can be done with ccmake.
<pre>
########### next target ###############
SET(kio_man_PART_SRCS
man2html.cpp
kio_man.cpp
)
KDE3_AUTOMOC(${kio_man_PART_SRCS})
KDE3_ADD_KPART(kio_man ${kio_man_PART_SRCS})
TARGET_LINK_LIBRARIES(kio_man ${QT_AND_KDECORE_LIBS} )
INSTALL_TARGETS(/lib/kde3 kio_man )
</pre>
Here comes the actual man-ioslave. At first the source files are listed,
then they are "automoced". The KDE3_ADD_KPART() creates the loadable
plugin named kio_man.so. Maybe the name "KDE3_ADD_KPART" could be changed
to something like "KDE3_ADD_PLUGIN" or something like that, not sure.
Then INSTALL_TARGETS() creates the install rule for the target "kio_man",
i.e. kio_man.so will be installed to ${CMAKE_INSTALL_PREFIX}/lib/kde3.
What you can't see in this snippet, is that KDE3_ADD_KPART() also creates
an appropriate .la file together with the accompanying install rule.
AFAIK this is required for the dynamic loading by KDE.
<pre>
########### next target ###############
SET(kmanpart_PART_SRCS
kmanpart.cpp
)
KDE3_AUTOMOC(${kmanpart_PART_SRCS})
KDE3_ADD_KPART(kmanpart WITH_PREFIX ${kmanpart_PART_SRCS})
TARGET_LINK_LIBRARIES(kmanpart ${QT_AND_KDECORE_LIBS} kparts )
INSTALL_TARGETS(/lib/kde3 kmanpart )
</pre>
And the next target, this time a real KPart, which can be used to view
man-pages directly within konqueror (i.e. not via the man-ioslave). As
you can see here KDE3_ADD_KPART() is called with the special parameter
"WITH_PREFIX", which has the effect that the resulting file will be named
"libkmanpart.so", just as it was in the original Makefile.am The rest is
basically the same, additionally it links to libkparts.
<pre>
########### install files ###############
INSTALL_FILES( /share/apps/kio_man FILES kio_man.css )
INSTALL_FILES( /share/services FILES man.protocol kmanpart.desktop )
KDE3_PLACEHOLDER()
</pre>
And here you can see the autmatically converted install rules for the
remaining files.<br>
IMO this is definitely more obvious than the syntax we had in the
Makefile.am's.
Compare e.g. the lines above to the following lines from the Makefile.am:
<pre>
kdelnk_DATA = man.protocol kmanpart.desktop
kdelnkdir = $(kde_servicesdir)
</pre>
Do these two lines tell you what they do ?
As Matthias puts it: "An API is intuitive [...] if a programmer who
doesn't know the API can understand code written using it."
<b>How to build a KDEInit-enabled application</b>
Now let's try to build another application, kcalc.
Check it out, run am2cmake, cmake and make. It will fail. Again, a
config.h is missing, so we have to add the required configure checks:
<pre>
INCLUDE(CheckIncludeFiles)
CHECK_INCLUDE_FILES( unistd.h HAVE_UNISTD_H)
CHECK_INCLUDE_FILES( string.h HAVE_STRING_H)
CHECK_INCLUDE_FILES( ieeefp.h HAVE_IEEEFP_H)
INCLUDE(CheckFunctionExists)
CHECK_FUNCTION_EXISTS( isinf HAVE_FUNC_ISINF)
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/config.h.cmake
${CMAKE_BINARY_DIR}/config.h)
</pre>
You know already most of it from the man-ioslave. Additionally here a
test for the function isinf() was required, this is done similar to the
header check using the CHECK_FUNCTION_EXIST() function. I guess you
already know how config.h.cmake looks now:
<pre>
#ifndef CONFIG_H
#define CONFIG_H
#cmakedefine HAVE_UNISTD_H
#cmakedefine HAVE_STRING_H
#cmakedefine HAVE_FUNC_ISINF
#endif
</pre>
But it still won't compile, some include directories have to be added and
some libs to link to. Once this is done, it compiles cleanly. Here
kcalc/CMakeLists.txt:
<pre>
FIND_PACKAGE(KDE3 REQUIRED)
SET(CMAKE_VERBOSE_MAKEFILE ON)
ADD_DEFINITIONS(${QT_DEFINITIONS} ${KDE3_DEFINITIONS})
LINK_DIRECTORIES(${KDE3_LIB_DIR})
ADD_SUBDIRECTORY( knumber )
INCLUDE_DIRECTORIES( ${KDE3_INCLUDE_DIR} ${QT_INCLUDE_DIR}
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} )
INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/knumber ) # added
manually
</pre>
Nothing fancy up to here, the above line had to be added manually, and
the
configure checks below too.
<pre>
# configure checks, added manually
INCLUDE(CheckIncludeFiles) #module to test for headers, coming with
cmake
CHECK_INCLUDE_FILES( unistd.h HAVE_UNISTD_H)
CHECK_INCLUDE_FILES( string.h HAVE_STRING_H)
CHECK_INCLUDE_FILES( ieeefp.h HAVE_IEEEFP_H)
INCLUDE(CheckFunctionExists) #module to test for existence of functions,
coming with cmake
CHECK_FUNCTION_EXISTS( isinf HAVE_FUNC_ISINF)
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/config.h.cmake
${CMAKE_BINARY_DIR}/config.h)
</pre>
Now comes the first target, kcalc as a KDEInit Loadable Module, short KLM
(i.e.an application which can be started by forking from kdeinit)
<pre>
########### next target ###############
SET(kcalc_KDEINIT_SRCS
kcalc.cpp
kcalc_button.cpp
kcalc_const_button.cpp
kcalc_const_menu.cpp
kcalc_core.cpp
kcalcdisplay.cpp
dlabel.cpp
stats.cpp
)
KDE3_AUTOMOC(${kcalc_KDEINIT_SRCS})
SET( kcalc_UI
colors.ui
general.ui
constants.ui
)
KDE3_ADD_UI_FILES(kcalc_KDEINIT_SRCS ${kcalc_UI} )
SET( kcalc_KCFG_SRCS
kcalc_settings.kcfgc
)
KDE3_ADD_KCFG_FILES(kcalc_KDEINIT_SRCS ${kcalc_KCFG_SRCS})
KDE3_ADD_KLM( kcalc ${kcalc_KDEINIT_SRCS})
# gmp, knumber and kdeui added manually
TARGET_LINK_LIBRARIES(kdeinit_kcalc ${QT_AND_KDECORE_LIBS} kdeui knumber
gmp)
INSTALL_TARGETS(/lib kdeinit_kcalc )
TARGET_LINK_LIBRARIES( kcalc kdeinit_kcalc )
INSTALL_TARGETS(/bin kcalc )
</pre>
Here is some new stuff. kcalc uses some designer ui files. These are
added to the target using KDE3_ADD_UI_FILES(). kcalc also uses
kconfig_compiler. The kcfgc file is processed using
KDE3_ADD_KCFGC_FILES(). Finally the KLM is created using KDE3_ADD_KLM().
This command creates both a KDE loadable module and a normal executable.
Notable is the command TARGET_LINK_LIBRARIES(). am2cmake didn't recognize
that kcalc links to libkdeui.so, libgmp.so and the static library
libknumber.a. As you can see it is enough to specify the actual library
name, i.e. "knumber" in the link command. This is enough for cmake, since
libknumber.a is part of this project, cmake knows where to find and how
to link to it.
The other lines are basically only install instructions.
<pre>
########### install files ###############
INSTALL_FILES( /share/applications/kde FILES kcalc.desktop )
INSTALL_FILES( /share/config.kcfg FILES kcalc.kcfg )
INSTALL_FILES( /share/apps/kcalc FILES kcalcui.rc )
INSTALL_FILES( /share/apps/kconf_update FILES kcalcrc.upd )
KDE3_INSTALL_ICONS( hicolor )
</pre>
And now a short look at kcalc/knumber/CMakeLists.txt:
<pre>
ADD_SUBDIRECTORY( tests )
INCLUDE_DIRECTORIES( ${KDE3_INCLUDE_DIR} ${QT_INCLUDE_DIR}
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/.. ) # added manually
ADD_DEFINITIONS(-D_GNU_SOURCE -D_ISOC99_SOURCE ) # added manually
########### next target ###############
SET(knumber_STAT_SRCS
knumber.cpp
knumber_priv.cpp
)
KDE3_AUTOMOC(${knumber_STAT_SRCS})
ADD_LIBRARY(knumber STATIC ${knumber_STAT_SRCS})
########### install files ###############
KDE3_PLACEHOLDER()
</pre>
Nothing very exciting here. Here a static library is built (the "STATIC"
keyword in the ADD_LIBRARY() command). The two lines marked as such had
to be added manually.
--
Telefonieren Sie schon oder sparen Sie noch?
NEU: GMX Phone_Flat http://www.gmx.net/de/go/telefonie
More information about the CMake-Promote
mailing list