本文总结了在windows上使用cocos compile
命令编译cocos2d-x安卓apk的基本用法,以及记录一个使用NDK-r9d(gcc 4.8)编译C++11的@H_502_5@hash_map遇到的一个问题:@H_502_5@error: invalID use of incomplete type 'struct std::hash<MessageType>'。
从2.x到3.x,cocos的辅助工具做的越来越完善了,2.x刚开始的时候编译apk是比较费劲的,除了最基本的安装JDK,NDK,AndroidSDK,Ant还要装cygwin,自己配环境变量,执行打包脚本等等。我最近使用的是cocos2d-x官方的github仓库中的默认v3分支最新代码(3.10),以编译cpp-tests工程为androID apk为例,使用最新的打包方式:cocos compile.
基本的环境准备如今的cocos,大量使用了Python作为其辅助工具,因此第一步就是装好python,推荐比较经典的2.7.x版本。
装好python之后就可以到引擎的根目录,执行setup.py来初始化cocos环境了,它会引导你配置好cocos命令行工具执行所需要的环境变量和工具。其中包括:
<code >Setting up cocos2d<span >-x</span><span >...</span><span >-></span>Check environment <span >variable</span> COCOS_CONSolE_ROOT <span >-></span>Search for environment <span >variable</span> COCOS_CONSolE_ROOT<span >...</span> <span >-></span>COCOS_CONSolE_ROOT is found : D:<span >\</span>codes<span >\</span>cocos2d<span >-x</span><span >\</span>tools<span >\</span>cocos2d<span >-console</span><span >\</span>bin<span >variable</span> COCOS_X_ROOT <span >variable</span> COCOS_X_ROOT<span >...</span> <span >-></span>COCOS_X_ROOT is found : D:<span >\</span>codes<span >variable</span> COCOS_TEMPLATES_ROOT <span >variable</span> COCOS_TEMPLATES_ROOT<span >...</span> <span >-></span>COCOS_TEMPLATES_ROOT is found : D:<span >\</span>templates<span >-></span>Configuration for AndroID platform only,you can also <span >skip</span> <span >and</span> manually edit your environment variables<span >variable</span> NDK_ROOT <span >variable</span> NDK_ROOT<span >...</span> <span >-></span>NDK_ROOT is found : D:<span >\</span>Programs<span >\</span>androID<span >-ndk</span><span >-r9d</span><span >\</span><span >variable</span> ANDROID_SDK_ROOT <span >variable</span> ANDROID_SDK_ROOT<span >...</span> <span >-></span>ANDROID_SDK_ROOT is found : D:<span >\</span>adt<span >-bundle</span><span >-windows</span><span >-x86_64</span><span >-</span><span >20131030</span><span >\</span>sdk<span >variable</span> ANT_ROOT <span >variable</span> ANT_ROOT<span >...</span> <span >-></span>ANT_ROOT is found : D:<span >\</span>programs<span >\</span>apache<span >-ant</span><span >1.9</span><span >.4</span><span >\</span>bin<span >\</span></code><ul ><li >1</li><li >2</li><li >3</li><li >4</li><li >5</li><li >6</li><li >7</li><li >8</li><li >9</li><li >10</li><li >11</li><li >12</li><li >13</li><li >14</li><li >15</li><li >16</li><li >17</li><li >18</li><li >19</li><li >20</li><li >21</li><li >22</li><li >23</li><li >24</li><li >25</li><li >26</li></ul><ul ><li >1</li><li >2</li><li >3</li><li >4</li><li >5</li><li >6</li><li >7</li><li >8</li><li >9</li><li >10</li><li >11</li><li >12</li><li >13</li><li >14</li><li >15</li><li >16</li><li >17</li><li >18</li><li >19</li><li >20</li><li >21</li><li >22</li><li >23</li><li >24</li><li >25</li><li >26</li></ul>
其中几个常用SDK和NDK的下载和安装不再细说。在配置好之后,能看到像我上面这样的输出就ok了,相对于2.x中要做的工作,这样的引导是安装已经很简单了。
在命令行执行打包命令配置好环境之后,打包就非常简单了。对于cocos自带的cpp-tests项目,打包apk有两种 *** 作方法:
方法1
在引擎根目录/build/目录下,执行@H_502_5@python androID_build.py cpp-tests即可。建议在cmd窗口中 *** 作,可以看到真个过程,包括异常退出等情况。关于@H_502_5@androID_build.py的更多用法请参考其文件内容,里面有usage说明。
方法2
在引擎根目录/tests/cpp-tests/目录,执行cocos命令:
其实,两种方法都是使用了@H_502_5@cocos compile这个命令行工具。关于其完整的用法请在cmd中输入@H_502_5@cocos compile -h即可查看帮助信息。第一种方式中的脚本@H_502_5@androID_build.py其实是使用@H_502_5@-s参数来调用@H_502_5@cocos compile命令,-s选项指定了工程的目录地址。即可。自己打开瞧瞧它的内容就知道了。很简单。
自己创建的项目打包apk使用@H_502_5@cocos new命令创建的工程如何打包成apk?
也很简单,跟cpp-tests是一样的过程,也是使用@H_502_5@cocos compile命令。在执行命令之前,比cpp-tests多的一步 *** 作是,添加自己写的C++源代码文件名称和包含路径到AndroID.mk.
假设项目名字叫”Dog”
第一步,添加文件包含路径和cpp文件名到Dog/proj.androID/jni/AndroID.mk
例如下面的AndroID.mk文件是我的游戏目录下/proj.androID/jni/AndroID.mk文件,其中那一堆cpp就是自己写的cpp源代码,要参与到二进制编译的cpp都要加进来。
<code >LOCAL_PATH := <span >$(call my-dir)include $</span>(CLEAR_VARS)<span >$(call import-add-path,$</span>(LOCAL_PATH)/../../cocos2d)<span hlJs-formula" hlJs-special" >#</span> 从hellocpp/main.cpp这行往下,是自己添加的cpp文件LOCAL_SRC_fileS := hellocpp/main.cpp <span >\</span> ../../Classes<span >\AppDelegate</span>.cpp <span >\CCDirector</span>.cpp <span >\customs</span><span >\FlowLayout</span>.cpp <span >\Menu</span>.cpp <span >\data</span>_models<span >\TestDataCenter</span>.cpp <span >\LogicDirector</span>.cpp <span >\message</span><span >\Message</span>.cpp <span >\MessageCenter</span>.cpp <span >\PageManager</span>.cpp <span >\pages</span><span >\CameraTest</span>.cpp <span >\CCBPage</span>.cpp <span >\CCBTestPage</span>.cpp <span >\littletouchPage</span>.cpp <span >\MainPage</span>.cpp <span >\NodeTestPage</span>.cpp <span >\RootPage</span>.cpp <span >\ScrollvIEwTestPage</span>.cpp <span >\SuperPage</span>.cpp <span >\TestEntranceLayer</span>.cpp <span >\touchTestPage</span>.cpp <span >\util</span><span >\CocosWindow</span>.cpp <span >\cocos</span>_util.cpp <span >\DrawNode</span>3D.cpp <span >\StringUtil</span>.cpp <span >\ShaderTest</span>.cpp <span >#</span> 文件的包含路径LOCAL_C_INCLUDES := <span >$(LOCAL_PATH)/../../Classes<span >#</span> _COCOS_header_ANDROID_BEGIN<span >#</span> _COCOS_header_ANDROID_ENDLOCAL_STATIC_liBRARIES := cocos2dx_static<span >#</span> _COCOS_liB_ANDROID_BEGIN<span >#</span> _COCOS_liB_ANDROID_ENDinclude $</span>(BUILD_SHARED_liBRARY)<span >$(call import-module,.)<span >#</span> _COCOS_liB_import_ANDROID_BEGIN<span >#</span> _COCOS_liB_import_ANDROID_END</span></code><ul ><li >1</li><li >2</li><li >3</li><li >4</li><li >5</li><li >6</li><li >7</li><li >8</li><li >9</li><li >10</li><li >11</li><li >12</li><li >13</li><li >14</li><li >15</li><li >16</li><li >17</li><li >18</li><li >19</li><li >20</li><li >21</li><li >22</li><li >23</li><li >24</li><li >25</li><li >26</li><li >27</li><li >28</li><li >29</li><li >30</li><li >31</li><li >32</li><li >33</li><li >34</li><li >35</li><li >36</li><li >37</li><li >38</li><li >39</li><li >40</li><li >41</li><li >42</li><li >43</li><li >44</li><li >45</li><li >46</li><li >47</li><li >48</li><li >49</li><li >50</li><li >51</li><li >52</li><li >53</li><li >54</li><li >55</li><li >56</li><li >57</li><li >58</li><li >59</li></ul><ul ><li >1</li><li >2</li><li >3</li><li >4</li><li >5</li><li >6</li><li >7</li><li >8</li><li >9</li><li >10</li><li >11</li><li >12</li><li >13</li><li >14</li><li >15</li><li >16</li><li >17</li><li >18</li><li >19</li><li >20</li><li >21</li><li >22</li><li >23</li><li >24</li><li >25</li><li >26</li><li >27</li><li >28</li><li >29</li><li >30</li><li >31</li><li >32</li><li >33</li><li >34</li><li >35</li><li >36</li><li >37</li><li >38</li><li >39</li><li >40</li><li >41</li><li >42</li><li >43</li><li >44</li><li >45</li><li >46</li><li >47</li><li >48</li><li >49</li><li >50</li><li >51</li><li >52</li><li >53</li><li >54</li><li >55</li><li >56</li><li >57</li><li >58</li><li >59</li></ul>2. 在Dog/proj.androID/目录下执行:cocos compile -p androID
通过这两部就完成了自己创建项目的打包apk *** 作,可以注意到,比较复杂的就是第一步,在把自己的cpp文件加到AndroID.mk的时候,尤其是当你的cpp放的到处都是,像我的那样分散在多个子目录中。为了这一步的自动化,可以自己写个脚本。我这里分享一个很简单的小脚本,它可以遍历子目录,记录下所有的cpp文件。其实就是一个简单的类似unix命令tree的小脚本。
tree.py: 递归遍历子目录,统计所有.cpp文件,并写入完整路径到cpps.txt
<code ><span ># Coding=utf-8</span><span >import</span> os<span ><span >def</span> <span >get_dir_tree</span><span >(begin_dir,coll)</span>:</span> files = os.Listdir(begin_dir) <span >for</span> file_name <span >in</span> files: full_path = os.path.join(begin_dir,file_name) <span >if</span> os.path.isdir(full_path): get_dir_tree(full_path,coll) <span >else</span>: coll.append(full_path)<span >if</span> <span >"__main__"</span> == __name__: file_tree = [] get_dir_tree(os.getcwd(),file_tree) <span ># write .cpp file names into file</span> <span >with</span> open(<span >"cpps.txt"</span>,<span >"w"</span>) <span >as</span> f: <span >for</span> name <span >in</span> file_tree: <span >if</span> str(name).endswith(<span >".cpp"</span>): f.write(name + <span >" \\n"</span>)</code><ul ><li >1</li><li >2</li><li >3</li><li >4</li><li >5</li><li >6</li><li >7</li><li >8</li><li >9</li><li >10</li><li >11</li><li >12</li><li >13</li><li >14</li><li >15</li><li >16</li><li >17</li><li >18</li><li >19</li><li >20</li><li >21</li><li >22</li><li >23</li><li >24</li></ul><ul ><li >1</li><li >2</li><li >3</li><li >4</li><li >5</li><li >6</li><li >7</li><li >8</li><li >9</li><li >10</li><li >11</li><li >12</li><li >13</li><li >14</li><li >15</li><li >16</li><li >17</li><li >18</li><li >19</li><li >20</li><li >21</li><li >22</li><li >23</li><li >24</li></ul>把这个tree.py脚本丢到: 项目根目录/Classes/目录下,执行即可生成一个cpps.txt,里面记录了所有的cpp文件路径,然后按列选择@H_502_5@/Classes/..../xxxx.cpp \,复制粘贴到AndroID.mk即可。
cpps.txt
C++11中的强类型枚举(scoped enum)作为hash表键值导致的编译错误我的cocos代码中使用了一个强类型枚举作为键值的@H_502_5@unordered_map,如下:
<code ><span >enum</span> <span >class</span> MessageType{ kMessageTypeChangePage = <span >0</span>,kMessageTypePushPage,kMessageTypePopPage,kMessageTypeChangeBackground,};<span >class</span> MessageCenter : <span >public</span> Singleton<MessageCenter> { <span >// ......</span><span >private</span>: <span >typedef</span> <span >std</span>::<span ><span >vector</span><Message*></span> MessageQueue; MessageQueue messages_; <span >set</span><PriorityHandler*></span> HandlerQueue; <span >unordered_map</span><MessageType,HandlerQueue></span> HandlerMap; HandlerMap handlerMap_;};</code><ul ><li >1</li><li >2</li><li >3</li><li >4</li><li >5</li><li >6</li><li >7</li><li >8</li><li >9</li><li >10</li><li >11</li><li >12</li><li >13</li><li >14</li><li >15</li><li >16</li><li >17</li><li >18</li><li >19</li><li >20</li></ul><ul ><li >1</li><li >2</li><li >3</li><li >4</li><li >5</li><li >6</li><li >7</li><li >8</li><li >9</li><li >10</li><li >11</li><li >12</li><li >13</li><li >14</li><li >15</li><li >16</li><li >17</li><li >18</li><li >19</li><li >20</li></ul>其中的HandlerMap类型就是以enum class MessageType来作为键值的hash表,在windows上我使用visual studio 2013编译项目,顺利通过。
编译apk时就出问题了。在使用@H_502_5@cocos compile -p androID命令,使用NDK对上面的代码进行编译的时候,会发现如下错误:
<code ><span >In</span> file included from <span >D</span><span >:/programs/androID-ndk-r9d/sources/cxx-stl/gnu-libstdc++/</span><span >4.8</span>/<span >include</span>/bits/hashtable.<span >h:</span><span >35</span><span >:</span><span hlJs-constant" >D</span><span >include</span>/<span >unordered_map:</span><span >47</span>,102); Box-sizing: border-Box;">:</span>\codes\<span >3.9</span>\<span >PlayingWithCocos3D</span>\proj.androID\../cocos2d/cocos/<span >3</span>d/../renderer/<span >CCTexture2D</span>.<span >32</span>,102); Box-sizing: border-Box;">3</span>d/../base/<span >CCProtocols</span>.<span >34</span>,102); Box-sizing: border-Box;">3</span>d/../<span >2</span>d/<span >CCNode</span>.<span >2</span>d/<span >CCScene</span>.<span >3</span>d/../base/<span >CCDirector</span>.<span >37</span>,102); Box-sizing: border-Box;">3</span>d/../base/<span >CCAsyncTaskPool</span>.<span >29</span>,102); Box-sizing: border-Box;">3</span>d/../cocos2d.<span >41</span>,from jni/../../<span >Classes</span>/util/cocos_util.<span >3</span>,from jni/../../<span >Classes</span>/cocos_include.<span >4</span>,from jni/../../<span >Classes</span>/message/<span >MessageCenter</span>.<span hlJs-constant" >Classes</span>\message\<span >MessageCenter</span>.<span >cpp:</span><span >1</span><span >:</span><span >D</span><span >include</span>/bits/hashtable_policy.<span >1082</span><span >53</span><span >:</span> <span >error:</span> invalID use of incomplete type <span >'struct std::hash<MessageType>'</span> using __ebo_h1 = _Hashtable_ebo_helper<<span >1</span>,_H1>; ^</code><ul ><li >1</li><li >2</li><li >3</li><li >4</li><li >5</li><li >6</li><li >7</li><li >8</li><li >9</li><li >10</li><li >11</li><li >12</li><li >13</li><li >14</li><li >15</li><li >16</li></ul><ul ><li >1</li><li >2</li><li >3</li><li >4</li><li >5</li><li >6</li><li >7</li><li >8</li><li >9</li><li >10</li><li >11</li><li >12</li><li >13</li><li >14</li><li >15</li><li >16</li></ul>编译器抱怨说 : struct std::hash是不完整类型。它为什么会这样认为?这是因为hash表的定义需要一个hash函数,对于内置的数据类型,C++标准要求标准库要提供预定义的hash函数,在@H_502_5@<functional>头文件里可以找到内置数据类型的hash函数定义:
而对于enum class类型C++标准并没有要求必须提供。windows上VC++编译器应该是提供了enum class的hash函数,因此编译能够通过。那么对于gcc编译器,要想解决这个问题就需要自己定义hash函数,针对我的enum class MessageType。
为了快点通过编译在androID上看到我的游戏测试结果,我定义了一个很简单的hash函数,直接把enum的值转为size_t。
有了这个hash函数,NDK编译通过了并且打包成功。
作者水平有限,对相关知识的理解和总结难免有错误,还望给予指正,非常感谢!
在这里也能看到这篇文章:github博客,CSDN博客,欢迎访问
总结以上是内存溢出为你收集整理的【cocos2d-x 3.x 学习与应用总结】4: 使用cocos compile编译apk全部内容,希望文章能够帮你解决【cocos2d-x 3.x 学习与应用总结】4: 使用cocos compile编译apk所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)