您的位置:首页 > 移动开发 > Android开发

android工程的mk写法。

2014-12-08 21:18 155 查看
android因为用的gcc和g++编译,需要写makefile文件来编译armeabi或者armeabi-v7a的库。

首先感谢这篇文章:android mk终极写法

编译第三方库

我这里只加了剔除的功能。还有一些容易出错的地方。

我把库都放在一起,比如dish文件夹(我的命名空间)。这样我就可以只定义一个环境变量(DISH_HOME)就可以拿到所有我需要的库。

比如要编译lua库。

一般我会这样,源码放在src文件夹,编译放在build文件夹,编译好的sdk放在sdk文件夹。

dish/src/lua-5.2.3

/build/lua

/sdk/lua

然后随便拷贝一个空的android工程文件夹。这样放,proj.windows放其他的编译工程,这里是windows这里不讨论。

build/lua/proj.android

/proj.windows

然后修改.project文件里的 projectDescription/name 为比如这里的root_lua(eclipse不能导入相同工程名字的项目)。

jni文件夹里改Application.mk:

APP_ABI := armeabi-v7a armeabi
APP_STL := gnustl_static

APP_MODULES := lua_static


最后一句最好加上,默认的eclipse如果没有写这句不会帮你编译静态库(google版的会)。APP_ABI写上你可能需要的芯片型号。我一般都写armeabi-v7a armeabi这两个,现在主要用的是armeabi-v7a。

先上lua的Android.mk:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

include $(LOCAL_PATH)/lua_static.mk
然后在jni文件夹里再加上一个lua_static.mk:这样当lua_static.mk改变后并不会引发重新编译。而直接写进Android.mk就会造成重编译。

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := lua_static

LOCAL_MODULE_FILENAME := liblua_static

LOCAL_C_INCLUDES += $(DISH_HOME)/src/lua-5.2.3/src

LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES=1 -D__ANDROID__
LOCAL_CXXFLAGS += -fexceptions -frtti -std=c++11 -x c++ -D__ANDROID__
LOCAL_CPPFLAGS += -fexceptions

#
# config self source file path ,suffix.
MY_FILES_PATH := $(LOCAL_PATH)/../../../../src/lua-5.2.3/src

# config filter out file and path.
# MY_FILTER_OUT := ../../proj.android%
MY_FILTER_OUT += ../../../../src/lua-5.2.3/src/lua.c
MY_FILTER_OUT += ../../../../src/lua-5.2.3/src/luac.c

MY_FILES_SUFFIX := %.cpp %.c %.cc

# traverse all file function.
rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))

# get all source file.
MY_ALL_FILES := $(foreach src_path,$(MY_FILES_PATH), $(call rwildcard,$(src_path),*.*) )
MY_ALL_FILES := $(MY_ALL_FILES:$(MY_CPP_PATH)/./%=$(MY_CPP_PATH)%)
MY_SRC_LIST  := $(filter $(MY_FILES_SUFFIX),$(MY_ALL_FILES))
MY_SRC_LIST  := $(MY_SRC_LIST:$(LOCAL_PATH)/%=%)
MY_SRC_LIST  := $(filter-out $(MY_FILTER_OUT),$(MY_SRC_LIST))

# traverse all include path.
MY_ALL_DIRS := $(dir $(foreach src_path,$(MY_FILES_PATH), $(call rwildcard,$(src_path),*/) ) )
# remove duplicate
MY_ALL_DIRS := $(call sort,$(MY_ALL_DIRS))

# assign to NDK system.
LOCAL_SRC_FILES  += $(MY_SRC_LIST)
LOCAL_C_INCLUDES += $(MY_ALL_DIRS)

# $(info $(LOCAL_SRC_FILES))
# $(info $(LOCAL_C_INCLUDES))

include $(BUILD_STATIC_LIBRARY)


LOCAL_C_INCLUDES是头文件包含集。

LOCAL_***FLAGS是你需要的预定义。

MY_FILES_PATH是你的源码集,c,cpp什么的。

MY_FILTER_OUT是需要忽略的策略集,

忽略一个文件夹这样

MY_FILTER_OUT += ../../../../src/lua-5.2.3/ignore_dir%

单个文件就写全。

LOCAL_C_INCLUDES这句最好注释掉然后用LOCAL_C_INCLUDES拿全头文件集。

有时候源文件目录过多会有gcc或者g++参数溢出错误。

调试打开这个:

# $(info $(LOCAL_SRC_FILES))

# $(info $(LOCAL_C_INCLUDES))

build/lua/proj.android里加

build.bat:

@echo off

%ANDROID_NDK%\ndk-build.cmd all


然后跑build.bat就编好了。

dish/build/lua里加make_sdk.bat:

@echo off

xcopy proj.windows\\bin\*.dll ..\\..\\sdk\\lua\\bin\\Windows\ /s /h /d /y
xcopy proj.windows\\bin\*.exe ..\\..\\sdk\\lua\\bin\\Windows\ /s /h /d /y

xcopy proj.windows\\bin\*.pdb ..\\..\\sdk\\lua\\lib\\Windows\ /s /h /d /y
xcopy proj.windows\\bin\*.lib ..\\..\\sdk\\lua\\lib\\Windows\ /s /h /d /y

echo y | xcopy proj.android\obj\local\*.a			..\\..\\sdk\\lua\\lib\\Android\ /s /h /d /y

echo y | xcopy ..\\..\\src\\lua-5.2.3\\src\lauxlib.h ..\\..\\sdk\\lua\\include\\lua\ /s /h /d /y
echo y | xcopy ..\\..\\src\\lua-5.2.3\\src\lua.h ..\\..\\sdk\\lua\\include\\lua\ /s /h /d /y
echo y | xcopy ..\\..\\src\\lua-5.2.3\\src\lua.hpp ..\\..\\sdk\\lua\\include\\lua\ /s /h /d /y
echo y | xcopy ..\\..\\src\\lua-5.2.3\\src\luaconf.h ..\\..\\sdk\\lua\\include\\lua\ /s /h /d /y
echo y | xcopy ..\\..\\src\\lua-5.2.3\\src\lualib.h ..\\..\\sdk\\lua\\include\\lua\ /s /h /d /y

pause


然后跑make_sdk.bat就生成你的sdk了。

如何使用

LOCAL_LDLIBS	+= -L$(DISH_HOME)/sdk/lua/lib/Android/$(APP_ABI)
LOCAL_C_INCLUDES += $(DISH_HOME)/sdk/lua/include
LOCAL_LDLIBS	+= -llua_static


就链接成功了。

一些错误:

1、使用第三方库的时候明明加了库了为什么会报链接不到?

在链接静态库时,如果多个静态库之间存在依赖关系,则有依赖关系的静态库之间存在链接顺序问题。这在使用静态库时需要注意,否则会报符号找不到的链接错误。

例如zziplib用了zlib:

LOCAL_LDLIBS	+= -L$(DISH_HOME)/sdk/zlib/lib/Android/$(APP_ABI)
LOCAL_LDLIBS	+= -L$(DISH_HOME)/sdk/zziplib/lib/Android/$(APP_ABI)
LOCAL_LDLIBS	+= -lzziplib_static
LOCAL_LDLIBS	+= -lzlib_static


而不能写成

LOCAL_LDLIBS	+= -lzlib_static
LOCAL_LDLIBS	+= -lzziplib_static


lib2.a 依赖于 lib1.a,而最终可执行文件 test 依赖于 lib2.a,则链接选项应为:

-llib2.a -llib1.a,而不能反过来,否则会报 lib1.a 中的某些符号未定义。

2、每次修改Android.mk都会触发重编译,好痛苦。

尽量不动这个文件,而是把工程分很多小块然后这样链进来

include $(LOCAL_PATH)/client.mk

。。。

LOCAL_WHOLE_STATIC_LIBRARIES += client_static

LOCAL_WHOLE_STATIC_LIBRARIES += shared_static

client_static这里是一个编译模块。这样gcc,g++只会编译修改了的文件。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: