make
的输出如下
gcc -Wall -Wextra -std=c99 -o bin/test src/obj/ src/obj/main.o src/obj/test.o
/usr/bin/ld: cannot find src/obj/: File format not recognized
collect2: error: ld returned 1 exit status
make: *** [test] Error 1
如您所见,执行的编译命令正在尝试将src / obj /编译为目标文件。我最好的猜测是它以某种方式被列在OBJ变量中。
编辑:这是一个有效的makefile。经过一些调试后,我做了以下更改。
这不起作用。文件路径在编译时都混淆了。 所以这......
# object directory
OBJ_DIR=$(SRC_DIR)/obj
# souce files
SRC=$(wildcard $(SRC_DIR)/*.c)
# object files
OBJ=$(patsubst $(SRC_DIR)/%.c, $(OBJ_DIR)/%.o, $(SRC)) # still directories in OBJ list causing problems
成了这个......
# object directory
OBJ_DIR=obj
# souce files
SRC=$(patsubst $(SRC_DIR)/%.c,%.c,$(wildcard $(SRC_DIR)/*.c))
# object files
OBJ=$(patsubst %.c,%.o,$(SRC))
这......
# rule that individual objects rely on .c versions and .h files
# needs to compile to .o files, then compile to executable
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
# actual compile commands
$(PROJ_NAME): $(OBJ_DIR)/$(OBJ)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJ_DIR)/$(OBJ)
成了这个......
# rule that individual objects rely on .c versions and .h files
# needs to compile to .o files, then compile to executable
%.o: $(SRC_DIR)/%.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
# actual compile commands
$(PROJ_NAME): $(SRC_DIR)/$(OBJ_DIR)/$(OBJ)
$(CC) $(CFLAGS) -o $(TARGET) $(SRC_DIR)/$(OBJ_DIR)/$(OBJ)
基本上,使用patsubst
我确保列表中的所有文件都没有附加到它们的路径,然后在需要时手动指定完整路径。
答案 0 :(得分:3)
这两行
$(PROJ_NAME): $(OBJ_DIR)/$(OBJ)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJ_DIR)/$(OBJ)
可能不对,因为$(OBJ)
已包含$(OBJ_DIR)
所以使用
$(PROJ_NAME): $(OBJ)
@echo OBJ= $(OBJ) at= $@ caret= $^
$(COMPILE.c) $(CFLAGS) -o $@ $^
代替。了解有关GNU make内置规则的更多信息(您将使用make -p
获取它们)。如果您满意,请删除调试@echo
行。
正如我评论的那样,使用remake作为remake -x
或make --trace
来了解正在发生的事情(假设是GNU make&amp; Linux)。
您可能希望使用strip函数删除前导空格和尾随空格,例如
OBJ= $(strip $(patsubst $(SRC_DIR)/%.c, $(OBJ_DIR)/%.o, $(SRC)))
确保您的OBJ_DIR
定义(以及Makefile
中的其他定义)不包含尾随空格。不要在其中添加评论:
#be sure that following line does not have comments or trailing spaces
OBJ= $(strip $(patsubst $(SRC_DIR)/%.c, $(OBJ_DIR)/%.o, $(SRC)))
将#
条注释放在 make 变量的行中是一个非常糟糕的习惯。
您应该在定义行之前或之后放置注释行。
答案 1 :(得分:1)
我尝试使用包含src
文件的a.c
目录的makefile。
$(OBJ_DIR)/$(OBJ)
似乎扩展为src/obj/ src/obj/a.o
。变量$(OBJ)
可能包含空字符串或空格
答案 2 :(得分:0)
您的问题肯定与宏定义结束时的注释有关。 #
只应在宏行上使用,以便在宏定义的末尾嵌入空格,这是错误的,并且会产生不必要的模糊后果。
以下是一些提示和评论:
您可以使用:=
运算符在解析时评估宏,这可能更适合$(wildcard..)
和$(shell...)
扩展。
SRCS:=$(wildcard $(SRC_DIR)/*.c)
为清楚起见,您应该为事物列表使用复数标识符:SRCS
和OBJS
。 OBJS
应该只是包含路径的目标文件列表。我不明白为什么你坚持从源和对象文件列表中剥离路径。 Gnu Make通用规则可以轻松地为不同的输出源和/或对象目录指定不同的编译选项。您可以利用此功能从相同的源生成不同的目标,例如32位和64位版本,并让它们共存而不会发生冲突。
最终目标应该很简单:
$(PROJ_NAME): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS)