想自己写个cocos2dx的编译脚本(一)

cocos android工程的编译命令是 cocos compile -p android,这是编译并打包的命令,如果我想编译和打包分开呢,本身这条命令耗时太多,分开的话会快些,正好可以借此机会更加了解些apk的结构.。

我看别人在编译的时候用的编译命令是build_native.py,但我自己的cocos项目里没有这个脚本,本人的cocos2dx的版本是3.15.1,据说这个脚本被弃用了,但还是找来看看吧。

在cocos的安装目录里搜索build_native.py,还是在一个demo里面找到这个脚本,拷贝到自己的项目中,执行python build_native.py,各种错误啊。

原版build_native.py

#!/usr/bin/python
# build_native.py
# Build native codes


import sys
import os, os.path
import shutil
from optparse import OptionParser

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

def check_environment_variables_sdk():
    ''' Checking the environment ANDROID_SDK_ROOT, which will be used for building
    '''

    try:
        SDK_ROOT = os.environ['ANDROID_SDK_ROOT']
    except Exception:
        print "ANDROID_SDK_ROOT not defined. Please define ANDROID_SDK_ROOT in your environment"
        sys.exit(1)

    return SDK_ROOT

def check_environment_variables():
    ''' Checking the environment NDK_ROOT, which will be used for building
    '''

    try:
        NDK_ROOT = os.environ['NDK_ROOT']
    except Exception:
        print "NDK_ROOT not defined. Please define NDK_ROOT in your environment"
        sys.exit(1)

    return NDK_ROOT

def select_toolchain_version():
    '''Because ndk-r8e uses gcc4.6 as default. gcc4.6 doesn't support c++11. So we should select gcc4.7 when
    using ndk-r8e. But gcc4.7 is removed in ndk-r9, so we should determine whether gcc4.7 exist.
    Conclution:
    ndk-r8e  -> use gcc4.7
    ndk-r9   -> use gcc4.8
    '''

    ndk_root = check_environment_variables()
    if os.path.isdir(os.path.join(ndk_root,"toolchains/arm-linux-androideabi-4.8")):
        os.environ['NDK_TOOLCHAIN_VERSION'] = '4.8'
        print "The Selected NDK toolchain version was 4.8 !"
    elif os.path.isdir(os.path.join(ndk_root,"toolchains/arm-linux-androideabi-4.7")):
        os.environ['NDK_TOOLCHAIN_VERSION'] = '4.7'
        print "The Selected NDK toolchain version was 4.7 !"
    else:
        print "Couldn't find the gcc toolchain."
        exit(1)

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")

    num_of_cpu = get_num_of_cpu()
	
    if ndk_build_param == None:
        command = '%s -j%d -C %s NDK_DEBUG=%d' % (ndk_path, num_of_cpu, app_android_root, build_mode=='debug')
    else:
        command = '%s -j%d -C %s NDK_DEBUG=%d %s' % (ndk_path, num_of_cpu, app_android_root, build_mode=='debug', ' '.join(str(e) for e in ndk_build_param))
    if 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)

def copy_files(src, dst):

    for item in os.listdir(src):
        path = os.path.join(src, item)
        # Android can not package the file that ends with ".gz"
        if not item.startswith('.') and not item.endswith('.gz') and os.path.isfile(path):
            shutil.copy(path, dst)
        if os.path.isdir(path):
            new_dst = os.path.join(dst, item)
            os.mkdir(new_dst)
            copy_files(path, new_dst)

def copy_resources(app_android_root):

    # remove app_android_root/assets if it exists
    assets_dir = os.path.join(app_android_root, "assets")
    if os.path.isdir(assets_dir):
        shutil.rmtree(assets_dir)

    # copy resources
    os.mkdir(assets_dir)
    resources_dir = os.path.join(app_android_root, "../Resources")
    if os.path.isdir(resources_dir):
        copy_files(resources_dir, assets_dir)

def build(ndk_build_param,android_platform,build_mode):

    ndk_root = check_environment_variables()
    sdk_root = None
    select_toolchain_version()

    current_dir = os.path.dirname(os.path.realpath(__file__))
    cocos_root = os.path.join(current_dir, "../cocos2d")

    app_android_root = current_dir
    copy_resources(app_android_root)
    
    if android_platform is not None:
				sdk_root = check_environment_variables_sdk()
				if android_platform.isdigit():
						android_platform = 'android-'+android_platform
				else:
						print 'please use vaild android platform'
						exit(1)
		
    if build_mode is None:
    	  build_mode = 'debug'
    elif build_mode != 'release':
        build_mode = 'debug'
    
    do_build(cocos_root, ndk_root, app_android_root,ndk_build_param,sdk_root,android_platform,build_mode)

# -------------- main --------------
if __name__ == '__main__':

    parser = OptionParser()
    parser.add_option("-n", "--ndk", dest="ndk_build_param", help='parameter for ndk-build', action="append")
    parser.add_option("-p", "--platform", dest="android_platform", 
    help='parameter for android-update.Without the parameter,the script just build dynamic library for project. 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()
    
    build(opts.ndk_build_param,opts.android_platform,opts.build_mode)


首先是 Couldn't find the gcc toolchain.  在脚本中找到打印这个错误的地方



我的NDK版本用的是r14b,里面确定没有4.7和4.8,但有4.9

修改脚本代码

def select_toolchain_version():
    '''Because ndk-r8e uses gcc4.6 as default. gcc4.6 doesn't support c++11. So we should select gcc4.7 when
    using ndk-r8e. But gcc4.7 is removed in ndk-r9, so we should determine whether gcc4.7 exist.
    Conclution:
    ndk-r8e  -> use gcc4.7
    ndk-r9   -> use gcc4.8
    '''

    ndk_root = check_environment_variables()
    print ndk_root
    if os.path.isdir(os.path.join(ndk_root,"toolchains/arm-linux-androideabi-4.8")):
        os.environ['NDK_TOOLCHAIN_VERSION'] = '4.8'
        print "The Selected NDK toolchain version was 4.8 !"
    elif os.path.isdir(os.path.join(ndk_root,"toolchains/arm-linux-androideabi-4.9")):
        os.environ['NDK_TOOLCHAIN_VERSION'] = '4.9'
        print "The Selected NDK toolchain version was 4.9 !"
    elif os.path.isdir(os.path.join(ndk_root,"toolchains/arm-linux-androideabi-4.7")):
        os.environ['NDK_TOOLCHAIN_VERSION'] = '4.7'
        print "The Selected NDK toolchain version was 4.7 !"
    else:
        print "Couldn't find the gcc toolchain."
        exit(1)

才晓得 python里的else if 要写成,elif,学习了。


再有,报出了NDK_MODULE_PATH环境变量未定义

在网上搜索了一下这个变量

http://blog.sina.com.cn/s/blog_4057ab62010197z8.html


http://blog.csdn.net/wanna_ku/article/details/18948893



结合这两篇文文章,我知道了该怎么修改脚本了,在do_build方法中定义一个ndk_module_path,在命令行的结尾加入这个变量:





接着又报出找不到NDK_MODULE_PATH中定义的目录


查看定义的cocos目录,很明显找不到这个目录嘛,修正:



这下编译时是没有报错啦,但是将apk放到模拟器上运行时,却说找不到main.lua文件,莫名奇妙了好久,结果是apk的asset目录被清空啦


正常的apk中是包含了assets的,里面是一些lua文件和资源, 在执行build_native.py的时候被删除了

def copy_resources(app_android_root):

    # remove app_android_root/assets if it exists
    assets_dir = os.path.join(app_android_root, "assets")
    if os.path.isdir(assets_dir):
        shutil.rmtree(assets_dir)

    # copy resources
    os.mkdir(assets_dir)
    #这里需要修改,如果编译的是cocos2dx-lua工程,则要把lua 源文件拷进来
    resources_dir = os.path.join(app_android_root, "../Resources")
    if os.path.isdir(resources_dir):
        copy_files(resources_dir, assets_dir)
    #拷贝lua与资源
    resources_dir = os.path.join(app_android_root, "../../../src")
    if os.path.isdir(resources_dir):
        tmpDir = os.path.join(assets_dir, 'src')
        os.mkdir(tmpDir)
        copy_files(resources_dir, tmpDir)
    shutil.copy(os.path.join(app_android_root, '../../../config.json'), assets_dir)
    resources_dir = os.path.join(assets_dir, '../../../../res')
    tmpDir = os.path.join(assets_dir, 'res')
    os.mkdir(tmpDir)
    copy_files(resources_dir, tmpDir)

OK了,Apk也能正常运行了, 编译部分完成,之后再做个打包的脚本。

修改完成后的脚本:

# coding=UTF-8
#!/usr/bin/python
# build_native.py
# Build native codes

import sys
import os, os.path
import shutil
from optparse import OptionParser

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

def check_environment_variables_sdk():
    ''' Checking the environment ANDROID_SDK_ROOT, which will be used for building
    '''

    try:
        SDK_ROOT = os.environ['ANDROID_SDK_ROOT']
    except Exception:
        print "ANDROID_SDK_ROOT not defined. Please define ANDROID_SDK_ROOT in your environment"
        sys.exit(1)

    return SDK_ROOT

def check_environment_variables():
    ''' Checking the environment NDK_ROOT, which will be used for building
    '''

    try:
        NDK_ROOT = os.environ['NDK_ROOT']
    except Exception:
        print "NDK_ROOT not defined. Please define NDK_ROOT in your environment"
        sys.exit(1)

    return NDK_ROOT

def select_toolchain_version():
    '''Because ndk-r8e uses gcc4.6 as default. gcc4.6 doesn't support c++11. So we should select gcc4.7 when
    using ndk-r8e. But gcc4.7 is removed in ndk-r9, so we should determine whether gcc4.7 exist.
    Conclution:
    ndk-r8e  -> use gcc4.7
    ndk-r9   -> use gcc4.8
    '''

    ndk_root = check_environment_variables()
    print ndk_root
    if os.path.isdir(os.path.join(ndk_root,"toolchains/arm-linux-androideabi-4.8")):
        os.environ['NDK_TOOLCHAIN_VERSION'] = '4.8'
        print "The Selected NDK toolchain version was 4.8 !"
    elif os.path.isdir(os.path.join(ndk_root,"toolchains/arm-linux-androideabi-4.9")):
        os.environ['NDK_TOOLCHAIN_VERSION'] = '4.9'
        print "The Selected NDK toolchain version was 4.9 !"
    elif os.path.isdir(os.path.join(ndk_root,"toolchains/arm-linux-androideabi-4.7")):
        os.environ['NDK_TOOLCHAIN_VERSION'] = '4.7'
        print "The Selected NDK toolchain version was 4.7 !"
    else:
        print "Couldn't find the gcc toolchain."
        exit(1)

def do_build(cocos_root, ndk_root, app_android_root,ndk_build_param,sdk_root,android_platform,build_mode):
    platform = sys.platform
    if platform == 'win32':  
        ndk_module_path = 'NDK_MODULE_PATH=%s;%s/external;%s/cocos;%s/cocos/scripting' % (cocos_root, cocos_root, cocos_root, cocos_root)
    else:  
        ndk_module_path = 'NDK_MODULE_PATH=%s:%s/external:%s/cocos' % (cocos_root, cocos_root, cocos_root)

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

    num_of_cpu = get_num_of_cpu()
	
    if ndk_build_param == None:
        command = '%s -j%d -C %s NDK_DEBUG=%d %s' % (ndk_path, num_of_cpu, app_android_root, build_mode=='debug', ndk_module_path)
    else:
        command = '%s -j%d -C %s NDK_DEBUG=%d %s' % (ndk_path, num_of_cpu, app_android_root, build_mode=='debug', ' '.join(str(e) for e in ndk_build_param))
    print 'command is : ', command
    if 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)

def copy_files(src, dst):

    for item in os.listdir(src):
        path = os.path.join(src, item)
        # Android can not package the file that ends with ".gz"
        if not item.startswith('.') and not item.endswith('.gz') and os.path.isfile(path):
            shutil.copy(path, dst)
        if os.path.isdir(path):
            new_dst = os.path.join(dst, item)
            os.mkdir(new_dst)
            copy_files(path, new_dst)

def copy_resources(app_android_root):

    # remove app_android_root/assets if it exists
    assets_dir = os.path.join(app_android_root, "assets")
    if os.path.isdir(assets_dir):
        shutil.rmtree(assets_dir)

    # copy resources
    os.mkdir(assets_dir)
    #这里需要修改,如果编译的是cocos2dx-lua工程,则要把lua 源文件拷进来
    resources_dir = os.path.join(app_android_root, "../Resources")
    if os.path.isdir(resources_dir):
        copy_files(resources_dir, assets_dir)
    #拷贝lua与资源
    resources_dir = os.path.join(app_android_root, "../../../src")
    if os.path.isdir(resources_dir):
        tmpDir = os.path.join(assets_dir, 'src')
        os.mkdir(tmpDir)
        copy_files(resources_dir, tmpDir)
    shutil.copy(os.path.join(app_android_root, '../../../config.json'), assets_dir)
    resources_dir = os.path.join(assets_dir, '../../../../res')
    tmpDir = os.path.join(assets_dir, 'res')
    os.mkdir(tmpDir)
    copy_files(resources_dir, tmpDir)
    

def build(ndk_build_param,android_platform,build_mode):

    ndk_root = check_environment_variables()
    sdk_root = None
    select_toolchain_version()

    current_dir = os.path.dirname(os.path.realpath(__file__))
    #这里也修改了一下,之前是 ../cocos2d,明显cocos2dx3.15没有这个目录
    cocos_root = os.path.join(current_dir, "../../cocos2d-x")

    app_android_root = current_dir
    copy_resources(app_android_root)
    
    if android_platform is not None:
				sdk_root = check_environment_variables_sdk()
				if android_platform.isdigit():
						android_platform = 'android-'+android_platform
				else:
						print 'please use vaild android platform'
						exit(1)
		
    if build_mode is None:
    	  build_mode = 'debug'
    elif build_mode != 'release':
        build_mode = 'debug'
    
    do_build(cocos_root, ndk_root, app_android_root,ndk_build_param,sdk_root,android_platform,build_mode)

# -------------- main --------------
if __name__ == '__main__':

    parser = OptionParser()
    parser.add_option("-n", "--ndk", dest="ndk_build_param", help='parameter for ndk-build', action="append")
    parser.add_option("-p", "--platform", dest="android_platform", 
    help='parameter for android-update.Without the parameter,the script just build dynamic library for project. 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()
    
    build(opts.ndk_build_param,opts.android_platform,opts.build_mode)



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值