在cocos2d-x中使用luajit

今天嘗試了一下如何在cocos2d-x中使用luajit,發現cocos2d-x本身對luajit的支持還算不錯,但是有一些地方做的還是不夠完善,我的平臺是linux,我不知道是不是平臺的問題,也許mac上做的很完善,所以寫下這往篇文章希望對在linux平臺上開發cocos2d-x的同學有所幫助。

首先,爲什麼要用luajit呢?我能想到的原因有兩個,一是效率,二是加密。用luajit之後執行效率會有很大的提升,特別是在android下,另外呢luajit之後得到的文件是二進制的bytecode,基本無法反編譯,因此對於商業產品來說,提高了被反解的成本

那麼luajit與lua到底有什麼區別呢?從使用上來說沒有區別,因爲頭文件都是一致的,所以將lua換成luajit來說,有兩個步驟,一個是將頭文件換成luajit的,另外一個是將動態鏈接庫或者靜態鏈接庫也換成luajit的

開發平臺:Ubuntu 13.04 64位

cocos2d-x:2.2.1

首先我們來看一下如何讓cocos2d-x在linux平臺上支持luajit

事實上在linux平臺上cocos2d-x對於各模塊均採用了動態鏈接來進行鏈接,因此我們可以單獨處理luajit,而最後在Makefile裏引用luajit

事實上對於linux平臺來說cocos2d-x並沒有支持luajit,大家可以查看${COCOS_ROOT}/scripting/lua/proj.linux

TARGET = liblua.so

INCLUDES += -I.. -I../lua -I../tolua \
        -I../Classes -I../../../CocosDenshion/include -I../../../extensions -I../../../external/chipmunk/include/chipmunk

SOURCES = ../lua/lapi.o \
          ../lua/lauxlib.c \
          ../lua/lbaselib.c \
          ../lua/lcode.c \
          ../lua/ldblib.c \
          ../lua/ldebug.c \
          ../lua/ldo.c \
          ../lua/ldump.c \
          ../lua/lfunc.c \
          ../lua/lgc.c \
          ../lua/linit.c \
          ../lua/liolib.c \
          ../lua/llex.c \
          ../lua/lmathlib.c \
          ../lua/lmem.c \
          ../lua/loadlib.c \
          ../lua/lobject.c \
          ../lua/lopcodes.c \
          ../lua/loslib.c \
          ../lua/lparser.c \
          ../lua/lstate.c \
          ../lua/lstring.c \
          ../lua/lstrlib.c \
          ../lua/ltable.c \
          ../lua/ltablib.c \
          ../lua/ltm.c \
          ../lua/lundump.c \
          ../lua/lvm.c \
          ../lua/lzio.c \
          ../lua/print.c \
          ../tolua/tolua_event.c \
          ../tolua/tolua_is.c \
          ../tolua/tolua_map.c \
          ../tolua/tolua_push.c \
          ../tolua/tolua_to.c \
          ../cocos2dx_support/tolua_fix.c \
          ../cocos2dx_support/CCLuaBridge.cpp \
          ../cocos2dx_support/CCLuaEngine.cpp \
          ../cocos2dx_support/CCLuaStack.cpp \
          ../cocos2dx_support/CCLuaValue.cpp \
          ../cocos2dx_support/Cocos2dxLuaLoader.cpp \
          ../cocos2dx_support/LuaCocos2d.cpp \
          ../cocos2dx_support/CCBProxy.cpp \
          ../cocos2dx_support/Lua_extensions_CCB.cpp \
          ../cocos2dx_support/lua_cocos2dx_extensions_manual.cpp

include ../../../cocos2dx/proj.linux/cocos2dx.mk

TARGET := $(LIB_DIR)/$(TARGET)
SHAREDLIBS += -lextension

all: $(TARGET)

$(TARGET): $(OBJECTS) $(CORE_MAKEFILE_LIST)
	@mkdir -p $(@D)
	$(LOG_LINK)$(CXX) $(CXXFLAGS) $(OBJECTS) -shared -o $@ $(SHAREDLIBS) $(STATICLIBS)

$(OBJ_DIR)/%.o: ../%.cpp $(CORE_MAKEFILE_LIST)
	@mkdir -p $(@D)
	$(LOG_CXX)$(CXX) $(CXXFLAGS) $(INCLUDES) $(DEFINES) -c $< -o $@

$(OBJ_DIR)/%.o: ../%.c $(CORE_MAKEFILE_LIST)
	@mkdir -p $(@D)
	$(LOG_CC)$(CC) $(CCFLAGS) $(INCLUDES) $(DEFINES) -c $< -o $@

顯然對於linux來說,直接使用了lua而非luajit,既然我們要使用luajit,那麼有兩種選擇,一種是將這裏Makefile裏的lua全部換成luajit,另外一種是將這個Makefile裏的lua部分刪除,將一個so文件分成兩個。因爲對luajit不是很熟悉,所以我們採用第二種。新的Makefile文件如下

TARGET = liblua.so

INCLUDES += -I.. -I../luajit/include -I../tolua \
        -I../Classes -I../../../CocosDenshion/include -I../../../extensions -I../../../external/chipmunk/include/chipmunk

SOURCES = ../tolua/tolua_event.c \
          ../tolua/tolua_is.c \
          ../tolua/tolua_map.c \
          ../tolua/tolua_push.c \
          ../tolua/tolua_to.c \
          ../cocos2dx_support/tolua_fix.c \
          ../cocos2dx_support/CCLuaBridge.cpp \
          ../cocos2dx_support/CCLuaEngine.cpp \
          ../cocos2dx_support/CCLuaStack.cpp \
          ../cocos2dx_support/CCLuaValue.cpp \
          ../cocos2dx_support/Cocos2dxLuaLoader.cpp \
          ../cocos2dx_support/LuaCocos2d.cpp \
          ../cocos2dx_support/CCBProxy.cpp \
          ../cocos2dx_support/Lua_extensions_CCB.cpp \
          ../cocos2dx_support/lua_cocos2dx_extensions_manual.cpp

include ../../../cocos2dx/proj.linux/cocos2dx.mk

TARGET := $(LIB_DIR)/$(TARGET)
SHAREDLIBS += -lextension

all: $(TARGET)

$(TARGET): $(OBJECTS) $(CORE_MAKEFILE_LIST)
	@mkdir -p $(@D)
	$(LOG_LINK)$(CXX) $(CXXFLAGS) $(OBJECTS) -shared -o $@ $(SHAREDLIBS) $(STATICLIBS)

$(OBJ_DIR)/%.o: ../%.cpp $(CORE_MAKEFILE_LIST)
	@mkdir -p $(@D)
	$(LOG_CXX)$(CXX) $(CXXFLAGS) $(INCLUDES) $(DEFINES) -c $< -o $@

$(OBJ_DIR)/%.o: ../%.c $(CORE_MAKEFILE_LIST)
	@mkdir -p $(@D)
	$(LOG_CC)$(CC) $(CCFLAGS) $(INCLUDES) $(DEFINES) -c $< -o $@

但是這樣一來就沒有luajit了,怎麼辦呢?當然需要編譯一個libluajit.so出來了,這個其實很簡單,在${COCOS_ROOT}/scripting/lua/luajit/LuaJIT-2.0.1

然後make就會在src下產生一下libluajit.so出來,只需要將這個文件拷貝到${COCOS_ROOT}/lib/linux/release以及${COCOS_ROOT}/lib/linux/debug下即可

到這裏,其實已經將luajit準備好了,但是我們需要將工程裏的Makefile文件進行一點小的修改,以${COCOS_ROOT}/samples/Lua/HelloLua爲例

新的proj.linux/Makefile如下

EXECUTABLE = HelloLua

COCOS_ROOT = ../../../..
INCLUDES =  -I../ -I../Classes -I$(COCOS_ROOT)/CocosDenshion/include \
    -I$(COCOS_ROOT)/scripting/lua/luajit/include \
    -I$(COCOS_ROOT)/scripting/lua/tolua \
    -I$(COCOS_ROOT)/scripting/lua/cocos2dx_support \
    -I$(COCOS_ROOT)/extensions \

SOURCES = main.cpp ../Classes/AppDelegate.cpp 

SHAREDLIBS += -lcocos2d -lcocosdenshion -llua -lluajit -lextension
COCOS_LIBS = $(LIB_DIR)/libcocos2d.so $(LIB_DIR)/libcocosdenshion.so $(LIB_DIR)/liblua.so $(LIB_DIR)/libluajit.so

include $(COCOS_ROOT)/cocos2dx/proj.linux/cocos2dx.mk

$(TARGET): $(OBJECTS) $(STATICLIBS) $(COCOS_LIBS) $(CORE_MAKEFILE_LIST)
	@mkdir -p $(@D)
	$(LOG_LINK)$(CXX) $(CXXFLAGS) $(OBJECTS) -o $@ $(SHAREDLIBS) $(STATICLIBS) $(LIBS)

$(OBJ_DIR)/%.o: ../%.cpp $(CORE_MAKEFILE_LIST)
	@mkdir -p $(@D)
	$(LOG_CXX)$(CXX) $(CXXFLAGS) $(INCLUDES) $(DEFINES) $(VISIBILITY) -c $< -o $@

$(OBJ_DIR)/%.o: %.cpp $(CORE_MAKEFILE_LIST)
	@mkdir -p $(@D)
	$(LOG_CXX)$(CXX) $(CXXFLAGS) $(INCLUDES) $(DEFINES) $(VISIBILITY) -c $< -o $@

顯然我們加了一個-lluajit以及${LIB_DIR}/libluajit.so,至此就可以在linux下使用了。


接下來我們看一下如何讓cocos2d-x在android平臺上支持luajit

事實上android下對luajit的支持相對較好,有一個shell文件來完成大部分編譯的事情,${COCOS_ROOT}/scripting/lua/luajit/build_android.sh

但是這個文件有點小問題,一個是第5行SRCDIR=$DIR/LuaJIT-2.0.1原來是LuaJit,可能這個文件原來是在mac上寫的,所以不區分大小寫

另外一個是裏面的一些命令沒有使用arch,大家可以直接看最終版的文件如下

#!/bin/sh
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
host_os=`uname -s | tr "[:upper:]" "[:lower:]"`
arch_os=`uname -m | tr "[:upper:]" "[:lower:]"`

SRCDIR=$DIR/LuaJIT-2.0.1
cd "$SRCDIR"

NDK=$NDK_ROOT
NDKABI=8
NDKVER=$NDK/toolchains/arm-linux-androideabi-4.7
NDKP=$NDKVER/prebuilt/${host_os}-${arch_os}/bin/arm-linux-androideabi-
NDKF="--sysroot $NDK/platforms/android-$NDKABI/arch-arm"

# Android/ARM, armeabi (ARMv5TE soft-float), Android 2.2+ (Froyo)
DESTDIR=$DIR/android/armeabi
rm "$DESTDIR"/*.a
make clean
make HOST_CC="gcc -m32" CROSS=$NDKP TARGET_SYS=Linux TARGET_FLAGS="$NDKF"

if [ -f $SRCDIR/src/libluajit.a ]; then
    mv $SRCDIR/src/libluajit.a $DESTDIR/libluajit.a
fi;

# Android/ARM, armeabi-v7a (ARMv7 VFP), Android 4.0+ (ICS)
NDKARCH="-march=armv7-a -mfloat-abi=softfp -Wl,--fix-cortex-a8"
DESTDIR=$DIR/android/armeabi-v7a
rm "$DESTDIR"/*.a
make clean
make HOST_CC="gcc -m32" CROSS=$NDKP TARGET_SYS=Linux TARGET_FLAGS="$NDKF $NDKARCH"

if [ -f $SRCDIR/src/libluajit.a ]; then
    mv $SRCDIR/src/libluajit.a $DESTDIR/libluajit.a
fi;

# Android/x86, x86 (i686 SSE3), Android 4.0+ (ICS)
NDKABI=14
DESTDIR=$DIR/android/x86
NDKVER=$NDK/toolchains/x86-4.7
NDKP=$NDKVER/prebuilt/${host_os}-${arch_os}/bin/i686-linux-android-
NDKF="--sysroot $NDK/platforms/android-$NDKABI/arch-x86"
rm "$DESTDIR"/*.a
make clean
make HOST_CC="gcc -m32" CROSS=$NDKP TARGET_SYS=Linux TARGET_FLAGS="$NDKF"

if [ -f $SRCDIR/src/libluajit.a ]; then
    mv $SRCDIR/src/libluajit.a $DESTDIR/libluajit.a
fi;

make clean

修改完成之後,我們可以直接執行./build_android.sh來生成android下用的.a文件

注:這一步如果報錯,那就應該是你的編譯環境的問題,而非是cocos2d-x的問題,我遇到的一個問題就是少了mulitlib庫,所以如果大家在這一步報錯

不妨仔細看一眼錯誤在說什麼,然後按錯誤去google一把,來解決問題,因爲這裏的錯誤一般來說真不是cocos2d-x的問題

這一步完成之後,事實上android就直接換成luajit的了


因爲土鱉沒有mac機器,所以也不知道怎麼換,這裏就獻醜了。


發佈了217 篇原創文章 · 獲贊 8 · 訪問量 69萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章