谨以此文作为编写makefile的遇到问题的小结,不会长篇讨论makefile的语法(可以参考官方文档),仅仅讨论遇到的问题。
makefile文件是用来建立编译运行时规则,对makefile的解析最终还是会转换为对编译器(例如gcc)的调用,废话少说,看makefile文件,以实例来理解:
# which compile
CC:= g++
CPPFLAGS:= -fno-strict-aliasing -g -O2 -Ulinux -Dlinux=linux -lstdc++ -lrt -lm -lpthread \
-ldl -lrt -lcrypto -I. -I/usr/local/Other/include \
-I/usr/local/otherStatic/include -L/usr/local/otherStatic/lib -lotherStaticlib \
-Wl,-rpath,/usr/local/otherSo/lib
XXXXDaemon: XXXXDaemon.o
$(CC) $^ -o $@ $(CPPFLAGS)
XXXXDaemon.o: XXXXDaemon.h Other.h
all:
XXXXDaemon
clean:
-rm XXXXDaemon *.o
.PHONY: clean
以下作说明:
1. 该makefile是用来编译C++文件,所以CC指定为g++;
2. 需要引用第三方头文件,-I后面接目录,例如当前目录“-I.”;
3.引用第三方库,包括静态库和动态库,-L后面接库目录,然后-l指定库名,so easy;
4.引用的第三方so动态库,往往在运行程序时提示找不到该so,然后用ldd命令查看发现确实引用不到,因为我们的第三方库没有放在默认路径里,可以使用参数“-Wl,-rpath,目录”来指定运行时库的路径,然后用ldd命令可以清楚看到所加在动态库的路径;附加一段说明:
-Wl,option
Pass option as an option to the linker. If option contains commas, it is split into
multiple options at the commas. You can use this syntax to pass an argument
to the option.
5. $(CC) $^ -o $@ $(CPPFLAGS)
该条规则翻译成编译器命令,即为“g++ 所有依赖对象obj文件 -o(输出) 目标“;makefile的核心即为“目标:条件”,makefile手册截断话:
For instance, the value of ‘$^’ is a list of all the prerequisites of the rule,
including the names of the directories in which they were found, and the value of ‘$@’is the target. Thus:
foo.o : foo.c
cc -c $(CFLAGS) $^ -o $@
$^ The names of all the prerequisites, with spaces between them.
$@ The file name of the target of the rule.
知道的就这么多了,下面说说Android.mk,还是先看例子:
LOCAL_PATH:= $(call my-dir)
#libiconv.so
include $(CLEAR_VARS)
LOCAL_MODULE := libiconv
LOCAL_CFLAGS := \
-DANDROID \
-DLIBDIR="c" \
-DBUILDING_LIBICONV \
-DIN_LIBRARY
LOCAL_SRC_FILES := \
libcharset/lib/localcharset.c \
lib/iconv.c \
lib/relocatable.c
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/include \
$(LOCAL_PATH)/libcharset \
$(LOCAL_PATH)/lib \
$(LOCAL_PATH)/libcharset/include \
$(LOCAL_PATH)/srclib
include $(BUILD_SHARED_LIBRARY)
#test
include $(CLEAR_VARS)
LOCAL_MODULE :=test
LOCAL_SRC_FILES := tests/test-to-wchar.c
LOCAL_C_INCLUDES += \
$(LOCAL_PATH)/include \
$(LOCAL_PATH)/libcharset \
$(LOCAL_PATH)/lib \
$(LOCAL_PATH)/libcharset/include \
$(LOCAL_PATH)/srclib
LOCAL_SHARED_LIBRARIES := libiconv
include $(BUILD_EXECUTABLE)
这个Android.mk是用来生成iconv动态库,以及一个简单的测试示例,最终生成libiconv.so和test;以下做简要说明,具体可参考android makefile手册:
1. LOCAL_PATH:这里为jni目录,
2. include $(CLEAR_VARS),摘用一段话解释下:
The CLEAR_VARS variable gets set by the Android build system to the location of clear-vars.mk
fragment. Including this Makefile fragment clears the LOCAL_ <name> variables such as LOCAL_MODULE,
LOCAL_SRC_FILES, etc., with the exception of LOCAL_PATH.
导入该脚本将清除以LOCAL_开头的变量,除了LOCAL_PATH
3. LOCAL_C_INCLUDE:包含头文件
4. LOCAL_SRC_FILES:包含源文件
5. LOCAL_SHARED_LIBRARIES:链接的动态库,gcc的-l选项
6. include $(BUILD_EXECUTABLE) :生成可执行程序,BUILD_SHARED_LIBRARY:生成动态库,BUILD_STATIC_LIBRARY生成静态库
7. LOCAL_STATIC_LIBRARIES:链接静态库,上面没有用到,gcc的-l选项
8. LOCAL_CFLAGS :可以加入gcc编译参数,例如“LOCAL_CFLAGS := -march=armv7-a”
9. LOCAL_MODULE:指定生成的模块名称
ok,就这样,有补充再加。