为了使用g++编译jni,我上网查找资料,也下载了makefiel的教程。网上的资料大多乱七八糟,没法看。教程里面是一个片段一个片段的介绍的,根本不知道哪一个在上,哪一个在下。后经3个小时的不断尝试,我终于写出了正确的makefile。(CSDN把所有TAB删掉了,其实标签后面的指令是以TAB开始的。好在我都有分段。指令段的第二行开始都是有TAB的)
makefile完整结构如下:
CC = g++
target = ../jni/Tjni.dll
options_jni = -shared -Wl,-kill-at -s -o
options_exe = -s -o
options_obj = -c -o
options = -shared -Wl,-kill-at -s -o
sources = sample_razerpen_jni_Tjni.cpp
subObjects = JniToolClasses.o
export CC
.PHONY:build
build:
$(MAKE) -C JniToolClasses
$(MAKE) $(target)
$(target):$(subObjects) $(sources)
$(CC) $(options) $(target) $(subObjects) $(sources)
.PHONY:rebuild
rebuild:
$(MAKE) clear
$(MAKE) build
.PHONY:clean
clean:
$(MAKE) clear
.PHONY:clear
clear:
-del "$(target)"
-del "*.o" /s /q
makefile由两部分组成,从export CC往上,包括exportCC,是变量定义部分。变量不可以赋值给变量。变量名是随便起的。变量名通过$(CC)这种格式引用(引用方式相当于C语言的宏)。
变量定义之后的是命令部分。每一个命令段都有一个以冒号结束的标签(如clean:)标签左边不能有TAB。标签右边是条件,意思是条件中的文件更新了以后,这个命令就可以通过make clean执行。如果文件没有更新,则略过这段指令。如果没有指定文件,则每次调用make clean都会执行。
$(MAKE)等价于make。不过在Eclipse中用$(MAKE)会高亮显示为关键字,make则不会。
.PHONY:clean是为了防止文件系统中存在clean这个文件而导致make执行错误的指令。有了它,make clean在任何情况下都代表执行clean段,而不会编译出一个叫clean的文件。每一个不代表文件的标签都应该附上这一条。
$(target):$(subObjects) $(sources)
$(CC) $(options) $(target) $(subObjects) $(sources)
也是一个指令段,但是这个指令段指向一个文件$(target)(前面已经定义了target=../jni/Tjni.dll)。所以不附加.PHONY。冒号的右边是$(subObjects) $(sources),表示如果在$(subObjects) 或者$(sources)之中,有一个文件有更新,则允许执行这段指令,否则跳过。
$(CC) $(options) $(target) $(subObjects) $(sources)其实就是g++ -shared -Wl,-kill-at -s -o ../jni/Tjni.dll JniToolClasses.o sample_razerpen_jni_Tjni.cpp
build:
$(MAKE) -C JniToolClasses
$(MAKE) $(target)
是第一段指令,如果直接执行make则等同于make build。
它的第一条指令是进入JniToolClasses执行子目录的makefile。如果没有子目录的makefile,则不应该写这一句。
第二条指令是执行当前文件的$(target)段。
再来看子目录下的makefile
target = ../JniToolClasses.o
options_obj = -c -o
sources = CJNIArrayLoader.cpp
export CC
.PHONY:build
build:
$(MAKE) $(target)
$(target):$(sources)
$(CC) $(options_obj) $(target) $(sources)
由于子目录,没有下级子目录,所以就不写$(MAKE) -C JniToolClasses了。
主makefile的clean可以清除子目录的.o文件,所以子makefile也不写clean段。
另外,像build clean这些标签名字也是可以改的。变量没有定义其实也可以写上,只不过会被忽略。
makefile完整结构如下:
CC = g++
target = ../jni/Tjni.dll
options_jni = -shared -Wl,-kill-at -s -o
options_exe = -s -o
options_obj = -c -o
options = -shared -Wl,-kill-at -s -o
sources = sample_razerpen_jni_Tjni.cpp
subObjects = JniToolClasses.o
export CC
.PHONY:build
build:
$(MAKE) -C JniToolClasses
$(MAKE) $(target)
$(target):$(subObjects) $(sources)
$(CC) $(options) $(target) $(subObjects) $(sources)
.PHONY:rebuild
rebuild:
$(MAKE) clear
$(MAKE) build
.PHONY:clean
clean:
$(MAKE) clear
.PHONY:clear
clear:
-del "$(target)"
-del "*.o" /s /q
makefile由两部分组成,从export CC往上,包括exportCC,是变量定义部分。变量不可以赋值给变量。变量名是随便起的。变量名通过$(CC)这种格式引用(引用方式相当于C语言的宏)。
变量定义之后的是命令部分。每一个命令段都有一个以冒号结束的标签(如clean:)标签左边不能有TAB。标签右边是条件,意思是条件中的文件更新了以后,这个命令就可以通过make clean执行。如果文件没有更新,则略过这段指令。如果没有指定文件,则每次调用make clean都会执行。
$(MAKE)等价于make。不过在Eclipse中用$(MAKE)会高亮显示为关键字,make则不会。
.PHONY:clean是为了防止文件系统中存在clean这个文件而导致make执行错误的指令。有了它,make clean在任何情况下都代表执行clean段,而不会编译出一个叫clean的文件。每一个不代表文件的标签都应该附上这一条。
$(target):$(subObjects) $(sources)
$(CC) $(options) $(target) $(subObjects) $(sources)
也是一个指令段,但是这个指令段指向一个文件$(target)(前面已经定义了target=../jni/Tjni.dll)。所以不附加.PHONY。冒号的右边是$(subObjects) $(sources),表示如果在$(subObjects) 或者$(sources)之中,有一个文件有更新,则允许执行这段指令,否则跳过。
$(CC) $(options) $(target) $(subObjects) $(sources)其实就是g++ -shared -Wl,-kill-at -s -o ../jni/Tjni.dll JniToolClasses.o sample_razerpen_jni_Tjni.cpp
build:
$(MAKE) -C JniToolClasses
$(MAKE) $(target)
是第一段指令,如果直接执行make则等同于make build。
它的第一条指令是进入JniToolClasses执行子目录的makefile。如果没有子目录的makefile,则不应该写这一句。
第二条指令是执行当前文件的$(target)段。
再来看子目录下的makefile
target = ../JniToolClasses.o
options_obj = -c -o
sources = CJNIArrayLoader.cpp
export CC
.PHONY:build
build:
$(MAKE) $(target)
$(target):$(sources)
$(CC) $(options_obj) $(target) $(sources)
由于子目录,没有下级子目录,所以就不写$(MAKE) -C JniToolClasses了。
主makefile的clean可以清除子目录的.o文件,所以子makefile也不写clean段。
另外,像build clean这些标签名字也是可以改的。变量没有定义其实也可以写上,只不过会被忽略。