﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-Error-随笔分类-QT</title><link>http://www.cppblog.com/Error/category/19669.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 05 Dec 2012 20:14:57 GMT</lastBuildDate><pubDate>Wed, 05 Dec 2012 20:14:57 GMT</pubDate><ttl>60</ttl><item><title>cmake编译qt工程</title><link>http://www.cppblog.com/Error/archive/2012/07/16/183712.html</link><dc:creator>Enic</dc:creator><author>Enic</author><pubDate>Mon, 16 Jul 2012 04:24:00 GMT</pubDate><guid>http://www.cppblog.com/Error/archive/2012/07/16/183712.html</guid><wfw:comment>http://www.cppblog.com/Error/comments/183712.html</wfw:comment><comments>http://www.cppblog.com/Error/archive/2012/07/16/183712.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Error/comments/commentRss/183712.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Error/services/trackbacks/183712.html</trackback:ping><description><![CDATA[<div><h1><div><span style="font-size: 10pt;">#实际上是调用cmake安装目录\share\cmake-2.8\Modules\FindQt4.cmake</span><br /><span style="font-size: 10pt;">#设置好一批预定义的东东</span><br /><span style="font-size: 10pt;">FIND_PACKAGE(Qt4 REQUIRED)</span><br /><br /><span style="font-size: 10pt;"># 不解释</span><br /><span style="font-size: 10pt;">SET(helloworld_SOURCES main.cpp hellowindow.cpp)</span><br /><span style="font-size: 10pt;">SET(helloworld_HEADERS hellowindow.h)</span><br /><br /><span style="font-size: 10pt;">#处理helloworld_HEADERS中的MOC宏，处理结果生成在helloworld_HEADERS_MOC</span><br /><span style="font-size: 10pt;">QT4_WRAP_CPP(helloworld_HEADERS_MOC ${helloworld_HEADERS})</span><br /><br /><span style="font-size: 10pt;">#添加QT头文件和宏</span><br /><span style="font-size: 10pt;">INCLUDE(${QT_USE_FILE})</span><br /><span style="font-size: 10pt;">ADD_DEFINITIONS(${QT_DEFINITIONS})</span></div><br /></h1><h1><br /></h1><h1><br /></h1><h1><br /></h1><h1><br /></h1><h1><br /></h1><h1>**********************************************<br /></h1><h1>Using CMake to Build Qt Projects</h1> 				     				    <p>Written by: Johan Thelin</p>  <p> Qt comes with the QMake tool for handling cross platform building issues. However, there are other build systems available such as autotools, SCons and CMake. These tools meet different criterias, for example external dependencies. </p>  <p> When the KDE project shifted from Qt 3 to Qt 4 the project changed build tool from autotools to CMake. This has given CMake a special position in the Qt world&nbsp;&amp;emdash;&nbsp;both from the number of users point and from a feature support and quality point. Seen from a workflow point of view, Qt Creator supports CMake since version 1.1 (1.3 if you want to use a Microsoft toolchain). </p>  <h2>A Basic Example</h2>  <p> In this article we will focus on CMake itself, and how to use it in conjunction with Qt. To do this, let's start with an overview of a simple, but typical CMake-based project. As you can tell from the listing below, the project consists of some source files and a text file. </p>  <pre>$ ls CMakeLists.txt hellowindow.cpp hellowindow.h main.cpp </pre>  <p> Basically, the CMakeLists.txt file replaces the projectfile used by QMake. To build the project, create a build directory and run cmake and then make from there. The reason for creating a build directory is that CMake has been built with out-of-source building in mind from the very start. It is possible to configure QMake to place intermediate files outside the source, but it requires extra steps. With CMake, it is the default. </p>  <pre>$ mkdir build $ cd build $ cmake .. &amp;&amp; make </pre>  <p align="center"> <a href="http://doc.qt.nokia.com/qq/34/cmake-build.png"><img src="http://doc.qt.nokia.com/qq/34/cmake-build-small.png" alt="" /></a><br /> <em>CMake building a basic project.</em> </p>  The argument given to CMake refers to the directory where the CMakeLists.txt file resides. This file  controls the whole build process. In order to fully understand it, it is important to recognize how the build process looks.  The figure below shows how the user files: sources, headers, forms and resource files are processed by the various Qt code generators before joining the standard C++ compilation flow. Since QMake was designed to handle this flow, it hides all the details of this flow.  <p align="center"> <a href="http://doc.qt.nokia.com/qq/34/qt-build-system.png"><img src="http://doc.qt.nokia.com/qq/34/qt-build-system-small.png" alt="" /></a><br /> <em>The Qt build system.</em> </p>  <p> When using CMake, the intermediate steps must be handled explicitly. This means that headers with <tt>Q_OBJECT</tt> macros must be run through moc, user interface forms must be processed by uic and resource files must pass through rcc. </p>  <p> In the example that we started with the world is slightly easier, though. It is limited to a single header file that needs to meet moc. But first, the CMakeLists.txt defines a project name and includes the Qt4 package as a required component. </p>  <pre>PROJECT(helloworld) FIND_PACKAGE(Qt4 REQUIRED) </pre>  <p> Then all sources involved in the build process are assigned to two variables. The SET command assigns the variable listed first with the values that follow. The names, <tt>helloworld_SOURCES</tt> and <tt>helloworld_HEADERS</tt>, is by convention. You can name them either way you like. </p>  <pre>SET(helloworld_SOURCES main.cpp hellowindow.cpp) SET(helloworld_HEADERS hellowindow.h) </pre>  <p> Notice that the headers only include the headers that needs to be processed by moc. All other headers can be left out of the CMakeLists.txt file. This also implicates that if you add a <tt>Q_OBJECT</tt> macro to any of your classes you must ensure that it is listed here. </p>  <p> To invoke moc, the macro <tt>QT4_WRAP_CPP</tt> is used. It assigns the names of the resulting files to the variable listed first. In this case the line looks as follows. </p>  <pre>QT4_WRAP_CPP(helloworld_HEADERS_MOC ${helloworld_HEADERS}) </pre>  <p> What happens is that all headers are processed by moc and the names of the resulting source files are listed in the <tt>helloworld_HEADERS_MOC</tt> variable. Again, the variable name is by convention rather than forced. </p>  <p> In order to build a Qt application, the Qt include directories needs to be added as well as a range of defines need to be set. This is handled through the commands <tt>INCLUDE</tt> and <tt>ADD_DEFINITIONS</tt>. </p>  <pre>INCLUDE(${QT_USE_FILE}) ADD_DEFINITIONS(${QT_DEFINITIONS}) </pre>  <p> Finally, CMake needs to know the name of the resulting executable and what to link it to. This is conveniently handled by by the commands <tt>ADD_EXECUTABLE</tt> and <tt>TARGET_LINK_LIBRARIES</tt>. Now CMake knows what to build, from what and through which steps. </p>  <pre>ADD_EXECUTABLE(helloworld ${helloworld_SOURCES}      ${helloworld_HEADERS_MOC}) TARGET_LINK_LIBRARIES(helloworld ${QT_LIBRARIES}) </pre>  <p> When reviewing the listing above, it relies on a number of variables starting with QT_. These are generated by the Qt4 package. However, as a developer, you must explicitly refer to them as CMake is not build as tightly to suite Qt as QMake. </p>  <h2>Adding More Qt</h2>  <p> Moving beyond the initial example, we now look at a project with both resources and user interface forms. The resulting application will look quite similar to its predecessor, but all the magic takes place under the hood. </p>  <p> The CMakeLists.txt file start by naming the project and including the Qt4 package - the complete file can be downloaded as a source code package accompanying this article. Then all the input files are listed and assigned to their corresponding variables. </p>  <pre>SET(helloworld_SOURCES main.cpp hellowindow.cpp) SET(helloworld_HEADERS hellowindow.h) SET(helloworld_FORMS hellowindow.ui) SET(helloworld_RESOURCES images.qrc) </pre>  <p> The new file types are then handled by <tt>QT4_WRAP_UI</tt> and <tt>QT4_ADD_RESOURCES</tt>. These macros operate in the same ways as <tt>QT4_WRAP_CPP</tt>. This means that the resulting files are assigned to variable given as the left-most argument. Notice that the header files generated by uic are needed as we need to build a dependency relationship between them and the final executable. Otherwise they will not be created. </p>  <pre>QT4_WRAP_CPP(helloworld_HEADERS_MOC ${helloworld_HEADERS}) QT4_WRAP_UI(helloworld_FORMS_HEADERS ${helloworld_FORMS}) QT4_ADD_RESOURCES(helloworld_RESOURCES_RCC ${helloworld_RESOURCES}) </pre>  <p> All the resulting files are then added as dependencies to the <tt>ADD_EXECUTABLE</tt> macro. This includes the uic generated headerfiles. This establishes the dependency from the executable to the hellowindow.ui file through the intermediary ui_hellowindow.h header. </p>  <pre>ADD_EXECUTABLE(helloworld ${helloworld_SOURCES}      ${helloworld_HEADERS_MOC}      ${helloworld_FORMS_HEADERS}      ${helloworld_RESOURCES_RCC}) </pre>  <p> Before this file can be used to build the project there is a small caveat to handle. As all intermediate files are generated outside the source tree, the header file generated by uic will not be located by the compiler. In order to handle this, the build directory needs to be added to the list of include directories. </p>  <pre>INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) </pre>  <p> With this line, all intermediary files will be available in the include path. </p>  <h2>Qt Modules</h2>  <p> Until now we have relied on the QtCore and QtGui modules. To be able to use more modules, the CMake environment must be tuned to enable them. By setting them to TRUE using the SET command, the included modules can be controlled. </p>  <p> For instance, to enable OpenGL support add the following line to your CMakeLists.txt. </p>  <pre>SET(QT_USE_QTOPENGL TRUE) </pre>  <p> The most commonly used modules are controlled using the following variables. </p>  <ul><li><tt>QT_USE_QTNETWORK</tt></li><li><tt>QT_USE_QTOPENGL</tt></li><li><tt>QT_USE_QTSQL</tt></li><li><tt>QT_USE_QTXML</tt></li><li><tt>QT_USE_QTSVG</tt></li><li><tt>QT_USE_QTTEST</tt></li><li><tt>QT_USE_QTDBUS</tt></li><li><tt>QT_USE_QTSCRIPT</tt></li><li><tt>QT_USE_QTWEBKIT</tt></li><li><tt>QT_USE_QTXMLPATTERNS</tt></li><li><tt>QT_USE_PHONON</tt></li></ul>  <p> In addition to these, the variable <tt>QT_DONT_USE_QTGUI</tt> can be used to disable the use to QtGui. There is a similar variable to disable QtCore, but that is more to be feature complete than to actually add much useful value. </p>  <h2>Added Value and Complexity</h2>  <p> It is not as trivial to use CMake as QMake, but the rewards are more features. The most notable point when moving from QMake is CMake's built in support for out-of-source builds. It can really change habits, and thus make versioning code much easier.  </p>  <p> It is also possible to add conditionals for various platforms and build scenarios. For instance, use different libraries for different platforms, as well as tuning the same project differently for different situations. </p>  <p> Other powerful features are the ability to generate multiple executables and libraries in one build as well as using said executables and libraries in the same build. This, in combination with the QtTest module can handle complex build situations from a single configuration. </p>  <p> The choice between CMake and QMake is really quite easy. For straight forward Qt projects, QMake is the obvious choice. When the build requirements passes the complexity threshold for QMake, CMake can take its place. With Qt Creator's support for CMake, the same tools can still be used. </p></div> <img src ="http://www.cppblog.com/Error/aggbug/183712.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Error/" target="_blank">Enic</a> 2012-07-16 12:24 <a href="http://www.cppblog.com/Error/archive/2012/07/16/183712.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>