Makefile的编写——用于C和JAVA

  因为要整理一个古老的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相关文章

你可能感兴趣的:(程序设计)