一步一步写一个简单通用的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 -ldl
objs/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 exit status
make: *** [bin/hellomake] Error
进入到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 -lm
objs/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 exit status
make: *** [bin/hellomake] Error
不好意思,这个是因为
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即可。
如有写的不符合指出,还望大家指出,共同进步
一步一步写一个简单通用的makefile(四)--写一个通用的makefile编译android可执行文件的更多相关文章
- win7中的Uac与开机自动启动(好几种办法,特别是用不带UAC的程序启动UAC程序是一个简单的好办法,写驱动自启动更是了不得)
在另一篇文章中已经介绍了给Exe加上Uac的方法,在使用的过程中我们会发现,如果把带Uac的Exe写入注册表的Run中,是无法实现开机自动启动的,原因就是带Uac的exe需要申请管理员权限,以便运行执 ...
- 从一个简单的组件化封装写优化DOM操作
/* *缺点 * 1. 还需要我们自己手工维护dom状态,以数据的思想去思考 *2. 数据改变后,还需要我们自己手动改变dom *3. * */ class LikeButton{ construct ...
- TCP/TP编程 - 一个简单的Linux下C写的socket服务器客户端程序
服务端: hello_server.c #include <stdio.h> #include <stdlib.h> #include <string.h> #in ...
- Python学习笔记23:Django构建一个简单的博客网站(一个)
在说如何下载和安装Django,本节将重点讨论如何使用Django站点. 一 新建project 命令:django-admin startproject mysite # 有的须要输入:django ...
- SpringMVC4+thymeleaf3的一个简单实例(篇四:form表单数据验证)
关于表单数据验证有很多中方法,这里我仅介绍JSR303注解验证.JSR303仅仅是一个规范,这里我们要用到它的一个实现:hibernate-validator. 注意在spring的配置文件sprin ...
- (原创)如何使用boost.asio写一个简单的通信程序(一)
boost.asio相信很多人听说过,作为一个跨平台的通信库,它的性能是很出色的,然而它却谈不上好用,里面有很多地方稍不注意就会出错,要正确的用好asio还是需要花一番精力去学习和实践的,本文将通过介 ...
- (2)自己写一个简单的servle容器
自己写一个简单的servlet,能够跑一个简单的servlet,说明一下逻辑. 首先是写一个简单的servlet,这就关联到javax.servlet和javax.servlet.http这两个包的类 ...
- GNU Make 学习系列一:怎样写一个简单的Makefile
编程通常遵循一个相当简单的程序:编辑源文件,编译源代码成可执行的格式,调试结果.尽管将源代码翻译成可执行程序是常规的过程,如果做的不正确,程序员可能会浪费大量的时间去追踪问题.大多数的开发者都经历过这 ...
- 写一个简单的C词法分析器
写一个简单的C词法分析器 在写本文过程中,我参考了<词法分析器的实现>中的一些内容.这里我们主要讨论写一个C语言的词法分析器. 一.关键字 首先,C语言中关键字有: auto.break. ...
随机推荐
- thinkphp 缓存写入失败,网站报错
周末,正在家里休息,同事突然call 我,说网站打不开了,网站一直很正常的,突然成这样,肯定某个地方出问题了, 原来是网站所在的硬盘分区,没空间了,被mysql的日志占满了!!! 哎,好好的周末,在公 ...
- Instructions Set JAVA_HOME System-Wide
Instructions Set JAVA_HOME System-Wide 1 Start a root terminal session and then change directories t ...
- C语言-07其它相关
预处理指令 /* 不带参数的宏定义 1.所有的预处理指令都是以#开头 2.预处理指令分3种 1> 宏定义 2> 条件编译 3> 文件包含 3.预处理指令在代码翻译成0和1之前执行 4 ...
- 《C和指针》章节后编程练习解答参考——第10章
10.1 #include <stdio.h> typedef struct { unsigned ]; unsigned ]; unsigned ]; }TelphoneNumber; ...
- iBatis系列一
XML iBatis可以使用xml来作为参数输入以及结果返回:这个功能的优势在于某些特定的场景:还有可以通过DOM方式来作为参数传递:但是这个方式应用的比较少,如果服务器是xml服务器可以采用这种方式 ...
- xcode升级后, 插件失效修复
1. 首先查看 Xcode 的 UUID,在终端执行 defaults read /Applications/Xcode.app/Contents/Info DVTPlugInCompatibilit ...
- Python中类的运算符重载
这篇文章仅仅是总结性质的,待以后有时间的时候会针对比较难理解的部分补充一些例子. 构造和析构 __init__ __del__ 函数调用 __call__ 打印操作 __str__ __repr__ ...
- java项目打成jar包时引用了第三方jar,此时我们该如何解决呢
Web项目做多了,反而对单纯的java项目陌生了,今天我们在开发项目的过程中,碰到一个这样的需求:需要将java项目放到linux系统上跑起来,当然这个javaSE项目是带main方法的.我们知道在I ...
- HTML DOM select() 方法
定义和用法 select() 方法用于选择该元素中的文本. 语法 textareaObject.select() 实例 下面的例子可选择文本框中的文本: <html> <head&g ...
- Manacher 算法-----o(n)回文串算法
回文的含义是:正着看和倒着看相同,如abba和yyxyy Manacher算法基本要点:用一个非常巧妙的方式,将所有可能的奇数/偶数长度的回文子串都转换成了奇数长度:在每个字符的两边都插 ...