通常程序并不只存放在同一个目录下,例如:
├── include
│ ├── bar.h
│ └── foo.h
├── Makefile
└── src
├── bar.c
├── foo.c
└── main.c
代码分别如下:
/* bar.h */
#ifndef __BAR_H
#define __BAR_H
extern void bar(void);
#endif /* __BAR_H */
/* foo.h */
#ifndef __FOO_H
#define __FOO_H
extern void foo(void);
#endif /* __FOO_H */
/* bar.c */
#include <stdio.h>
void bar(void)
{
printf("bar function\n");
}
/* foo.c */
#include <stdio.h>
void foo(void)
{
printf("foo function\n");
}
/* main.c */
#include <stdio.h>
#include "foo.h"
#include "bar.h"
int main(void)
{
printf("main function\n");
foo();
bar();
return 0;
}
顶层Makefile如下:
# Makefile
CC = gcc
OBJ = main.o foo.o bar.o
prog:$(OBJ)
$(CC) -o $@ $(OBJ)
%.o:%.c
$(CC) -c $<
.PHONY:clean
clean:
-rm -f prog $(OBJ)
如果仍然使用上面的Makefile,make时是不会通过的,因为main.c这些源文件已经移动到src目录中去了,默认情况下,make时只会在当前目录下寻找目标和依赖,也就是寻找main.o main.c这类文件,当前目录没有这些文件,肯定不能生成最终的目标文件prog,那么如何在其它目录下搜索目标和依赖呢?在Makefile中可以使用VPATH或者vpath,例如:
# Makefile
CC = gcc
OBJ = main.o foo.o bar.o
VPATH = src:include
prog:$(OBJ)
$(CC) -o $@ $(OBJ)
%.o:%.c
$(CC) -c $<
main.o:foo.h bar.h
.PHONY:clean
clean:
-rm -f prog $(OBJ)
再次make,还是会提示缺少foo.h文件,那是因为VAPTH只对make起作用,以便make找到目标和依赖,不会对编译起任何作用。而gcc在编译main.c时由于没有找到foo.h这类头文件,所以会出现编译错误,这个时候就需要加上-I选项,修改后的Makefile如下:
# Makefile
CC = gcc
OBJ = main.o foo.o bar.o
CFLAGS = -I include
VPATH = src:include
prog:$(OBJ)
$(CC) -o $@ $(OBJ)
%.o:%.c
$(CC) $(CFLAGS) -c $<
main.o:foo.h bar.h
.PHONY:clean
clean:
-rm -f prog $(OBJ)
再运行make,最终得到prog程序。除了VPATH外,还可以使用vpath,用法如下:
1. vpath pattern directories
2. vpath pattern
3. vpath
第一个用法用于指定搜索目录,后两个用法用于清除搜索目录,例如:
# Makefile
CC = gcc
OBJ = main.o foo.o bar.o
CPPFLAGS= -Iinclude
#VPATH = src:include
vpath %.h include
vpath %.c src
prog:$(OBJ)
$(CC) -o $@ $(OBJ)
%.o:%.c
$(CC) $(CPPFLAGS) -c $<
main.o:foo.h bar.h
.PHONY:clean
clean:
-rm -f prog $(OBJ)
注:将CFLAGS改为CPPFLAGS,因为-I选项应该是预编译中的选项,而不是编译选项。