写在前面:

前段时间下载了cocos2d-x 3.1,按照官网的教程,配置环境,编译打包,走了一遍,感觉不错,顺便发现其中用了很多python的脚本文件,比如今天要说的android-build.py.这个文件把编译,打包的功能全部整合到了一起.也就是传说中的一键打包.正好最近在看python,就顺手拿这个脚本学习一下.

小贴士:

在正式看这个脚本文件前,推荐先到cocos2d-x的官网按教程,配置环境,编译,打包,走一遍,先有个大概的了解.教程地址.http://www.cocos2d-x.org/wiki/Getting_Started_with_Cocos2d-x.

我是做coco2d-x游戏开发的,用的是windows环境.运行cocos2d-x 3.1需要安装和配置下面的软件.JDK,android-sdk,ant,python,android-ndk-r9d.系统就必须win7以上了.想进一步学习的话,也可以去看看python,我也是最近在看,大家可以相互学习进步.

正文:

android-build.py脚本文件在引擎目录下的build文件夹里.里面的代码还是有点多,这里就不全部粘贴出来了,可以在原文件上直接看源代码.

下面的一些内容会涉及到python的语法内容,如果对python比较熟悉的话可以直接跳到看重点关注.写了很多python相关的,主要是自己也在学python. :-)

import sys
import os, os.path
import shutil
from optparse import OptionParserCPP_SAMPLES = ['cpp-empty-test', 'cpp-tests']
LUA_SAMPLES = ['lua-empty-test', 'lua-tests']
ALL_SAMPLES = CPP_SAMPLES + LUA_SAMPLES

这是开始的东东,前面几行的import,就和java的import一样,导入一些需要的模块.

CPP_SAMPLES = ['cpp-empty-test', 'cpp-tests']

这个是python里的一种数据类型,叫做列表,和java,c++里的数组类似.里面也可以放整型,字符型啦这些数据.这里放的是字符串,python中的字符串可以用单引号,也可以用双引号括起.两个列表可以直接用 "+",合成一个新的列表.还有就是python里的数据类型都没有类型标识.所以你看python代码时变量前面一般不会看到,long,int这些啦.这三行存的是代码里要编译的demo的名字,后面要用到.

def get_num_of_cpu():''' The build process can be accelerated by running multiple concurrent job processes using the -j-option.'''try:platform = sys.platformif platform == 'win32':if 'NUMBER_OF_PROCESSORS' in os.environ:return int(os.environ['NUMBER_OF_PROCESSORS'])else:return 1else:from numpy.distutils import cpuinforeturn cpuinfo.cpu._getNCPUs()except Exception:print "Can't know cpuinfo, use default 1 cpu"return 1

这个是python里的方法,看方法名字知道是用来获取系统处理器数量的.其中sys就是最开始导入的一个模块,提供了一些方法处理系统方面的一些功能.在这里

 platform = sys.platform

获得当前的操作系统平台

os.environ['NUMBER_OF_PROCESSORS']

获得系统变量的值.在python中有种数据类型叫做字典,类似java,c++中的map,通过键找到对应的值.

def check_environment_variables():

检查是否设置了ndk的环境变量'NDK_ROOT',就是在环境变量里新建一个'NDK_ROOT',再把你ndk的根目录路径设置到其中.

def check_environment_variables_sdk():

检查android sdk的环境变量设置,如果没有,则需要把sdk的根目录路径设置到新建的环境变量'ANDROID_SDK_ROOT'中.

def select_toolchain_version():

选择需要的toolchain.代码注释说的很明白.因为cocos2d-x 3.1用的是c++11,所以toolchain的版本需要用gcc4.7以上的版本.

重点关注:

def do_build(cocos_root, ndk_root, app_android_root, ndk_build_param,sdk_root,android_platform,build_mode):ndk_path = os.path.join(ndk_root, "ndk-build")# windows should use ";" to seperate module pathsplatform = sys.platformif platform == 'win32':ndk_module_path = 'NDK_MODULE_PATH=%s;%s/external;%s/cocos' % (cocos_root, cocos_root, cocos_root)else:ndk_module_path = 'NDK_MODULE_PATH=%s:%s/external:%s/cocos' % (cocos_root, cocos_root, cocos_root)num_of_cpu = get_num_of_cpu()if ndk_build_param == None:command = '%s -j%d -C %s %s' % (ndk_path, num_of_cpu, app_android_root, ndk_module_path)else:command = '%s -j%d -C %s %s %s' % (ndk_path, num_of_cpu, app_android_root, ndk_build_param, ndk_module_path)print commandif os.system(command) != 0:raise Exception("Build dynamic library for project [ " + app_android_root + " ] fails!")elif android_platform is not None:sdk_tool_path = os.path.join(sdk_root, "tools/android")cocoslib_path = os.path.join(cocos_root, "cocos/platform/android/java")command = '%s update lib-project -t %s -p %s' % (sdk_tool_path,android_platform,cocoslib_path)if os.system(command) != 0:raise Exception("update cocos lib-project [ " + cocoslib_path + " ] fails!")command = '%s update project -t %s -p %s -s' % (sdk_tool_path,android_platform,app_android_root)if os.system(command) != 0:raise Exception("update project [ " + app_android_root + " ] fails!")buildfile_path = os.path.join(app_android_root, "build.xml")command = 'ant clean %s -f %s -Dsdk.dir=%s' % (build_mode,buildfile_path,sdk_root)os.system(command)

这个方法是这个脚本里最重要的一个.现在基本作个逐行解释吧.

ndk_path = os.path.join(ndk_root, "ndk-build")

os.path.join的功能是把,ndk_root和"ndk-build"链接到一起,ndk_root你ndk的根目录路径,上面已经做了设置."ndk-build"是ndk下的编译命令,用过ndk的会知道,这个命令是用来编译c/c++代码的.具体的可以参考你ndk目录中的docs文件夹,其中包括NDK-BUILD.xml这个文档就是来介绍ndk-build命令的.因为执行"ndk-build"命令,需要在ndk目录中执行.(也可以如上面的操作,设置到环境变量里,在执行此命令时就无需在根目录执行了).上面的输出,在我的机子上是"e:\\android-ndk-r9d\\ndk-build".

    num_of_cpu = get_num_of_cpu()if ndk_build_param == None:command = '%s -j%d -C %s %s' % (ndk_path, num_of_cpu, app_android_root, ndk_module_path)else:command = '%s -j%d -C %s %s %s' % (ndk_path, num_of_cpu, app_android_root, ndk_build_param, ndk_module_path)

获得编译命令。代码功能类似c++中的sprintf,将%后的参数依次置换为ndk_path等等,最后command获得置换后的值。

这个command就是要执行的编译命令,其中包括一些参数。目前做ndk编译的,一般都是在cygwin中执行,针对coco2d-x 2.x的编译用的是一个.sh文件。可以参考2.x版本的sh脚本。不过从ndkr8开始,其中已经内置了cygwin,所以使用ndk编译时就无需再在cygwin命令下执行编译命令了,可以直接在ndk中使用ndk-build命令。有个好处就是可以不需要安装cygwin了。 最后一个参数

ndk_module_path 用以指示查找android.mk中使用$(call import-module, XXX)函数引入外部库文件的路径。
ndk_build_param 这个参数没有搞懂是干嘛用的,脚本示例用的是-p,在ndk参考文档上没有找到。
if os.system(command) != 0:raise Exception("Build dynamic library for project [ " + app_android_root + " ] fails!")

os.system(XX)可以执行上面的编译命令,如果不成功会抛个异常。这个方法很好用,如果你把XX换成你电脑上的某个程序,如我电脑上os.system("F:\\Program Files\\Tencent\\Bin\\QQ.exe"),就可以打开QQ了。

command中的第一个参数是你ndk根目录加"ndk-build",-j后面跟的是处理器核心数(在ndk官方文档上没找到这个参数,不过加上这个参数后,编译速度确实有所提高:)),-C后面跟的是编译生成的.so放置的路径。

ndk_module_path 指示引入外部参考库的文件路径,在android.mk中会用到。
ndk_build_param 这个参数脚本示例用的是 -p,在ndk文档里没找到这个参数,不知道其作用。
sdk_tool_path = os.path.join(sdk_root, "tools/android") 获取sdk目录下android命令的执行路径,用来使用"android",执行update操作.
cocoslib_path = os.path.join(cocos_root, "cocos/platform/android/java") 获取引擎里的java库工程路径
command = '%s update lib-project -t %s -p %s' % (sdk_tool_path,android_platform,cocoslib_path)command = '%s update project -t %s -p %s -s' % (sdk_tool_path,android_platform,app_android_root)

上面两条命令,第一条是执行android update lib-project的命令来更新库工程。第二条是执行android update project的命令来更新应用程序工程。

更新过的android工程会生成build.xml和ant属性文件,这样就可以使用ant进行打包程序了。

因为cocos2d-x引擎是分为两个部分的(针对for android开发来说),一个是c++端的,一个是java端的。c++端是重头,引擎的大功能都是c++实现的。但是针对android来说,最基本的还是java,首先你程序的启动必须是从java这边的activity启动的,然后再调用c++端的openGL_ES进行渲染,其中一些获取硬件功能的方法,如获取重力感应,也是需要java这边android sdk提供的接口来操作的,所以cocos2d-x for android,java这边的代码是必须存在的。2.x版本前,引擎java这边的代码是放到一个包里的,你需要把这个包引入到你的android工程中就可以使用java这端的引擎,进而调用c++那端的代码了,两者交互用的是jni,不懂的童鞋可以上网学习,这里就不做介绍了。3.x版本后,将java这端的引擎代码做成了一个库工程,到时你的android工程直接引用这个库工程就可以了,相对2.x的代码集成,这样管理代码更加方便和安全。

buildfile_path = os.path.join(app_android_root, "build.xml")
command = 'ant clean %s -f %s -Dsdk.dir=%s' % (build_mode,buildfile_path,sdk_root)

这里就是最后的android打包命令了,执行完后会在bin下生成apk.简单介绍下,clean就是清空工程目录下的gen,bin这些东东,-f 强制覆盖 -Dsd.dir 设置android sdk的路径

如果对ant不熟悉也没关系,你只需要知道两点:1.在eclipse上的创建,打包android程序就是执行的ant命令,eclipse只是封装成可视化操作而已。2.要学会使用ant创建和打包android工程(这里不做演示了,如果要搞定build.xml,要讲的也不少,可以去百度 android ant,里面有很多介绍)。

其实说完了上面的重点关注后,脚本剩下的就和上面的一些检查方法类似了。

def copy_resources(target, app_android_root): 用来拷贝资源的,包括src下的代码,resource,asset下的资源文件。在ant打包时会把拷贝的资源打到apk里,基本上都是python文件操作的内容。还包括shutil高级文件操作模块。感兴趣的童鞋就去学习python吧。:)
def build_samples(target,ndk_build_param,android_platform,build_mode):当前脚本文件编译的samples。我们这个脚本就是运行这个方法来执行拷资源,编译,打包的。

可以从代码中看出,执行的顺序是先把各种环境变量检查,赋值,然后执行拷贝资源,最后编译打包。

脚本最后的代码是类似c++的main(),也就是说这个脚本最开始运行的地方是从这里开始的

# -------------- main --------------
if __name__ == '__main__':#parse the paramsusage = """This script is mainy used for building tests built-in with cocos2d-x.Usage: %prog [options] [cpp-empty-test|cpp-tests|lua-empty-test|lua-tests|cpp|lua|all]If you are new to cocos2d-x, I recommend you start with cpp-empty-test, lua-empty-test.You can combine these targets like this:python android-build.py -p 10 cpp-empty-test lua-empty-testNote: You should install ant to generate apk while building the andriod tests. But it is optional. You can generate apk with eclipse."""parser = OptionParser(usage=usage)parser.add_option("-n", "--ndk", dest="ndk_build_param",help='Parameter for ndk-build')parser.add_option("-p", "--platform", dest="android_platform",help='Parameter for android-update. Without the parameter,the script just build dynamic library for the projects. Valid android-platform are:[10|11|12|13|14|15|16|17|18|19]')parser.add_option("-b", "--build", dest="build_mode",help='The build mode for java project,debug[default] or release. Get more information,please refer to http://developer.android.com/tools/building/building-cmdline.html')(opts, args) = parser.parse_args()if len(args) == 0:parser.print_help()sys.exit(1)else:try:build_samples(args, opts.ndk_build_param,opts.android_platform,opts.build_mode)except Exception as e:print esys.exit(1)

注释写的很详细,说明了这个脚本的执行命令参数和其作用。

parser = OptionParser(usage=usage)

上面这个也是python相关的。可以参考点击打开链接这篇博客。

写在最后:

非常感谢您看完了这篇博客,看得很窝火,很想打扁博主? 想打就来吧! :)

这算是工作以来的第一篇技术博客,而且之前已经很久没有写文章了,写的过程也是断断续续的,写完后发现博客也挺难写的,对那些写了很多技术博客的人表示崇拜和感谢。

写之前觉得自己基本都懂了,但是写的过程中发现,其实还不是真懂,于是期间自己也想了很久,就像给人讲授东西一样,自己又重新学了一遍。其中会有说不好的,或者错误的,等着拍砖!!!也等着以后自己来给自己拍砖!!!!!!!

转载于:https://www.cnblogs.com/lovexb/p/4595125.html

cocos2d-x 3.1 编译脚本android-build.py相关推荐

  1. android lichee编译脚本解析

    #编译流程 #lichee 目录下 ./build.sh -p sun7i_android -k 3.4 1 2 3 #build.sh 解析#!/bin/bash set -e #"Exi ...

  2. 深入浅出filament Android编译脚本

    依赖环境 安装Android Studio 4.0+ OpenJDK 1.8 (单独安装,或者复用Android Studio内置,/Applications/Android Studio 4.0 P ...

  3. android.mk ndk编译选项优化,Android NDK 编译脚本分析 之一

    版权信息:本文为本人原创,欢迎转载,但请著明出处,并保留本版权信息. Android NDK编译脚本编写起来还是是比较简单条理的,然而它的语法和传统的linux GNU Make编译脚本的编写似乎有很 ...

  4. 【Android开发】之编译脚本Makefile编写

    摘抄自:https://blog.csdn.net/SoaringLee_fighting/article/details/84037468 略加部分修改完善. 1.NDK编译C/C++ Native ...

  5. Android NDK学习(二):编译脚本语法Android.mk和Application.mk

    一.Android.mk Android.mk分为一下几部分: LOCAL_PATH:= $(call my-dir), 返回当前文件在系统中的路径,Android.mk文件开始时必须定义该变量. i ...

  6. 深入分析Android (build/core/*.mk脚本)

    深入分析Android (build/core/*.mk脚本) 文档简要整理Android的make脚本的内容.以供备忘和参考. 1.    Build Layers Build Layers描述的是 ...

  7. 全志A64 lichee编译脚本build.sh分析

    lichee目录下的./build.sh脚本: set -e #用于指此脚本里执行的命令返回值非0时,终止当前脚本的执行.buildroot/scripts/mkcommon.sh $@ #接着执行m ...

  8. Android build编译过程

    Android build编译过程及Android.mk与Android.bp分析 Android的官方网站:http://source.android.com/source/building.htm ...

  9. Android编译脚本(.mk文件)解析

    摘要:本文将简单介绍Android编译系统并举例说明如何编写不同类型的mk文件以达到不同的目的.虽然.mk文件即将被.bp文件替代,但是在Android9之前的版本中.mk文件的使用频率依旧很高,同时 ...

  10. Android编译及编译脚本、Android构建基础学习笔记

    Android编译及编译脚本.Android构建基础学习笔记 Android编译及编译脚本 概述 Android.mk转换成Android.bp 例子(简单Android.mk文件转Android.b ...

最新文章

  1. 基于μC/OS—III的CC1120驱动程序设计
  2. vue-router路由基础
  3. 搜索github项目stars排名
  4. 算法导论学习笔记 6.5 优先队列
  5. Struts2(一)— 入门
  6. 【译】理解JavaScript闭包——新手指南
  7. [Java] 蓝桥杯ALGO-59 算法训练 快速排序
  8. mxonline实战14,全局搜索,修改个人中心页面个人资料信息
  9. webservice 调用错误
  10. 解剖SQLSERVER 第九篇 OrcaMDF现在能通过系统DMVs显示元数据(译)
  11. 华为鸿蒙操作系统国美通讯,国美通讯(600898)03月06日14:30大单揭秘
  12. 个人观点:苹果对iPad商标事件的解决办法
  13. 如何写论文摘要和引言
  14. [Asp.net Core]局部视图
  15. 趣味点名软件_网传川大教授用刷脸软件点名 无人逃课
  16. deepin C++ 编译错误 file not found 其实是原文件后缀的问题
  17. 【技术文档】centernet(姿态估计)
  18. 互斥锁(mutex)的使用
  19. julia的Unicode 字符输入
  20. 推荐系统论文拾遗之1——行列式点过程(DPP)多样性控制

热门文章

  1. springboot 文件上传 设置文件大小配置
  2. Linux下NTP时间同步客户端配置
  3. ASP.NET 运行机制详解
  4. beetl 国内下载量貌似快跟freemaker的差不多了
  5. RH413-Linux系统下的SUID文件权限测试
  6. 各种交换机端口安全总结(配置实例)
  7. 【硬件解码系列】之DXVA2
  8. Win-MASM64汇编语言-LOOP指令
  9. Maven-依赖调解/查看项目依赖了哪些包
  10. JavaScript-switch语句