win下实现简单的android(arm linux)交叉编译

起因

由于需要写些可执行native代码,但又懒得开AS,生成的可执行elf也不打包进apk。所以自己参看之前的gcc与make博客,简单写了下交叉编译工具。

后来发现直接建一个jni的文件夹后再里面写android.mk文件并把相关c文件放于同一目录下,执行ndk-build会自动在libs中生成…..不用建项目而且更好用…..mdzz

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
NDK_ROOT=D:/TrueSDK/AndroidNdk/android-ndk-r16b
TOOLCHAINS_ROOT=$(NDK_ROOT)/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64
#gcc位置
TOOLCHAINS_PREFIX=$(TOOLCHAINS_ROOT)/bin/arm-linux-androideabi
#工具链的头文件
TOOLCHAINS_INCLUDEF=$(TOOLCHAINS_ROOT)/lib/gcc/arm-linux-androideabi/4.9.x/include-fixed
TOOLCHAINS_INCLUDE=$(TOOLCHAINS_ROOT)/lib/gcc/arm-linux-androideabi/4.9.x/include
#工具链的lib
TOOLCHAINS_GCCLIB=$(TOOLCHAINS_ROOT)/lib/gcc/arm-linux-androideabi/4.9.x/armv7-a
PLATFORM_ROOT=$(NDK_ROOT)/platforms/android-26/arch-arm
#平台的头文件
PLATFORM_SYSROOT=$(NDK_ROOT)/sysroot
#平台的lib
PLATFORM_LIB=$(PLATFORM_ROOT)/usr/lib
NAME=hello
RM=del
# -I用来告诉gcc去哪里找头文件 -L告诉gcc去哪里找库文件 -ldl表示使用动态连接函数库 -nostdlib表示不用glibc的实现,用谷歌实现的
# -lxxx表示具体链接到libxxx.a或者libxxx.so 具体用那个用-Bdynamic动态与-Bstatic静态指定
#可执行文件的flag
FLAGSEXE=-I$(TOOLCHAINS_INCLUDE) \
-I$(TOOLCHAINS_INCLUDEF) \
--sysroot=$(PLATFORM_SYSROOT) \
-L$(PLATFORM_LIB) \
-L$(TOOLCHAINS_GCCLIB) \
-nostdlib \
-lgcc \
-Bdynamic \
-lc \
-ldl \
-pie -fPIE
#so的脚本
FLAGSSO=-I$(TOOLCHAINS_INCLUDE) \
-I$(TOOLCHAINS_INCLUDEF) \
--sysroot=$(PLATFORM_SYSROOT) \
-L$(PLATFORM_LIB) \
-L$(TOOLCHAINS_GCCLIB) \
-nostdlib \
-lgcc \
-Bdynamic \
-lc \
-ldl \
-fPIC \
-shared
# 这里是告诉链接器该链接什么 libgcc.a定了除法来用 其它库文件如include中的会自动包含从-L中寻找
OBJS=$(NAME).o \
$(PLATFORM_LIB)/crtbegin_dynamic.o \
$(PLATFORM_LIB)/crtend_android.o \
$(TOOLCHAINS_GCCLIB)/libgcc.a
all:
$(TOOLCHAINS_PREFIX)-gcc $(FLAGSEXE) -c $(NAME).c -o $(NAME).o
$(TOOLCHAINS_PREFIX)-gcc $(FLAGSEXE) $(OBJS) -o $(NAME)
clean:
$(RM) *.o
install:
adb push $(NAME) /data/local/
adb shell chmod 755 /data/local/$(NAME)
so:
$(TOOLCHAINS_PREFIX)-gcc $(FLAGSSO) -c $(NAME).c -o $(NAME).o
$(TOOLCHAINS_PREFIX)-gcc $(FLAGSSO) $(OBJS) -o lib$(NAME).so
##COMPLIE COMMAND:
#for so file: <ndk_toolchains>-gcc --sysroot=<ndk_toolchains_root_directory>/sysroot -llog -ldl -fPIC -shared -o libthook.so hook.c
#for so_inject executable file: <ndk_toolchains>-gcc --sysroot=<ndk_toolchains_root_directory>/sysroot -llog -ldl -fPIE -pie -llog -o so_inject so_inject.c
#default hook entry: hook_entry

说明:目前只能实现单个自定义c文件编译,且需要输入文件名参数,示例:
make NAME=hello
就可编译hello.c了
make so NAME=xxx
就可以编译为so库

-I -L -l

有了-I 和-L 编译时找.h和连接时找.o .a .so 的路径就有了
printf什么的库名字是指定好的,gcc会自动寻找这些基本库文件(但个数有限),路径已经由你指定了。所以能找到。(自己猜测,问问权威的老师)
后记:那是运行库…c运行时最基本的库,必连接的

所以特定需要的库手动添加就好了…..
-l(小写L)表示添加的库 比如-llog是添加log库(NDK库)去连接。等于在后面直接加liblog.so/a 参加连接,具体用那个用-Bdynamic动态与-Bstatic静态指定

–sysroot:
如果在编译时指定了-sysroot就是为编译时指定了逻辑目录。编译过程中需要引用的库,头文件,如果要到/usr/include目录下去找的情况下,则会在前面加上逻辑目录。相当于默认路径

PIE和PIC

区别
PIE:用在可执行文件
PIC:用在库文件
共同点
生成跟位置没有关系的symbol

make

make自动编译能做的只是.c->.o自动而已