CMAKE 在Linux下 构建android 编译、打包、发布环境

Stella981
• 阅读 1212

环境:

    linux :2.6.32-279.el6.x86_64
    linux 版本 cmake: http://www.cmake.org/cmake/resources/software.html
    android:
            linux版本 sdk:http://developer.android.com/sdk/index.html 
            linux 版本 ndk:http://developer.android.com/tools/sdk/ndk/index.html

    项目代码:project 目录,是C++ 、C语言代码
    以上版本注意linux系统是32还是64位版本的不同。
 我的思路是:用cmake编译project代码为一个.so库,然后java代码调用.so库,最终打包为apk
方法:
       1、 将上面的sdk 、ndk以及project解压放在自己的工作目录。例如我是这样的:

            [workspace]$ ls
            adt  project
            [workspace]$ ls adt
            eclipse  ndk  sdk

2、目录构建好之后,进入project工程的jni目录里面

        cd   /home/test/workspace/project/MobileClient/android/jni

这里面有andorid 编译用的各个目录。

        [ jni]$ ls
        AmkList.txt     build           game.h    gametest.h  jni.cpp      target
        Android.mk      CMakeLists.txt  Game          glTest.cpp  jvm  testCamera.cpp
        Application.mk  game.cpp    gametest.cpp  glTest.h    libcode.mk  source.mk       testCamera.h

jni目录上层目录里面的内容:

        [android]$ls
       AndroidManifest.xml  gen   res  asserts    libs     bin  obj      src     jni

       这些都是android编译环境的标准目录结构,我们的cmake就在jni目录里面构建的。
    3、利用ndk编译android的交叉工具链,命令make-standalone-toolchain.sh
        进入ndk的tools目录,里面都是一些脚本程序



        /home/test/workspace/adt/ndk/build/tools

执行命令

         [tools]$  ./make-standalone-toolchain.sh --platform=android-12 --ndk-dir=/home/test/workspace/adt/ndk/ --install-dir=/opt/android-12-toolchain/ --system=linux-x86_64



       --platform 平台
        --ndk-dir ndk的路径
        --install-dir是安装路径
        --system是操作系统,如果不写的话,脚本会自动提示你的。
    这样命令就安装到了/opt/目录下面了,我们的cmake还用到里面的lib 和头文件。
     安装完之后设置环境变量,不设置的话cmake就不会到里面寻找我们需要的库,而是去系统都文件里面找。
    命令: export PATH=$PATH:/opt/android-12-toolchain/sysroot/usr/lib/
     4、在jni目录编写CMakeLists.txt文件,我的cmake是要编译出来为so库,CMakeLists.txt的内容为:
            PROJECT(GAME)  工程名字

            SET(CMAKE_SYSTEM_NAME  Android) 
            SET(CMAKE_CXX_COMPILER "/opt/android-12-toolchain/arm-linux-androideabi/bin/g++")  交叉编译工具
            SET(CMAKE_C_COMPILER "/opt/android-12-toolchain/arm-linux-androideabi/bin/gcc")

显示系统信息

            MESSAGE(STATUS "System Info:" ${CMAKE_SYSTEM}) 
            MESSAGE(STATUS "System Processor:" ${CMAKE_SYSTEM_PROCESSOR})
            MESSAGE(STATUS "BUILD TYPE : " ${CMAKE_BUILD_TYPE})

设置代码里面的宏定义

ADD_DEFINITIONS(-DANDROID -DLINUX -DUNIX

-D_DISABLE_CXX_EXCEPTION

-DFT2_BUILD_LIBRARY -D__GL_ES_2_

-DAL_BUILD_LIBRARY -DAL_ALEXT_PROTOTYPES

-D_ARM_ASSEM_ -DNDK_DEBUG

-DKTX_OPENGL_ES2=1)

要求cmake的最低版本

CMAKE_MINIMUM_REQUIRED(VERSION 2.8)

设置编译之后的目标生成路径

SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/../target)

包含编译需要的头文件,

INCLUDE_DIRECTORIES(".")

INCLUDE_DIRECTORIES("./jvm")

INCLUDE_DIRECTORIES("../../../Src/Core/inc")

INCLUDE_DIRECTORIES("../../../Src/OGES2/inc")

INCLUDE_DIRECTORIES("../../../External/freetype/FreeType2/include")

INCLUDE_DIRECTORIES("../../../External/OGLES2")

INCLUDE_DIRECTORIES("../../../External/OGLES2/Include")

INCLUDE_DIRECTORIES("../../../External/OGLES2/Include/GLES2")

INCLUDE_DIRECTORIES("../../OpenAL4Android/include")

INCLUDE_DIRECTORIES("../../OpenAL4Android/OpenAL32/Include")

INCLUDE_DIRECTORIES("../../../External/luatinker/inc")

INCLUDE_DIRECTORIES("../../../MobileProtocol")

INCLUDE_DIRECTORIES("../../../MobileServer/Core/Networkware/msg")

INCLUDE_DIRECTORIES("./jvm")

#INCLUDE_DIRECTORIES("/usr/include/")

#INCLUDE_DIRECTORIES("/usr/include/sys")

FIND_LIBRARY(LIB_CSTD_DIR NAMES stdc++)

找的编译需要的库文件,设置到变量里面,下面连接的时候用

IF(LIB_CSTD_DIR)

MESSAGE(STATUS "LIB_CSTD_DIR: "${LIB_CSTD_DIR})

ENDIF(LIB_CSTD_DIR)

FIND_LIBRARY(LIB_C_DIR NAMES c)

IF(LIB_C_DIR)

MESSAGE(STATUS "LIB_C_DIR: "${LIB_C_DIR})

ENDIF(LIB_C_DIR)

FIND_LIBRARY(LIB_M_DIR NAMES m)

IF(LIB_M_DIR)

MESSAGE(STATUS "LIB_M_DIR: "${LIB_M_DIR})

ENDIF(LIB_M_DIR)

FIND_LIBRARY(LIB_DL_DIR NAMES dl)

IF(LIB_DL_DIR)

MESSAGE(STATUS "LIB_DL_DIR: "${LIB_DL_DIR})

ENDIF(LIB_DL_DIR)

FIND_LIBRARY(LIB_LOG_DIR NAMES log)

IF(LIB_LOG_DIR)

MESSAGE(STATUS "LIB_LOG_DIR: "${LIB_LOG_DIR})

ENDIF(LIB_LOG_DIR)

FIND_LIBRARY(LIB_GLESV2_DIR NAMES GLESv2)

IF(LIB_GLESV2_DIR)

MESSAGE(STATUS "LIB_GLESV2_DIR: "${LIB_GLESV2_DIR})

ENDIF(LIB_GLESV2_DIR)

FIND_FILE(CRTBEGIN_DIR NAMES crtbegin_dynamic.o)

IF(CRTBEGIN_DIR)

MESSAGE(STATUS "CRTBEGIN_DIR:" ${CRTBEGIN_DIR})

ENDIF(CRTBEGIN_DIR)

FIND_FILE(CRTEND_ANDROID_DIR NAMES crtend_android.o)

IF(CRTEND_ANDROID_DIR)

MESSAGE(STATUS "CRTEND_ANDROID_DIR:" ${CRTEND_ANDROID_DIR})

ENDIF(CRTEND_ANDROID_DIR)

编译需要的c、c++文件

也可以直接包含目录“AUX_SOURCE_DIRECTORY("../../../Src/Core/src/" CORE_SRCS)”

SET(PUGIXML_SRCS "../../../External/pugixml/src/pugixml.cpp")

SET(LPNG167_SRCS "../../../External/lpng167/png.c"

"../../../External/lpng167/pngerror.c"

"../../../External/lpng167/pngwutil.c"

)

SET(KTX20_SRCS "../../../External/ktx20/include/errstr.c"

"../../../External/ktx20/include/etcdec.cxx"

"../../../External/ktx20/include/writer.c"

)

SET(OGES2_MOJOSHADER_SRCS "../../../Src/OGES2/mojoshader/mojoshader.cpp"

"../../../Src/OGES2/mojoshader/mojoshader_assembler.cpp"

"../../../Src/OGES2/mojoshader/mojoshader_preprocessor.cpp"

)

SET(OGES2_SRCS      "../../../Src/OGES2/src/zOGLESFrameBuffer.cpp"

"../../../Src/OGES2/src/zOGLESMeshBufferResource.cpp"

"../../../Src/OGES2/src/zOGLESTexture.cpp"

"../../../Src/OGES2/src/zOGLShader.cpp"

"../../../Src/OGES2/src/zRenderDeviceOGLES.cpp"

)

SET(GAMEFRAMEWORK_SRCS "../../gameFrameWork/clientConfigFile.cpp"

"../../gameFrameWork/clientEventDevice.cpp"

"../../gameFrameWork/game.cpp"

"../../gameFrameWork/zHeightLayer.cpp"

"../../gameFrameWork/zTrigger.cpp"

)

SET(GAMEFRAMEWORK_MSG_SRCS "../../gameFrameWork/Msg/clientNetFunction.cpp"

"../../gameFrameWork/Msg/convert.cpp"

"../../gameFrameWork/Msg/MsgLuaRegister.cpp"

"../../gameFrameWork/Msg/systemMsgProcess.cpp"

)

SET(GAMEFRAMEWORK_UI_SRCS "../../gameFrameWork/ui/maoXue.cpp"

"../../gameFrameWork/ui/maoXueManager.cpp"

"../../gameFrameWork/ui/ui_window.cpp"

)

SET(GAMEFRAMEWORK_CG_SRCS "../../gameFrameWork/cg/zAnimPath.cpp"

"../../gameFrameWork/cg/zCgAnimation.cpp"

"../../gameFrameWork/cg/zCgLogicSequence.cpp"

)

SET(NETWORK_SRCS "../../network/MD5.cpp"

"../../network/networkAdapter.cpp"

"../../network/networkconnector.cpp"

"../../network/networkwarelzo.cpp"

"../../network/networkwaremessage.cpp"

)

生成目标库

ADD_LIBRARY(game SHARED ${FREETYPE2_BASE_SRCS}

jvm/JniHelper.cpp

jvm/GameHelper.cpp

jni.cpp

cos_game.cpp

glTest.cpp

testCamera.cpp

gametest.cpp

Game/cosApplication.cpp

Game/cos_main.cpp

${NETWORK_SRCS}

${PUGIXML_SRCS}

${ZLIB_SRCS}

${GAMEFRAMEWORK_UI_SRCS}

${GAMEFRAMEWORK_MSG_SRCS})

#)

需要连接的库

TARGET_LINK_LIBRARIES(cos_game ${LIB_CSTD_DIR}

${LIB_C_DIR}

${LIB_M_DIR}

${LIB_DL_DIR}

${LIB_GLESV2_DIR}

${LIB_LOG_DIR})

依赖的crtbegin_dynamic.o 和 crtend_android.o  android编译需要这两个文件。

add_dependencies(cos_game ${CRTBEGIN_DIR} ${CRTEND_ANDROID_DIR})

        5、编译cmake,外部编译

            在jni目录下面建立build目录 mkdir build,进入build目录,执行下面的命令:

             cmake .. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug

            生成libgame.so库,然后copy到android目录的libs目录下面,一定要copy到libs目录的armeabi目录下面
         6、回到android目录下面,生成apk文件,生成apk文件需要好几步我写了一个sh脚本,一起执行,脚本如下:

#!/bin/bash
export PATH=$PATH:../../../adt/sdk/build-tools/19.0.3/
export PATH=$PATH:../../../adt/sdk/tools/
export PATH=$PATH:./jdk1.6.0_45/bin/  这个jdk需要下载,安装,
aapt package -f -m -J gen -S res -I ../../../adt/sdk/platforms/android-19/android.jar -M AndroidManifest.xml
javac -target 1.5 -bootclasspath ../../../adt/sdk/platforms/android-19/android.jar -d bin src/com/cos/game/*.java gen/com/cos/game/R.java
dx --dex --output=bin/classes.dex bin
aapt  package -f -M AndroidManifest.xml -S res -A asserts -I ../../../adt/sdk/platforms/android-19/android.jar  -F bin/byreadreader  #如果apk要包含图片、声音,就放到asserts目录下面  
apkbuilder byreadreader.apk -v -u -z bin/byreadreader -f bin/classes.dex -rf src -rj libs -nf libs #libs目录就是我们生成的库
keytool -genkey -alias demo.keystore -keyalg RSA -validity 40000 -keystore demo.keystore
jarsigner -verbose -keystore demo.keystore -signedjar test.apk byreadreader.apk demo.keystore

主意:这些命令啥意思网上都有,可以查看一下。上面脚本里面用到的目录,都要和我写的一摸一样,否则可能出错,单是没有提示。
点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Easter79 Easter79
2年前
swap空间的增减方法
(1)增大swap空间去激活swap交换区:swapoff v /dev/vg00/lvswap扩展交换lv:lvextend L 10G /dev/vg00/lvswap重新生成swap交换区:mkswap /dev/vg00/lvswap激活新生成的交换区:swapon v /dev/vg00/lvswap
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
2年前
Java获得今日零时零分零秒的时间(Date型)
publicDatezeroTime()throwsParseException{    DatetimenewDate();    SimpleDateFormatsimpnewSimpleDateFormat("yyyyMMdd00:00:00");    SimpleDateFormatsimp2newS
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这