Gcc Makefile通用规则不起作用

Gcc Makefile通用规则不起作用,gcc,makefile,Gcc,Makefile,我试图创建一个通用的makefile,其中提供源文件和一些目录的名称,但是我无法获得目标文件的通用规则 我的makefile如下所示: SOURCE_NAMES=main EXECUTABLE_NAME=Program EXECUTABLE_DIR=./dist EXECUTABLE_EXT= SOURCE_DIR=./src SOURCE_EXT=.cc OBJECT_DIR=./build OBJECT_EXT=.obj COMPILER=gcc COMPILER_FLAGS=-c -W

我试图创建一个通用的makefile,其中提供源文件和一些目录的名称,但是我无法获得目标文件的通用规则

我的makefile如下所示:

SOURCE_NAMES=main
EXECUTABLE_NAME=Program

EXECUTABLE_DIR=./dist
EXECUTABLE_EXT=
SOURCE_DIR=./src
SOURCE_EXT=.cc
OBJECT_DIR=./build
OBJECT_EXT=.obj

COMPILER=gcc
COMPILER_FLAGS=-c -Wall -std=gnu++11
LINKER_FLAGS=

SOURCES=$(addsuffix $(SOURCE_EXT),$(addprefix $(SOURCE_DIR)/,$(SOURCE_NAMES)))
OBJECTS=$(addsuffix $(OBJECT_EXT),$(addprefix $(OBJECT_DIR)/,$(SOURCE_NAMES)))
EXECUTABLE=$(EXECUTABLE_DIR)/$(EXECUTABLE_NAME)$(EXECUTABLE_EXT)

all: $(EXECUTABLE) 

$(EXECUTABLE): $(OBJECTS) 
    $(COMPILER) $(LINKER_FLAGS) $(OBJECTS) -o $@

%$(OBJECT_EXT): %$(SOURCE_EXT)
    $(COMPILER) $(COMPILER_FLAGS) $< -o $@
但我不希望对每个源文件都显式地这样做

我该如何解决这个问题

编辑:


为了清楚起见,这个问题是关于为什么我的makefile末尾的通用规则不起作用。我希望
/build/main.obj
匹配
%$(OBJECT\u EXT)
%.obj
,但情况似乎并非如此,我不明白它为什么不起作用。

尝试将
/build
/src
添加到您的规则(包含在“显式”中)规则,但在Makefile中使用的变量中不存在)。

是否不将扩展名转换为变量?我觉得你有点过分了…@DevSolar你什么意思?就像简单地将$(OBJECT_EXT)和$(SOURCE_EXT)的所有出现分别替换为.obj和.cc一样?我已经试过了,但没用。我真的搞不懂你想做什么。例如,您将
$(SOURCES)
添加到
all:
目标;你可能有个好主意,但对我来说,它看起来像一只虫子。我建议采取相反的方法:从一个简单的(功能性的)Makefile开始,然后从那里开始。还有,.@DevSolar再次考虑我同意你的观点,所以我删除了它。我最初的想法是,如果源代码被更改,它应该重建源代码,但是我这样做的方式是错误的,就像你说的那样,它是多余的,因为它已经被不起作用的对象文件的依赖性暗示了。这个问题还没有解决,你所有的评论到目前为止都与这个问题无关,所以我编辑了这个问题,以澄清我想问的问题。有一个问题质量的门槛,在这个门槛上,我不愿意把一个问题变成一个实际复制报告问题的装置,而是倾向于指出问题中的弱点。“没关系,现在我突然想到了,”回答补充道,“就是这样。”。我怀疑这和目录有关。。。将
%$(对象外部):%$(源外部)
更改为
$(对象外部)/%$(对象外部):$(源外部)/%$(源外部)
修复了此问题。你能解释一下为什么在目标之前加上目录很重要吗?我希望
%
符号包含目录。@RPFeltz:如果
%
包含目录,除了源文件的目录外,您如何为目录中的对象文件制定规则?嗯,我不太清楚您的意思。我个人的解释是这样的:所有以.obj结尾的依赖项都应该由%.obj指定的规则处理,与它们所在的目录无关。@RPFeltz:那么你还没有真正理解
%
是如何工作的。规则依赖方的
%
将被规则目标方的
%
所代表的字符串替换。如果
%.obj
匹配,例如
/build/main.obj
,则右侧的
%.cc
将是
/build/main.cc
——并且您将无法从不同目录中的源文件创建
/build
中的对象文件。这就是为什么
%
不匹配目录名,而只匹配文件名(或者实际上是基名)。我明白了!那很有道理。我现在明白它为什么不起作用了。谢谢。
./build/main.obj: ./src/main.cc
    $(COMPILER) $(COMPILER_FLAGS) $< -o $@