因为要整理一个古老的JAVA project,原来的开发环境已经没有,找到source code,现在要重新搭建编译环境。决定使用Makefile的方式作为源代码的一部分。make一般用于GNU C,我们可以认为它是一个shell,可以完成我们期待的编译工作,无论是C还是java。Makefile每次总是要写半天,每次都不记得,总结一下,以后可以方便进行copy。
简单的就直接将编译的指令放入,例如在clutter学习中,可以这种最原始的方式:
stage:
gcc -Wall -g stage.c -o stage `pkg-config clutter-1.0 --cflags --libs`
这也是我通常能够记住的唯一的方式。为了让自己明白,以前如果不是太大的project,我就一个一个加。原始的也是最好的。如果我们希望有一个模板,能够通过更换参数可以适配不同的情况。可以使用下面的方式:
CFLAGS = -Wall -g `pkg-config clutter-1.0 clutter-imcontext-0.1 --cflags`
LIBS = -Wall -g `pkg-config clutter-1.0 clutter-imcontext-0.1 --libs`
TARGET1 = mytarget
OBJ1 = file1.o file2.o file3.o ....
%o : %c
$(CC) $(CFLAGS) -c $< -o $@
$(TARGET1): $(OBJ1)
$(CC) $(LIBS) -o $(TARGET1) $^
all: $(TARGET1)
clean:
rm $(TARGET1) *.o
这里的关键是%o: %c,冒号后面表示所依赖的文件。例如test: main.o test1.o test2.o,后面三个文件表示生成目标文件test所依赖的文件列表。%o这里指结尾为o的目标,也就是OBJ1中定义的各个filen.o,和其相关的是相应的%c,也就是对应的filen.c。$@表示当前规则下的目标文件列表,在这个例子中,即filen.o。$<指依赖的文件列表中的第一个文件,即filen.c。
$(TARGET1): $(OBJ1)中,目标文件为$(TARGET1),即mytarget,依赖文件为$(OBJ1),即file1.o file2.o file3.o。为了生成相关的file1.o文件,查找到匹配%o:%c,如果是file1.o,即为file1.o: file1.c。如此类推获得file2.o,file3.o,接着是生成最终执行文件,$(CC) $(LIBS) -o $(TARGET1) $^,$^表示依赖文件列表中的所有依赖,这里即所有的filen.o。
对于一个project,我们通常有多个子目录,每个子目录完成特定的内容,不同子目录可能由不同开发人员来维护。每个子目录有自己的Makefile,project只需遍历各个子目录并执行他的make就可以了。最简单的,例如我们需要进入子目录util,并运行它的make,可以简单地写为:
wei:
(cd util && make)
下面是一个长得比较正式的例子,其实我们可以使用上面简单的方式,我还是喜欢易懂的:
SUBDIRS = util sip ... ...
define make_subdir
@for subdir in $(SUBDIRS) ; do /
( cd $$subdir && make $1) /
done;
endef
all:
$(call make_subdir , all)rm:
$(call make_subdir , rm)install:
$(call make_subdir , install)
这里的关键是定义make_subdir的处理。对于每一个在$(SUBDIRS),例如util,sip,他赋值给subdir,并执行进入子目录,运行make,make是携带参数的,他携带调用是的第一个参数($1)。调用make_subdir的方式为$(call make_subdir,param1,param2 ....)。
对于java的编译,在子目录下面,我们的Makefile这样写:
CLASS_PATH = ../../../classes
SRC_FILE = Debug WeiUtil name1 name2 name3 ...define compile
@for file in $(SRC_FILE); do /
echo javac -d $(CLASS_PATH) $$file.java; /
(javac -d $(CLASS_PATH) $$file.java) || exit; /
done;
endef
all: rm
$(call compile)
rm:
rm -rf $(CLASS_PATH)/wei/util
这里也使用了遍历的方式,需要注意的是,当出现编译错误的时候,我们希望编译停下来,因此进行了判断,如果失败,exit。就这样,我们写了一个java的Makefile。建立自己的编译环境,不需要借助Eclipse等工具,同样可以组织大型project。只要有代码,开发环境就在。
相关链接:我的JAVA相关文章