Archive:Development/Tutorials/CMake (zh CN)

From KDE TechBase
Revision as of 14:34, 1 April 2007 by Liangqi (talk | contribs) (move all chinese from kdecn.org(Huanzhou Zhu))
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Template:CMake

简介

CMake读取脚本文件并且为它所运行的平台的本地构建系统产生输入文件。它可以生成GNU Makefiles、KDevelop的项目文件、XCode项目文件以及Visual Studio项目文件等多种文件格式。

CMake是自由软件并且是在BSD协议下发布的。它是由Kitware公司开发的。

这些地方学习CMake挺不错的:

另外,还可以考虑加入CMake邮件列表

为什么使用CMake?

CMake是KDE 4发布中的官方工具,这是在2006年3月决定的,它和以前的KDE工具automake和unsermake的主要技术不同点有:

  • CMake是独立于KDE开发的,它也可以被用于其它项目。
  • 编译时间更快,主要是因为没有再使用libtool。
  • 构建文件更容易编写。

如何使用CMake编译KDE

获取和安装CMake

Linux、BSD及其他Unix系统

[1]获得取回最新的CMake稳定版。

下载完后,解压并安装: $ mkdir cmake-build $ cd cmake-build $ ../bootstrap $ make $ make install

默认的,这将把CMake安装在/usr/local,因此,确定/usr/local/bin在的执行路径里。要改变安装路径,(例如debian中改为/usr),在bootstrap命令中加入'--prefix=PATH'选项。

如果你想使用当前的开发版本,请遵循here的指令。

Windows

[2]获得取回最新的CMake稳定版。

下载完后,运行cmake的安装程序。

默认将把CMake安装在C:\Program Files\CMake 2.4,,因此要确保<installpath>\bin在你的执行路径中。

如果你想使用当前的开发版本,请遵循here的指令。

Mac OSX

运行CMake

Linux、BSD及其他Unix系统

你必须运行CMake来为你的系统生成build文件。CMake支持in-source和out-of-source构建,不过目前KDE默认禁用in-source构建。

假定你在~/src/kdelibs/中有kdelibs/,那么,输入: $ ls kdelibs/ $ mkdir kdelibs-build $ cd kdelibs-build $ cmake ../kdelibs 这会在kdelibs-build/中生成构建kdelibs/的Makefiles。

Windows

你必须运行CMake来为你的系统生成build文件。CMake支持in-source和out-of-source构建,不过目前KDE默认禁用in-source构建。

假定你在c:\daten\kde4中有kdelibs\,那么,输入: c:\daten\kde4> cd kdelibs\win c:\daten\kde4> cmake c:\daten\kde4> make c:\daten\kde4> make install c:\daten\kde4> cd .. c:\daten\kde4> mkdir kdelibs-build c:\daten\kde4> cd kdelibs-build c:\daten\kde4\kdelibs-build> cmake ..\kdelibs

这样就生成了在 kdelibs-build\中构建kdelibs\的Makefiles。要获得更多的关于在Windows下编译KDE的信息,请阅读KDE On Windows

Mac OSX

KDevelop项目

如果你更喜欢KDevelop的项目文件(基本上就是Makefiles及为KDevelop生成的一些文件),这样运行CMake: $ cmake ../kdelibs -GKDevelop3 使用“cmake -h”来查看CMake支持那些生成器 (generators)及其他的选项。

CMake和Qt4

为了定位Qt 4,CMake会在你的执行路径中搜索qmake。CMake会使用QTDIR这个环境变量。因此请确保在执行路径中寻找到的第一个qmake就是你希望使用的。

更多细节

当CMake执行完成,它会生成一个叫“CMakeCache.txt”的文件。这个文件包含了CMake在你的系统上检测到的所有设置。如果你希望在其他生成器(generators)上运行CMake,或你希望CMake重新检测系统,请删除这个文件。

如果有些东西你知道它存在,而CMake没有检测到,你可以手动的告诉CMake到哪里去找它。CMake通过变量来存储这些信息。这些变量缓存在前面提到的 CMakeCache.txt中。这里有3个选项来手工调整这些变量:

  • 通过命令行告诉CMake现在的值: cmake ../kdelibs -DNAME_OF_THE_VARIABLE=value
  • 使用ccmake,它提供了一个基于鼠标的GUI来调整CMake变量(运行: ccmake ../kdelibs)
  • 直接编辑CMakeCache.txt(不推荐)

你应该最起码运行一次“ccmake ../kdelibs”,这样你会对CMake使用了那些变量有个印象。按“T”来查看“高级”的变量。如果有些东西CMake没有找到,运行ccmake并手工调整它。

一些你可能希望设置的变量:

  • CMAKE_INSTALL_PREFIX: cmake ../kdelibs -DCMAKE_INSTALL_PREFIX=/opt/kde4 相当于./configure --prefix=/opt/kde4
  • CMAKE_BUILD_TYPE: 决定你如何构建系统。你可以在“debugfull”、“debug”、“profile”、“relwithdebinfo”和“release”中进行选择。默认的是“relwithdebinfo”(-O2 -g)。更多细节查看FindKDE4Internal.cmake。
  • RPATH_STYLE: 这个不再有效了。默认情况下,一切都将在RPATH设置正确的情况下来构建。如果你不希望使用RPATH,将CMAKE_SKIP_RPATH设置为TRUE。
  • WITH_FOO: 这里有一些选项,例如WITH_CUPS或WITH_Jasper。如果你将他们关闭,cmake甚至不会去尝试寻找这个包。如果将它激活,cmake将会尝试寻找这个包。如果这样做失败了,你还可以通过上面介绍的方法手工设置。

环境变量

如果你在CMake没法找到的非标准位置安装了头文件或库( 例如Mac OSX下把fink安装到/sw),那么就请设置下面这些环境变量。尽管有相似的命名规则,这些设置在cmake的命令中并不会做为参数来工作。

  • CMAKE_INCLUDE_PATH,例如export CMAKE_INCLUDE_PATH=/sw/include
  • CMAKE_LIBRARY_PATH,例如export CMAKE_LIBRARY_PATH=/sw/lib

关于变量的更多信息,请参考 cmake.org wiki page

更进一步

如果cmake以“Generating done”结束,那表示没有错误,但如果以“Configuring done”结束,那表示有错误需要修正。当cmake成功结束,运行你的构建工具(如make、KDevelop、XCode或MSVC)来构建并等到它结束。然后运行“make install”。

如果你得到如下错误提示: CMake Error: This project requires some variables to be set, and cmake can not find them. Please set the following variables: X11_XTest_LIB (ADVANCED) 那表示你可能缺少库(或其他依赖包)。在cmake/modules目录中查找cmake无法找到的变量来确定是缺少哪个库文件。在上面的例子中,就是: FIND_LIBRARY(X11_XTest_LIB Xtst ${X11_LIB_SEARCH_PATH}) 这里缺失的库是Xtst。然后你找到这个库(也许是通过安装libXtst-devel)并再次运行cmake。

在简单的应用中使用CMake

这是最简单的CMakeLists.txt: add_executable(hello main.cpp) 这将从main.cpp源码文件创建一个叫“hello”(Windows下叫“hello.exe”)的可执行文件。你可以根据自己的需要将C和C++文件混合。在同一个CMakeLists.txt可以有多个可执行文件和库。同一个源码文件可以用于不同的目的,源码可以从其他目标中为每个目的独立的编译。CMake语言最重要的部分可能是变量: SET( MY_SOURCES main.cpp widget.cpp) MESSAGE(STATUS "my sources: ${MY_SOURCES}") 使用SET()命令来为变量设置值。如果你列出了一个以上的字符串,变量将是串列表。列表是一列由分号隔开的字符串。如果只设置个一项,那么这项只有一个值。可以通过${VAR}获得变量的值。可以使用FOREACH()来迭代一份列表: FOREACH(next_ITEM ${MY_SOURCES})

  MESSAGE(STATUS "next item: ${next_ITEM}")

ENDFOREACH(next_ITEM ${MY_SOURCES}) CMake中的命令是大小写无关的。变量名和参数名是大小写相关的。

还可以测试一些不同的东西: IF (UNIX)

  MESSAGE(STATUS "This is UNIX (including OS X and CygWin)")

ENDIF (UNIX)

IF (MSVC)

  SET(MY_SRCS ${MY_SRCS} winextra.cpp)

ENDIF (MSVC) 在第二个例子中,你可以看到如何将项目附加到列表中。

在cmake Wiki中有一份使用cmake构建KDE4软件的指导,推荐阅读。

在KDE项目中使用CMake

这里是一份基本的构建一个小KDE4项目的CMakeList文件:

PROJECT( kde4project) FIND_PACKAGE(KDE4 REQUIRED) INCLUDE_DIRECTORIES( ${KDE4_INCLUDES} )

SET(KDE4ProjectSources kde4mainapp.cpp someclass.cpp someotherclass.cpp)

KDE4_AUTOMOC( ${KDE4ProjectSources} )

KDE4_ADD_EXECUTABLE(kde4project ${KDE4ProjectSources} )

TARGET_LINK_LIBRARIES(kde4project ${KDE4_KDEUI_LIBS} ${KDE4_KPARTS_LIBS} )

扩展CMake

CMake可以通过cmake脚本扩展,CMake带有大量的脚本,在UNIX下,这些脚本默认安装在 /usr/local/share/CMake/Modules/内。KDE库也在/apps/cmake/modules/安装了一些CMake模块。这里的文件将被代替CMake的系统全局模块路径。FindFOO.cmake用来检测软件包, 这里有更多信息。在CMake中也可以写宏文件,对于大多数的软件构建来说,他们足够强大了。这些宏不会做为通用语言来使用。

你还可以在CMake中编写宏。他们非常强大,可以满足你编译的软件中所需要的所有事情,但是他们并不是被用作通用目的的编程语言。

将基于autotools的KDE软件转换为CMake

你可以在kdesdk/cmake/找到am2cmake脚本。这是ruby写成的,所以确定你的系统安装了ruby。在你的源码目录最上层运行am2cmak: $ cd src/mykooltool/ $ am2cmake --kde4 不要忘了开关“--kde4”,不然系统无法生成适合KDE4的文件。转换文件可能会正常工作,但编译的项目将需要一些额外的编辑。

你可能需要:

  • 使用INCLUDE_DIRECTORIES()添加更多include目录。
  • 使用TARGET_LINK_LIBRARIES()添加更多链接库。
  • 使用ADD_DEFINITIONS()添加更多编译开关。
  • 添加一些“configure”检查,参照如何进行平台检查如何找到已经安装的软件
  • 特别要注意以往的libtool便捷库,CMake并不支持这些库,而是生成一个ConvenienceLibs.cmake文件代替。在这个文件里,你可以为每个便捷库找到一个包含了这个库所有源码的变量。对于链接到这些库的目标,只要在源码中添加这些变量即可。
  • 一个AdditionalInfo.txt文件将被创建。你可以在这里找到项目所有的*.in和*.in.in文件。这些文件完成的任务将被手工转换到CMake.

常见问题

如何使我最喜欢的编辑器支持CMake的语法和缩进?

请阅读CMake Wiki中CMake编辑器支持这部分。这里介绍了如何设置Emac、VI、Kat、KWrite和KDevelop。

我需要在构建过程中产生一些文件,我该如何做?

使用ADD_CUSTOM_COMMAND()。这里有解释:在构建过程中如何生成一个源文件

我想在产生文件的构建过程中创建一个稍后使用的可执行文件,我要如何做?

假定可执行文件叫genembed。那么使用KDE4_ADD_EXECUTABLE(foo RUN_UNINSTALLED ${fooSources})来生成可执行文件。RUN_UNINSTALLED选项非常重要,因为可执行文件必须从构建目录运行,并会链接到builddir中的一些库。为达到这个目的,可执行文件通过相应设置的RPATH和包装的外壳脚本编译,和可执行文件的命名一样只是多了“.sh”后缀。这个外壳脚本设置LD_LIBRARY_PATH并调用实际的可执行文件。象上面介绍的在ADD_CUSTOM_COMMAND()中使用这个包装的外壳脚本。可以通过查询WRAPPER_SCRIPT来获得名称和确切的路径。这里有一个来自kdelibs/kstyles/keramik/完整的例子:

  1. build the executable

KDE4_ADD_EXECUTABLE(genembed RUN_UNINSTALLED ${genembed_SRCS})

  1. get the name of the generated wrapper script (which sets up LD_LIBRARY_PATH)

GET_TARGET_PROPERTY(GENEMBED_EXECUTABLE genembed WRAPPER_SCRIPT)

  1. and the custom command

ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/keramikrc.h

 COMMAND ${GENEMBED_EXECUTABLE} --file ${CMAKE_CURRENT_BINARY_DIR}/keramikPics.txt > \
 ${CMAKE_CURRENT_BINARY_DIR}/pixmaps.keramik
 DEPENDS genembed ${keramikPics}

)

如你所见genembed也做为依赖关系列出。这表示CMake知道它应该在执行这些规则之前创建genembed的可执行文件。

我不想设置-DCMAKE_INSTALL_PREFIX命令行参数。CMake是否支持KDEDIR环境变量?

不。KDE4反对使用$KDEDIR。

为什么我会得到类似/usr/lib/qt4/include/QtCore/qstring.h:536: undefined reference to `QString::fromLatin1_helper(char const*, int)'的编译错误?

如果你的qt/lib目录下有个老版本的Qt4,你必须删除这些老版本(4.0.4)文件。

我如何让CMake创建noisy makefiles?我希望准确的看到make过程执行的命令。

给make传递 VERBOSE 变量,例如: % make VERBOSE=1 或者 % VERBOSE=1 make

更多细节请查看CMake wiki: [http://www.cmake.org/Wiki/CMake_FAQ#Is_there_an_option_to_produce_more_.27verbose.27_compiling.3F 有没有选项可以产生更多的“verbose”编译?]

产生的Makefiles中没有“make distclean”标签。我如何才能清理包括cache文件在内的所有文件?

只需删除构建目录,或目录里包含的内容。