首页 > 解决方案 > 为内部目录创建目标文件时makefile失败

问题描述

在当前目录中,我有以下文件:

election.c election.h extended_map.c extended_map.h main.c test_utilities.c utilities.c utilities.h

另外,我在当前文件夹中有一个内部文件夹,mtm_map其中包括map.c map.h

我创建了一个运行良好的makefile:

make main.o
make extended_map.o
make election.o
make utilities.o
make clean

但运行时失败:

-bash-4.2$ make map.o
cc    -c -o map.o map.c
map.c: In function ‘getIndexOfKey’:
map.c:36:5: error: ‘for’ loop initial declarations are only allowed in C99 mode
     for (int i = 0; i < map->size; i++)
     ^
map.c:36:5: note: use option -std=c99 or -std=gnu99 to compile your code
map.c: In function ‘initializeElements’:
map.c:59:5: error: ‘for’ loop initial declarations are only allowed in C99 mode
     for (int i=initial_index;i<last_index;i++)
     ^
map.c: In function ‘mapCopy’:
map.c:165:5: error: ‘for’ loop initial declarations are only allowed in C99 mode
     for (int i = 0; i < map->size; i++)
     ^
map.c: In function ‘mapGet’:
map.c:239:5: error: ‘for’ loop initial declarations are only allowed in C99 mode
     for (int i = 0; i < map->size; i++)
     ^
make: *** [map.o] Error 1

生成文件:

CC = gcc
OBJS = main.o ./mtm_map/map.o extended_map.o election.o utilities.o
EXEC = election
DEBUG_FLAG = -DNDEBUG
COMP_FLAG = -std=c99 -Wall -pedantic-errors -Werror
$(EXEC) : $(OBJS)
    $(CC) $(DEBUG_FLAG) $(OBJS) -o $@
main.o: main.c ./mtm_map/map.h election.h test_utilities.h
    $(CC) -c $(DEBUG_FLAG) $(COMP_FLAG) $*.c
map.o: ./mtm_map/map.c ./mtm_map/map.h utilities.h
    $(CC) -c $(DEBUG_FLAG) $(COMP_FLAG) $*.c
extended_map.o: extended_map.c extended_map.h ./mtm_map/map.h utilities.h
    $(CC) -c $(DEBUG_FLAG) $(COMP_FLAG) $*.c
election.o: election.c election.h ./mtm_map/map.h extended_map.h utilities.h
    $(CC) -c $(DEBUG_FLAG) $(COMP_FLAG) $*.c
utilities.o: utilities.c utilities.h
    $(CC) -c $(DEBUG_FLAG) $(COMP_FLAG) $*.c
clean:
    rm -f $(OBJS) $(EXEC)

关于如何解决这个问题的任何建议?请注意,我希望在当前目录中创建 map.o(不是在里面mtm_map

标签: clinuxgccmakefile

解决方案


您的 Make 没有正确使用$(COMP_FLAG)您在其中定义的内容:

通常有一个CFLAGS变量可以使用隐式规则来编译源文件,所以我会重写你Makefile的,以消除你包含在其中的大量冗余代码:

# I use the ?= operator, so you can redefine the compiler with make CC=clang ...
CC       ?= gcc 
EXEC      = election
TOCLEAN   = $(EXEC)

# NDEBUG is a compilation option, not a linking one.  The purpose of MY_CFLAGS is
# to allow you to define extra CFLAGS to be used on source code compilation.
CFLAGS    = -std=c99 -Wall -pedantic-errors -Werror -DNDEBUG $(MY_CFLAGS)
 
OBJS      = main.o mtm_map/map.o extended_map.o election.o utilities.o
# you can add files to clean in a more complex makefile
TOCLEAN  += $(OBJS)

$(EXEC): $(OBJS)
    $(CC) $(LDFLAGS) -o $@ $(OBJS)
clean:
    rm -f $(TOCLEAN)

# Extra dependencies (the dependency a.o : a.c is automatic)
main.o: mtm_map/map.h election.h utilities.h
mtm_map/map.o: mtm_map/map.h utilities.h
extended_map.o: extended_map.h mtm_map/map.h utilities.h
election.o: election.h mtm_map/map.h extended_map.h utilities.h
utilities.o: utilities.h

这应该正确构建您的项目。

笔记

如果您决定某些源文件必须驻留在您拥有 Makefile 的目录之外的其他目录中,那么您必须考虑是否要将目标文件放在您的目录中或源文件所在的目录中。我遵循了我认为您想要的内容(在目录中构建所有源文件可能会导致名称冲突,因为不同目录中的两个文件可以具有相同的名称)但是您还必须使用对象的路径(如我这里用过)

还有另一种选择,是创建一个构建目录,因此所有文件都构建在副本或源中使用的层次结构中。但这还有其他一些缺点,因为您必须重写自动规则,以便在尝试将文件放入其中之前重建您拥有的目录结构。


推荐阅读