获取make以在特定目录中创建目标文件

时间:2013-02-01 04:34:53

标签: makefile gnu-make

GNU Make 3.82
gcc 4.7.2
c89

我有以下make文件:

INC_PATH=-I/home/dev_tools/apr/include/apr-1
LIB_PATH=-L/home/dev_tools/apr/lib
LIBS=-lapr-1 -laprutil-1
RUNTIME_PATH=-Wl,-rpath,/home/dev_tools/apr/lib
CC=gcc
CFLAGS=-Wall -Wextra -g -m32 -O2 -D_DEBUG -D_THREAD_SAFE -D_REENTRANT -D_LARGEFILE64_SOURCE $(INC_PATH)
SOURCES=$(wildcard src/*.c)
OBJECTS=$(patsubst %.c, %.o, $(SOURCES))

EXECUTABLE=bin/to

all:    build $(EXECUTABLE)

$(EXECUTABLE):  $(OBJECTS)
    $(CC) $(CFLAGS) -o $@ $(RUNTIME_PATH) $(OBJECTS) $(LIB_PATH) $(LIBS)

$(OBJECTS): $(SOURCES)
    $(CC) $(CFLAGS) -c $(SOURCES) $(LIB_PATH) $(LIBS)

build:
    @mkdir -p bin

clean:
    rm -rf $(EXECUTABLE) $(OBJECTS) bin
    find . -name "*~" -exec rm {} \;
    find . -name "*.o" -exec rm {} \;

我的目录结构就像这个project/src project/bin。我的Makefile位于project (root)文件夹中,我的所有* .h和* .c都在src目录中。目前我只有一个名为timeout.c的源文件

我收到此错误:

gcc: error: src/timeout.o: No such file or directory

我用它来获取所有源文件:

SOURCES=$(wildcard src/*.c)

目标文件:

OBJECTS=$(patsubst %.c, %.o, $(SOURCES))

但是,make似乎在Makefile所在的项目根文件夹中创建了目标文件。它应该不在src目录中吗?

3 个答案:

答案 0 :(得分:18)

这条规则有两个问题(好吧,三个):

$(OBJECTS): $(SOURCES)
    $(CC) $(CFLAGS) -c $(SOURCES) $(LIB_PATH) $(LIBS)

您还没有注意到,但该规则使每个对象依赖于所有源,并尝试以这种方式构建。只要您只有一个来源就没问题。使用static pattern rulean automatic variable轻松修复:

$(OBJECTS): src/%.o : src/%.c
    $(CC) $(CFLAGS) -c $< $(LIB_PATH) $(LIBS)

此外,命令(“$(CC)...”)没有指定输出文件名,因此gcc将从源文件名中推断出它;如果你给它src/timeout.c,它将产生timeout.o(在工作目录中,project/)。因此,您应指定输出文件的所需路径。使用另一个自动变量很容易:

$(OBJECTS): src/%.o : src/%.c
    $(CC) $(CFLAGS) -c $< $(LIB_PATH) $(LIBS) -o $@

答案 1 :(得分:4)

使用gcc -o 选项将输出文件写入特定位置。例如,您可以说:

$(CC) $(CFLAGS) -c $(SOURCES) $(LIB_PATH) $(LIBS) -o $(OBJECTS)

不幸的是,这一行存在问题:如果$(SOURCES)中有多个源文件,它将无效,因为$(OBJECTS)也将包含多个文件名,而 -o 选项仅绑定到第一个参数。

编译源代码文件列表中的每个文件的方法是使用隐式规则。在gmake中,您会写:

$(EXECUTABLE):  $(OBJECTS)
        $(CC) $(CFLAGS) -o $@ $(RUNTIME_PATH) $(OBJECTS) $(LIB_PATH) $(LIBS)

%.o : %.c
        $(CC) $(CFLAGS) -c $< -o $@

其中 $&lt; 将替换为输入文件的名称, $ @ 将替换为输出文件中的名称。

答案 2 :(得分:1)

我解决了这个请求,这是我的Makefile和目录树。


PROJECT:= main.exe

DIR_SRC + =。

DIR_SRC + = ./src

DIR_INC + = -lpthread

DIR_INC + = -I./inc

DIR_INC + = $(addprefix -I,$(DIR_SRC))

SRC_C + = $(通配符$(后缀/*.c,$(DIR_SRC)))

#OBJ:= $(过滤%.o,$(SRC_C:.c = .o))

OBJ:= $(部分%.c,%。o,$(SRC_C))

EXE:= $(项目)

CC_PREFIX:=

CC:= $(CC_PREFIX)gcc

CFLAG =

CLIB = -L。

.PHONY:全部

全部:$(OBJ)$(EXE)

%。o:%。c

$(CC) $(CFLAG) $(DIR_INC) -c $< -o $@ 

$(EXE):$(OBJ)

$(CC) $(CFLAG) $(CLIB) $(OBJ) -o $@ 

干净:

rm -r $(EXE) $(OBJ)

查看我的目录树:

enter image description here