一步一步写一个简单通用的makefile(四)--写一个通用的makefile编译android可执行文件
通常要把我们自己的的代码编译成在android里面编译的可执行文件,我们通常是建一个文件夹
.├── Android.mk├── Application.mk├── convolve.cl├── convolve_cl.cpp├── convolve_cl.cpp~├── inter_ocl│ └── opencl│ ├── CL│ │ ├── cl_ext.h│ │ ├── cl.h│ │ ├── cl_platform.h│ │ └── opencl.h│ ├── clew.c│ ├── clew.h│ ├── ocl_wrapper.c│ └── ocl_wrapper.h└── mylog.h
类似这样,里面有android.mk 文件,然后进入到这个文件夹执行ndk-build,生成文件如下:
[armeabi-v7a] Install : convolve-ocl => libs/armeabi-v7a/convolve-ocl[armeabi-v7a] Install : libstlport_shared.so => libs/armeabi-v7a/libstlport_shared.so
但是今天我们要修改上一章的模板makefile来编译可以在android中执行的可执行文件。
首先我们还是用之前的三个文件hellomake.c, hellofunc.c, hellofunc.h,文件树如下:
.├── makefile├── makefile1└── src ├── hellofunc.c ├── hellofunc.h └── hellomake.c
因为要用到android的交叉编译器,所以不能用gcc,另外寻找头文件的系统路径也不一样,寻找库的路径也和linux原本的不同,所以 -I 和 -L的路径也需要修改
修改之后的makefile如下:
#Hellomake
#Magnum, 2014-10-19
# 指令编译器和选项
TOOLCHAINS_ROOT=$(NDK_HOME)/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/
TOOLCHAINS_PREFIX=$(TOOLCHAINS_ROOT)/bin/arm-linux-androideabi
TOOLCHAINS_INCLUDE=$(TOOLCHAINS_ROOT)/lib/gcc/arm-linux-androideabi/4.8/include-fixed
PLATFORM_ROOT=$(NDK_HOME)/platforms/android-17/arch-arm
NDKINC=$(PLATFORM_ROOT)/usr/include
NDKLIB=$(PLATFORM_ROOT)/usr/lib
CC=$(TOOLCHAINS_PREFIX)-gcc
CFLAGS=-Wall
# 需要链接库的库名,比如libm.a,就是-lm,需要去掉前面的lib和后面的.a
LIBS=-lm
# 设置默认搜索头文件的路径,优先是这个,然后是系统路径
IncludeDir = -I./include/ -I$(NDKINC)
# 需要链接的库的路径
LinkDir = -L$(NDKINC)
OBJ_DIR = ./obj
BIN_DIR = ./bin
#PROJECT_TOP_DIR设置成pwd 或者"./"都行
PROJECT_TOP_DIR=.#$(shell pwd)#$(shell cd ../; pwd)
PROJECT_BIN_DIR=$(PROJECT_TOP_DIR)/bin
PROJECT_SRC_DIR=$(PROJECT_TOP_DIR)/src
PROJECT_LIB_DIR=$(PROJECT_TOP_DIR)/lib
PROJECT_OBJ_DIR=$(PROJECT_TOP_DIR)/objs
MKDIR := mkdir -p
# 目标文件
EXE_NAME=hellomake
TARGET=$(BIN_DIR)/$(EXE_NAME)
#源文件的文件类型
FILE_TYPE=c
src=$(wildcard $(PROJECT_SRC_DIR)/*.$(FILE_TYPE))
dir= $(notdir $(src))
PROJECT_OBJ= $(patsubst %.$(FILE_TYPE),%.o,$(dir) )
PROJECT_ALL_OBJS= $(addprefix $(PROJECT_OBJ_DIR)/, $(PROJECT_OBJ))
all: chdir $(TARGET)
$(TARGET): $(PROJECT_ALL_OBJS)
$(CC) $(CFLAGS) -o $@ $^ $(LinkDir) $(LIBS)
chdir:
@if test ! -d $(PROJECT_OBJ_DIR) ; \
then \
mkdir $(PROJECT_OBJ_DIR) ; \
fi
@if test ! -d $(PROJECT_BIN_DIR) ; \
then \
mkdir $(PROJECT_BIN_DIR) ; \
fi
.PHONY : clean
clean:
-rm -rf $(PROJECT_BIN_DIR) $(PROJECT_OBJ_DIR)
$(PROJECT_OBJ_DIR)/%.o:$(PROJECT_SRC_DIR)/%.$(FILE_TYPE)
$(CC) $(CFLAGS) -o $@ -c $< $(IncludeDir)
执行make, 报错:
/home/magnum/work-environment/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64//bin/arm-linux-androideabi-gcc -Wall -o objs/hellofunc.o -c src/hellofunc.c -I./include/ -I/home/magnum/work-environment/android-ndk-r9d/platforms/android-17/arch-arm/usr/include/home/magnum/work-environment/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64//bin/arm-linux-androideabi-gcc -Wall -o objs/hellomake.o -c src/hellomake.c -I./include/ -I/home/magnum/work-environment/android-ndk-r9d/platforms/android-17/arch-arm/usr/include/home/magnum/work-environment/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64//bin/arm-linux-androideabi-gcc -Wall -o bin/hellomake objs/hellofunc.o objs/hellomake.o -L/home/magnum/work-environment/android-ndk-r9d/platforms/android-17/arch-arm/usr/include -lm /home/magnum/work-environment/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld: error: cannot open crtbegin_dynamic.o: No such file or directory/home/magnum/work-environment/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld: error: cannot open crtend_android.o: No such file or directory/home/magnum/work-environment/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld: error: cannot find -lm/home/magnum/work-environment/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld: error: cannot find -lc/home/magnum/work-environment/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld: error: cannot find -ldlobjs/hellofunc.o:hellofunc.c:function myPrintHelloMake: error: undefined reference to 'puts'objs/hellomake.o:hellomake.c:function main: error: undefined reference to 'log'objs/hellomake.o:hellomake.c:function main: error: undefined reference to 'printf'collect2: error: ld returned 1 exit statusmake: *** [bin/hellomake] Error 1
进入到objs目录,发现.o文件生成成功,所以问题应该是出现在链接的时候。
crtbegin_dynamic.o: No such file or directory 和
crtend_android.o: No such file or directory 错误,
需要修改:
CFLAGS=-Wall -nostdlib . 然后执行make,错误只剩下:
/home/magnum/work-environment/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64//bin/arm-linux-androideabi-gcc -Wall -nostdlib -o bin/hellomake objs/hellofunc.o objs/hellomake.o -L/home/magnum/work-environment/android-ndk-r9d/platforms/android-17/arch-arm/usr/include -lm /home/magnum/work-environment/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld: error: cannot find -lmobjs/hellofunc.o:hellofunc.c:function myPrintHelloMake: error: undefined reference to 'puts'objs/hellomake.o:hellomake.c:function main: error: undefined reference to 'log'objs/hellomake.o:hellomake.c:function main: error: undefined reference to 'printf'collect2: error: ld returned 1 exit statusmake: *** [bin/hellomake] Error 1
不好意思,这个是因为
LinkDir = -L$(NDKINC), 这里复制后并没有修改,应该是LinkDir = -L$(NDKLIB),这个可以解决然后
undefined reference to 'log'
执行make,还是有一个错误:
/home/magnum/work-environment/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64//bin/arm-linux-androideabi-gcc -Wall -nostdlib -o objs/hellofunc.o -c src/hellofunc.c -I./include/ -I/home/magnum/work-environment/android-ndk-r9d/platforms/android-17/arch-arm/usr/include/home/magnum/work-environment/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64//bin/arm-linux-androideabi-gcc -Wall -nostdlib -o objs/hellomake.o -c src/hellomake.c -I./include/ -I/home/magnum/work-environment/android-ndk-r9d/platforms/android-17/arch-arm/usr/include/home/magnum/work-environment/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64//bin/arm-linux-androideabi-gcc -Wall -nostdlib -o bin/hellomake objs/hellofunc.o objs/hellomake.o -L/home/magnum/work-environment/android-ndk-r9d/platforms/android-17/arch-arm/usr/lib -lm -ldl objs/hellofunc.o:hellofunc.c:function myPrintHelloMake: error: undefined reference to 'puts'objs/hellomake.o:hellomake.c:function main: error: undefined reference to 'printf'
修改LIBS=-lm 更改为:LIBS=-lm -lc 再次执行make, 编译成功,
adb push ./bin/hellomake /data/local/tmp;
然后执行:
adb shell/data/local/tmp/hellomake, 奇怪没有任何输出,需要修改:
PROJECT_ALL_OBJS+=$(NDKLIB)/crtbegin_dynamic.o
PROJECT_ALL_OBJS+=$(NDKLIB)/crtend_android.o
然后从新编译,push,执行得到:
Hello makefiles!
Value:2.708050
好啦,完成
最后的makefile是:
#Hellomake
#Magnum, 2014-10-19
# 指令编译器和选项
TOOLCHAINS_ROOT=$(NDK_HOME)/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/
TOOLCHAINS_PREFIX=$(TOOLCHAINS_ROOT)/bin/arm-linux-androideabi
TOOLCHAINS_INCLUDE=$(TOOLCHAINS_ROOT)/lib/gcc/arm-linux-androideabi/4.8/include-fixed
PLATFORM_ROOT=$(NDK_HOME)/platforms/android-17/arch-arm
NDKINC=$(PLATFORM_ROOT)/usr/include
NDKLIB=$(PLATFORM_ROOT)/usr/lib
CC=$(TOOLCHAINS_PREFIX)-gcc
CFLAGS=-Wall -nostdlib #-Bdynamic
# 需要链接库的库名,比如libm.a,就是-lm,需要去掉前面的lib和后面的.a
LIBS=-lm -lc #-lgcc
# 设置默认搜索头文件的路径,优先是这个,然后是系统路径
IncludeDir = -I./include/ -I$(NDKINC)
# 需要链接的库的路径
LinkDir = -L$(NDKLIB)
OBJ_DIR = ./obj
BIN_DIR = ./bin
#PROJECT_TOP_DIR设置成pwd 或者"./"都行
PROJECT_TOP_DIR=.#$(shell pwd)#$(shell cd ../; pwd)
PROJECT_BIN_DIR=$(PROJECT_TOP_DIR)/bin
PROJECT_SRC_DIR=$(PROJECT_TOP_DIR)/src
PROJECT_LIB_DIR=$(PROJECT_TOP_DIR)/lib
PROJECT_OBJ_DIR=$(PROJECT_TOP_DIR)/objs
MKDIR := mkdir -p
# 目标文件
EXE_NAME=hellomake
TARGET=$(BIN_DIR)/$(EXE_NAME)
#源文件的文件类型
FILE_TYPE=c
src=$(wildcard $(PROJECT_SRC_DIR)/*.$(FILE_TYPE))
dir= $(notdir $(src))
PROJECT_OBJ= $(patsubst %.$(FILE_TYPE),%.o,$(dir) )
PROJECT_ALL_OBJS= $(addprefix $(PROJECT_OBJ_DIR)/, $(PROJECT_OBJ))
PROJECT_ALL_OBJS+=$(NDKLIB)/crtbegin_dynamic.o
PROJECT_ALL_OBJS+=$(NDKLIB)/crtend_android.o
all: chdir $(TARGET)
$(TARGET): $(PROJECT_ALL_OBJS)
$(CC) $(CFLAGS) -o $@ $^ $(LinkDir) $(LIBS)
chdir:
@if test ! -d $(PROJECT_OBJ_DIR) ; \
then \
mkdir $(PROJECT_OBJ_DIR) ; \
fi
@if test ! -d $(PROJECT_BIN_DIR) ; \
then \
mkdir $(PROJECT_BIN_DIR) ; \
fi
.PHONY : clean
clean:
-rm -rf $(PROJECT_BIN_DIR) $(PROJECT_OBJ_DIR)
$(PROJECT_OBJ_DIR)/%.o:$(PROJECT_SRC_DIR)/%.$(FILE_TYPE)
$(CC) $(CFLAGS) -o $@ -c $< $(IncludeDir)
后面要把一些代码编译成可执行文件在android设备上验证,用这个makefile即可。
如有写的不符合指出,还望大家指出,共同进步
更多相关文章
- 一款常用的 Squid 日志分析工具
- GitHub 标星 8K+!一款开源替代 ls 的工具你值得拥有!
- RHEL 6 下 DHCP+TFTP+FTP+PXE+Kickstart 实现无人值守安装
- Linux 环境下实战 Rsync 备份工具及配置 rsync+inotify 实时同步
- 如何编译Android内核
- 反编译Android(安卓)apk文件
- android—label窗口——基础编
- OPhone开发环境设置备忘录
- Android开发心得整理