`
doujiu
  • 浏览: 90269 次
  • 性别: Icon_minigender_1
  • 来自: 哈尔滨
社区版块
存档分类
最新评论

非常详细的cmake用例,收藏

阅读更多
CMake资料2 - Ogre3D开放资源地带
CMake资料2
出自Ogre3D开放资源地带
跳转到: 导航, 搜索

http://bbs.osgchina.org/redirect.php?tid=1229&goto=lastpost

1.5 VersionMe工程设计

下面我们将着手设计一个稍微复杂一些的工程,名为VersionMe。它同样包括一个动态链接库工程和一个依赖于它的可执行工程,并且计划实现以下一些功能:


可以查询当前操作系统的版本;

可以查询系统中安装的OpenSceneGraph库的版本;

可以执行上一次我们创建的HelloWorld工程的方法;


为了使我们的工程更具备开源工程的特征,我们模仿OpenSceneGraph的文件夹结构,设计如下:

Image:cmake1.jpg


名为VersionLib的链接库工程的头文件和源代码文件将分别保存到include和src两个目录下;而名为test的可执行工程则单独保存在同名目录下;此外,CMakeModules目录专职负责保存相关的CMake脚本数据。

这个工程的重点毫无疑问是VersionLib链接库,它的工作是提供显示系统版本和OSG版本的函数,以及调用之前的Hello::sayHello方法,再次在控制台界面上显示“Hello CMake!”这一行简单而友好的欢迎文字。

VersionLib库包括一个头文件Version和一个源代码文件Version.cpp,其代码如下:

/* Version */
#ifndef H_VERSION
#define H_VERSION
#if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__)
# ifdef VERSIONME_LIBRARY
# define VERSIONME_EXPORT __declspec(dllexport)
# else
# define VERSIONME_EXPORT __declspec(dllimport)
# endif
#else
# define VERSIONME_EXPORT
#endif
class VERSIONME_EXPORT Version
{
public:
void printHello();
const char* systemVersion();
const char* osgVersion();
};
#endif

/* Version.cpp */
#ifdef _MSC_VER
# include <windows><br>#else<br># include <sys utsname><br>#endif<br>#include <sstream><br>#include <hellolib hello=""><br>#include <osg version=""><br>#include <versionlib version=""><br><br>static char g_version[255] = "";<br>void Version::printHello()<br>{<br> Hello hello;<br> hello.sayHello();<br>}<br>const char* Version::systemVersion()<br>{<br> std::stringstream stream;<br>#ifdef _MSC_VER<br> OSVERSIONINFO osvi;<br> ZeroMemory( &amp;osvi, sizeof(OSVERSIONINFO) );<br> osvi.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );<br> GetVersionEx( &amp;osvi );<br> stream &lt;&lt; "Windows-";<br> stream &lt;&lt; osvi.dwMajorVersion &lt;&lt; "." &lt;&lt; osvi.dwMinorVersion &lt;&lt; "."<br> &lt;&lt; osvi.dwBuildNumber;<br>#else<br> struct utsname buff;<br> uname( &amp;buff );<br> stream &lt;&lt; buff.sysname &lt;&lt; "-" &lt;&lt; buff.release;<br>#endif<br> stream &gt;&gt; g_version;<br> return g_version;<br>}<br>const char* Version::osgVersion()<br>{<br> return osgGetVersion();<br>}<br><br>具体的实现过程我们不作介绍,这里的osgGetVersion()是OSG的版本查询函数,而GetVersionEx()和uname则分别是Windows和Linux下的版本查询API函数。嗯,是否觉得这里Windows API的实现更加费劲呢?(^_^)<br><br>此外,这里我们引用头文件Hello并调用了其中的函数,因此在之后的CMake脚本设计过程中,要考虑正确搜索和指定Hello头文件依赖目录以及依赖库的路径位置。<br><br>而Test工程的源代码就很简单了,只有一个test.cpp文件,内容如下:<br><br><br>/* test.cpp */<br>#include <iostream><br>#include <versionlib version=""><br>int main( int argc, char** argv )<br>{<br> Version obj;<br> std::cout &lt;&lt; "Operating System Version: " &lt;&lt; obj.systemVersion() &lt;&lt; std::endl;<br> std::cout &lt;&lt; "OpenSceneGraph Version: " &lt;&lt; obj.osgVersion() &lt;&lt; std::endl;<br> obj.printHello();<br> return 0;<br>}<br><br>我们希望在CMake-GUI窗口中有一个用户选项,用来决定是否编译这个Test工程。另外,我们还希望能够使用类似“make install”这样的命令来安装所有工程相关的动态库,静态库,头文件和可执行文件。(之前的HelloWorld工程是无法这样做的)<br><br>以上就是VersionMe工程设计的所有要求。下面,我们将开始CMake脚本的设计。<br><br>位于VersionMe根目录下的CMakeLists.txt脚本如下:<br><br>PROJECT( VersionMe )<br>CMAKE_MINIMUM_REQUIRED( VERSION 2.4.7 )<br>IF( COMMAND CMAKE_POLICY )<br> CMAKE_POLICY( SET CMP0003 NEW )<br>ENDIF( COMMAND CMAKE_POLICY )<br><br>SET( CMAKE_MODULE_PATH<br> "${PROJECT_SOURCE_DIR}/CMakeModules/;${CMAKE_MODULE_PATH}" )<br>SET( CMAKE_DEBUG_POSTFIX "d"<br> CACHE STRING "add a postfix, usually d on windows" )<br>OPTION( BUILD_TEST "Set to ON to build the test application." ON )<br>IF( WIN32 )<br> IF( MSVC )<br> ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )<br> ADD_DEFINITIONS( -D_CRT_SECURE_NO_DEPRECATE )<br> ENDIF( MSVC )<br>ENDIF( WIN32 )<br><br>FIND_PACKAGE( Hello )<br>FIND_PACKAGE( osg )<br>INCLUDE( CustomModules )<br>INCLUDE_DIRECTORIES( include )<br>ADD_SUBDIRECTORY( src/VersionLib )<br>IF( BUILD_TEST )<br> ADD_SUBDIRECTORY( test )<br>ENDIF( BUILD_TEST )<br><br>这一次的代码编写恐怕比之前丰富了不少,有点眼晕吗?没关系,我们结合上一节的CMake命令和内置变量介绍,一点一点地分析。<br><br>首先设置工程名称和所需的CMake版本,此处还使用了一个CMAKE_POLICY命令来设置版本的兼容性,以避免一些不必要的警告信息。<br><br>之后,我们指定基本的CMake配置参数,包括模块搜索目录,Debug版本生成目标的后缀,一个用户选项BUILD_TEST,以及针对Visual Studio的一些宏定义设置。(通过判断WIN32和MSVC内置变量来执行这一动作)<br><br>后面的工作比较重要一些,首先是使用FIND_PACKAGE来搜索外部依赖库的路径。CMake中预置了很多模块搜索的脚本,可以用来检索各种知名工程的文件和路径信息,并以CMake变量的方式返回。例如,FIND_PACKAGE(OpenGL)将自动调用CMake安装目录share/cmake-2.6/Modules文件夹中的FindOpenGL.cmake脚本的内容,自动搜索或者由用户指定OpenGL头文件和链接库的位置,并主要返回以下变量:<br><br> * OPENGL_FOUND:是否找到OpenGL库的标识;<br> * OPENGL_GLU_FOUND:是否找到GLU库的标识;<br> * OPENGL_INCLUDE_DIR:头文件gl.h所在的文件夹路径;<br> * OPENGL_gl_LIBRARY:链接库opengl32的绝对路径;<br> * OPENGL_glu_LIBRARY:链接库glu32的绝对路径; <br><br>这个时候可以用下面的形式为名为ProjName的工程指定依赖库OpenGL的头文件和链接库文件,脚本代码如下:<br><br>INCLUDE_DIRECTORIES( ${OPENGL_INCLUDE_DIR} )<br>TARGET_LINK_LIBRARIES( ProjName<br> ${OPENGL_gl_LIBRARY}<br> ${OPENGL_glu_LIBRARY}<br>)<br><br>注意Windows环境下不存在OPENGL_INCLUDE_DIR,因为没有必要做特别指定。<br><br>回到我们的VersionMe工程来,这里我们试图搜索两个外部依赖库的信息:Hello代表我们之前生成的HelloWorld工程,而OSG表示外部的OpenSceneGraph工程。后者的搜索模块在CMake的较新版本中已经包含,包括Findosg,FindosgUtil,FindosgViewer等多个cmake文件,可以使用FIND_PACKAGE直接调用并返回相应的头文件和链接库路径变量。(通常名为OSG_INCLUDE_DIR,OSG_LIBRARY等)<br><br>但是Hello这个库却不可能有相应的模块文件,毕竟CMake可不知道我们之前做了什么。因此我们需要手动编写名为FindHello.cmake的脚本,并将其保存在CMakeModules目录下。具体的脚本编写方法我们稍后再说。<br><br>在使用FIND_PACKAGE搜索到外部Hello库和OSG库的具体位置之后,(也可能找不到,此时需要在CMake-GUI中手动进行设置),下一步还要使用INCLUDE命令包含一个自定模块CustomModules.cmake。它的工作是定义了几个方便VersionMe工程设置的宏函数,以免我们在后面的子工程创建过程中编写过多的代码;OSG中有一个类似功能的模块文件OsgMacroUtils.cmake,有兴趣的朋友不妨提前阅读一下。<br><br>笔者在CustomModules中手动编写了三个实用的宏函数:INCLUDE_FOR_PROJECT,LINK_PROJECT以及INSTALL_PROJECT。它们不仅将在VersionMe的设计中大显身手,也许更可以为您自己的工程脚本编写提供一些助力。<br><br>在INCLUDE命令之后,注意我们还使用了一次INCLUDE_DIRECTORIES命令。这是什么意思呢?再次考虑VersionMe的文件夹结构,和之前的HelloWorld工程不同,这一次所有的头文件不再与源代码文件放在同一目录下,而是放置在单独的include文件夹,以便于更有效的文件管理。但是,对于编译器而言,这样会使它无法正确搜索到#include引用的头文件位置。因此我们必须提前设置好相应的头文件依赖路径,并且这一设置对于所有的子工程都是统一的。<br><br>仅对于上例而言,下面两种指定头文件路径的方式是等价的:<br><br>INCLUDE_DIRECTORIES( include )<br>INCLUDE_DIRECTORIES( “${PROJECT_SOURCE_DIR}/include” )<br><br>这之后的脚本代码就轻松一点了,ADD_SUBDIRECTORY命令指定了下一级子工程CMake脚本的位置,此外我们还通过判断用户是否选择了BUILD_TEST选项,来决定是否编译test工程。(即是否进入test工程所在的脚本目录)<br><br>我们快速浏览一下VersionLib子工程和test子工程的脚本代码:<br><br>SET( LIB_NAME VersionLib )<br>SET( HEADER_PATH ${PROJECT_SOURCE_DIR}/include/${LIB_NAME} )<br>SET( ${LIB_NAME}_HEADERS<br> ${HEADER_PATH}/Version<br>)<br>SET( ${LIB_NAME}_SOURCES<br> Version.cpp<br>)<br>ADD_DEFINITIONS( -DVERSIONME_LIBRARY )<br>ADD_LIBRARY( ${LIB_NAME} SHARED<br> ${${LIB_NAME}_HEADERS}<br> ${${LIB_NAME}_SOURCES}<br>)<br>SET_TARGET_PROPERTIES( ${LIB_NAME}<br> PROPERTIES DEBUG_POSTFIX<br> "${CMAKE_DEBUG_POSTFIX}"<br>)<br><br>INCLUDE_FOR_PROJECT( ${LIB_NAME} HELLO OSG )<br>LINK_PROJECT( ${LIB_NAME} HELLO OSG )<br>INSTALL_PROJECT( ${LIB_NAME} )<br><br>虽然看上去复杂了一些,但其实源文件设置和工程属性设置的脚本代码并没有太多深奥的地方。无非是大量使用CMake变量而已,如果您熟悉其它程序语言设计的话,相信很快会对此习以为常,并能够适当地在自己的工程中加以借鉴。当使用ADD_LIBRARY新增了一个动态链接库工程之后,我们还额外地使用SET_TARGET_PROPERTIES设置了工程Debug版本的生成目标后缀——它有什么作用呢?还记得您编译OSG的时候,会生成osgd,osgDBd,osgViewerd等一系列有别于Release版本文件的链接库吧,这里就是同样的道理,这个命令将为VersionLib库的Debug版本文件新增一个用于区分的后缀,使之成为VersionLibd.dll的形式,要知道编译器自己可不会这样做。<br><br>之后我们依次调用三个自定义的宏函数,也就是前文说过的INCLUDE_FOR_PROJECT,LINK_PROJECT和INSTALL_PROJECT。它们的工作依次是:指定工程所用的头文件依赖目录(Hello库和OSG库的头文件目录);工程所需的外部链接库文件绝对路径(HelloLib.lib和osg.lib);以及指定安装这个工程的相关生成文件到预设的目录中。<br><br>这些宏函数的具体实现过程稍后详述。<br><br>子工程test的脚本代码为:<br><br>SET( EXAMPLE_NAME Test )<br>SET( EXAMPLE_FILES<br> test.cpp<br>)<br>ADD_EXECUTABLE( ${EXAMPLE_NAME} test.cpp )<br>SET_TARGET_PROPERTIES( ${EXAMPLE_NAME}<br> PROPERTIES DEBUG_POSTFIX<br> "${CMAKE_DEBUG_POSTFIX}" )<br>LINK_PROJECT( ${EXAMPLE_NAME} VersionLib )<br>INSTALL_PROJECT( ${EXAMPLE_NAME} )<br><br>注意我们没有必要为Test工程设置头文件依赖目录了,从test.cpp的源代码可以看出,它只需要引用VersionLib/Version这个头文件,(以及一个可以由编译器自动找到的STL头文件iostream)而这个文件的路径位于:${PROJECT_SOURCE_DIR}/include,毫无疑问,它在前文中已经由INCLUDE_DIRECTORIES设置完毕了。<br><br>Test子工程依赖于即将生成的VersionLib库,不必担心它们的编译顺序上会有什么偏差,CMake会为我们安排好一切。 </versionlib></iostream></versionlib></osg></hellolib></sstream></sys></windows>


分享到:
评论

相关推荐

    测试用例实例++非常详细

    测试用例示例测试用例示例测试用例示例测试用例示例测试用例示例测试用例示例测试用例示例测试用例示例测试用例示例测试用例示例测试用例示例

    绝对超详细测试用例设计

    绝对超详细测试用例设计,不得违权,仅供参考学习,谢谢配合!

    软件测试用例模板一详细用例(经典)

    软件测试用例模板详细用例(经典) 本文档提供了一个详细的软件测试用例模板,涵盖了动能测试点、性能测试点和兼容性测试点。该模板适用于各种软件测试项目,用户只需根据实际情况替换内容。下面是该模板的详细说明...

    用例的详细讲解

    详细的用例讲解,做开发设计必备的知识,你值得拥有

    游戏-详细测试用例(模版).xlsx

    电子表格模板,内容详细,包括组队系统等测试用例 创建队伍、加入队伍、队伍排序、队伍解散、退出队伍、组队战斗、组队功能和特殊情况等 内容仅供参考

    软件的测试用例实例(非常详细).pdf

    本文将深入探讨测试用例的概念、分类和在实际软件测试中的应用,以“软件的测试用例实例(非常详细)”为背景。 首先,测试用例的目的是确保软件在各种条件下都能正常工作。比如兼容性测试,这是测试软件是否能在不同...

    测试用例内有三个测试用例相关文件

    2. **详细测试用例.doc**:这份Word文档可能包含了一个或多个具体测试用例的详细描述,每个都按照上述模板中的元素进行编写。这些详细测试用例将为执行者提供明确的指导,帮助他们准确地进行测试,确保每个角落的...

    需求用例编写详细规范

    【需求用例编写详细规范】 1. 简介 1.1 文档目的 本规范旨在为EBS(Enterprise Business System)开发小组提供一套详细的需求用例编写指南,确保需求能够清晰、完整且准确地传达给所有项目参与者。通过遵循此规范...

    用户注册测试用例(详细)

    本测试用例详细文档提供了关于用户注册和密码修改的关键测试点,以及一个实际的BUG提交报告示例,对于新手测试工程师来说是非常宝贵的参考资料。通过理解和应用这些知识点,可以帮助测试人员更高效地完成测试任务,...

    通用测试用例模板,很适合测试的人

    测试用例模板是软件质量保证过程中的重要工具,它详细定义了如何对软件进行测试,以验证其功能是否符合预期。下面将详细解释这个模板的各个部分及其在测试中的作用。 1. **修订历史记录**:这部分记录了测试用例的...

    软件测试用例模板一详细用例(经典).doc

    一个详细的测试用例通常包含以下要素: 1. **用例编号**:用于唯一标识每个测试用例,方便管理和跟踪。例如,TestCase_LinkWorks_WorkEvaluate_02。 2. **项目名称**:指出该测试用例属于哪个项目,便于了解测试的...

    测试用例+详细

    测试用例详细设计 本测试用例旨在对LinkWorks_WorkEvaluate项目的WorkEvaluate模块进行详细的测试,涵盖了该模块的所有功能和业务规则。该测试用例非常适合新手作为参考,帮助他们更好地理解测试用例的设计和实施。...

    详细的软件测试用例模板——excel版

    1、有详细的用例编写模板,一般的问题都已有涉及到。2、编辑测试用例的时候,只要套用这个模板就可以了。

    企业测试用例

    测试用例是一份详细的文档,描述了对软件进行测试的具体步骤,包括输入数据、预期结果以及执行这些步骤的顺序。它的主要目的是验证软件系统是否符合预先定义的需求或规范,确保在实际运行环境中能够正确无误地工作。...

    增加功能测试用例详细步骤

    这是一个软件测试里增加功能测试用例的详细步骤

    软件测试用例模板一详细用例经典.doc

    软件测试用例模板详细用例经典是软件测试中非常重要的一部分,以下是对该模板的详细分析和知识点总结: 一、测试用例设计 测试用例设计是软件测试的核心部分,该模板提供了一个详细的测试用例设计模板,包括测试...

Global site tag (gtag.js) - Google Analytics