【发布时间】:2014-12-18 10:30:29
【问题描述】:
我的问题
我正在用一个 makefile 编译多个目标,到目前为止效果很好。我的问题是其中一个目标共享一个 .h 文件 (hash.h),该文件根据宏进行更改:HASHTABLE_USING_LISTS
所以,当 Makefile 运行时,所有东西都被编译,但是 practica2_list_bench,它应该使用定义了 HASHTABLE_USING_LISTS 的版本,最终链接到一个旧的 .o 对象,该对象在没有它的情况下编译。
最终导致整个程序的内存损坏和漂亮的SIGSEV。
很明显,我必须以某种方式告诉 Makefile 在 .h 文件更改时重新编译(在这种情况下,它通过指定该宏来更改)。
这是我所有的 Makefile:
.SECONDEXPANSION:
# This is the makefile that generates the executable
# If compiing with -ansi, we should use
# -Wno-error=implicit-function-declaration -Wno-implicit-function-declaration
CFLAGS = -Wall -Werror -g
LFLAGS = -lm
INCLUDE_BENCH = -I$(CURDIR) -Ibenchmark
FILES_O =
FILES_C =
TARGET = practica2
CURRENT =
NAME = $(TARGET)
NAME_BENCH = $(TARGET)_bench
NAME_LIST = $(TARGET)_list_bench
.PHONY: bare bench list
all: bare bench list
bare: FILES_C = main.c parsing.c linked-list.c hash.c
bare: FILES_O = $(subst .c,.o,$(FILES_C))
bench: FILES_C = benchmark/main_bench.c parsing.c benchmark/benchmark.c linked-list.c hash.c
bench: CFLAGS += $(INCLUDE_BENCH)
bench: CURRENT = _BENCH
bench: FILES_O = $(subst .c,.o,$(FILES_C))
list: FILES_C = benchmark/main_bench.c parsing.c benchmark/benchmark.c linked-list.c benchmark/hash_list.c
list: CFLAGS += -DHASHTABLE_USING_LISTS $(INCLUDE_BENCH)
list: CURRENT = _LIST
list: FILES_O = $(subst .c,.o,$(FILES_C))
clean:
-/bin/rm -f *.o benchmark/*.o $(NAME) $(NAME_BENCH) $(NAME_LIST)
%.o: %.c hash.h
gcc $(CFLAGS) -c $< -o $@
bare bench list: $$(FILES_O)
gcc $(FILES_O) -o $(NAME$(CURRENT)) $(LFLAGS)
我完全没有想法。想出这个“多目标”“第二次扩展”版本时遇到了很多麻烦,我不知道从这里开始我应该如何继续。
请注意,可能会进行一些改进,但这是我将在解决后解决的另一个问题。
谢谢!
【问题讨论】:
-
头文件没有改变,你定义了一个宏,告诉编译器以不同的方式预处理头文件。您有两个选择: Make 可以使用一个额外的文件来跟踪您上次构建的可执行文件,您可以将每个目标文件的两个版本保存在两个不同的名称下,您可以维护两个目标目录来保存目标文件两个可执行文件,或者您可以每次都重建所有可执行文件(粗略但有效)。什么听起来不错?
-
@Beta 我想拥有单独的文件夹将是要走的路。我将如何在 FILES_O 上的每个条目前面加上一些文本?如
FILES_O = $(prepend objs/,$(subs .c,.o,$(FILES_C)))? GCC 会足够聪明地“检测”那些位于不同文件夹中的 .o 文件并相应地生成它们? -
@Beta
addprefix似乎是我的命令。我会测试一下。 -
@Beta 完成并正常工作,谢谢。我会用最终版本回答自己
标签: c linux makefile dependencies