34
GNU Make 3.82
gcc 4.7.2
c89

我有以下制作文件:

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目录下吗?

4

3 回答 3

29

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

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

您还没有注意到,但是该规则使每个对象都依赖于所有源,并尝试以这种方式构建。只要您只有一个来源,这不是问题。使用静态模式规则自动变量易于修复:

$(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 $@
于 2013-02-01T07:03:56.453 回答
7

使用gcc's -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 $@

其中$<替换为输入文件的名称,$@替换为输出文件的名称。

于 2013-02-01T05:54:42.323 回答
2

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

PROJECT := main.exe

DIR_SRC += .
DIR_SRC += ./src

DIR_INC += -lpthread 
DIR_INC += -I./inc 
DIR_INC += $(addprefix -I, $(DIR_SRC))

SRC_C += $(wildcard $(addsuffix /*.c, $(DIR_SRC)))
#OBJ := $(filter %.o, $(SRC_C:.c=.o))
OBJ := $(patsubst %.c, %.o, $(SRC_C))
EXE := $(PROJECT)

CC_PREFIX := 
CC := $(CC_PREFIX)gcc
CFLAG = 
CLIB = -L .

.PHONY:all

all:$(OBJ) $(EXE)

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

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

clean:
    rm -r $(EXE) $(OBJ) 

查看我的目录树:

在此处输入图像描述

于 2020-08-10T04:04:48.650 回答