【cocos2d-x 3.x 学习与应用总结】4: 使用cocos compile编译apk

【cocos2d-x 3.x 学习与应用总结】4: 使用cocos compile编译apk,第1张

概述前言 本文总结了在windows上使用cocos compile命令编译cocos2d-x安卓apk的基本用法,以及记录一个使用NDK-r9d(gcc 4.8)编译C++11的hash_map遇到的一个问题: error: invalid use of incomplete type 'struct std::hash<MessageType>'。 cocos compile 基本用法, 编译de 前言

本文总结了在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>'。

cocos compile 基本用法,编译deBUG版本的cpp-tests.

从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所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1082162.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-27
下一篇 2022-05-27

发表评论

登录后才能评论

评论列表(0条)

保存