C++ Makefile:没有生成目标的规则
我在这个网站上寻找解决方案,也尝试了谷歌一段时间,但不知何故,我无法让它工作 我的源代码应该在src目录中,而目标文件应该在obj目录中。现在我尝试创建一个简单的makefie,但我要么得到一个没有规则的错误,要么无法使用目录C++ Makefile:没有生成目标的规则,c++,c,build,makefile,C++,C,Build,Makefile,我在这个网站上寻找解决方案,也尝试了谷歌一段时间,但不知何故,我无法让它工作 我的源代码应该在src目录中,而目标文件应该在obj目录中。现在我尝试创建一个简单的makefie,但我要么得到一个没有规则的错误,要么无法使用目录 CC = /usr/bin/gcc CXXFLAGS = -O2 -g -Wall -fmessage-length=0 SRC:= nohupshd.cpp \ task.cpp OBJ:= nohupshd.o \
CC = /usr/bin/gcc
CXXFLAGS = -O2 -g -Wall -fmessage-length=0
SRC:= nohupshd.cpp \
task.cpp
OBJ:= nohupshd.o \
task.o
OBJDIR:= obj
SRCDIR:= src
DEP:= src/task.h
LIBS:=
TARGET:= nohupshd
all: $(TARGET)
$(TARGET): $(OBJ)
$(CC) -o $(TARGET) $(OBJ) $(LIBS)
clean:
rm -f $(OBJ) $(TARGET)
备选案文1:
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
$(CC) -S $(SRCDIR)/$< -o $(OBJDIR)/$@
$(CC) -c $(SRCDIR)/$< -o $(OBJDIR)/$@
备选案文1a:
%.o: %.cpp
$(CC) -S $(SRCDIR)/$< -o $(OBJDIR)/$@
$(CC) -c $(SRCDIR)/$< -o $(OBJDIR)/$@
当我使用这个模式时,我总是会得到一个错误,即nohupshd.o没有构建规则
备选案文2:
$(OBJ) : $(OBJDIR)/%.o: $(SRCDIR)/%.cpp
$(CC) -S $(SRCDIR)/$< -o $(OBJDIR)/$@
$(CC) -c $(SRCDIR)/$< -o $(OBJDIR)/$@
当我使用这个变体时,我可以看到它试图构建,但是我得到错误,说file.o不适合目标模式
另一个问题是$不重复编译器行中的目录名$ 不要在编译器行中重复目录名$ 因此,最后我找到了如何编写此makefile的答案,请查看我标记为正确答案的帖子,了解我的错误: 生成的makefile如下所示,为了完整起见,我将其发布在这里,包括头文件的依赖项。如果不需要,请删除ASM部分:
.SUFFIXES:
.SUFFIXES: .o .cpp
.SUFFIXES: .o .d
CC := g++
LNK:= ar
CXXFLAGS = -O2 -g -Wall -fmessage-length=0
OBJDIR:= obj
SRCDIR:= src
HDIR:= include
INCLUDE_PATHS:= -Iinclude -Iinclude/interfaces -Iinclude/support
CPP_FILES := propertyfile/propertyfile.cpp \
propertyfile/propertyitem.cpp \
propertyfile/propertyfactory.cpp
OBJ := $(patsubst %.cpp,$(OBJDIR)/%.o, $(CPP_FILES))
SRC := $(patsubst %.cpp,$(SRCDIR)/%.o, $(CPP_FILES))
ASM := $(patsubst %.cpp, $(OBJDIR)/$*.asm, $(CPP_FILES))
LIBS:=
TARGET:= libsupport.a
all: $(TARGET)
$(TARGET): $(OBJ)
@echo "Linking..."
@$(LNK) rvs $(TARGET) $(OBJ)
@cp $(TARGET) ../lib
@cp -r include ..
clean:
rm -f $(OBJ) $(ASM) $(TARGET)
-include $(patsubst %.cpp,$(OBJDIR)/%.d, $(CPP_FILES))
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(OBJDIR)/%.d
@mkdir -p `dirname $@`
$(CC) $(CXXFLAGS) -S $< -o $(OBJDIR)/$*.asm $(INCLUDE_PATHS)
$(CC) $(CXXFLAGS) -c $< -o $@ $(INCLUDE_PATHS)
$(OBJDIR)/%.d: $(SRCDIR)/%.cpp
$(CC) $(CXXFLAGS) -MM -MT $@ -MF $(OBJDIR)/$*.d -c $< $(INCLUDE_PATHS)
我希望这能帮助其他用户。我发现的所有示例要么非常简单,单独列出了多个文件,而不是规则的一部分,但没有真正解释它是如何工作的,要么非常复杂,我无法找到它如何帮助我。因此,最后我找到了如何编写此makefile的答案,要了解我的错误,请查看我标记为正确答案的帖子: 生成的makefile如下所示,为了完整起见,我将其发布在这里,包括头文件的依赖项。如果不需要,请删除ASM部分:
.SUFFIXES:
.SUFFIXES: .o .cpp
.SUFFIXES: .o .d
CC := g++
LNK:= ar
CXXFLAGS = -O2 -g -Wall -fmessage-length=0
OBJDIR:= obj
SRCDIR:= src
HDIR:= include
INCLUDE_PATHS:= -Iinclude -Iinclude/interfaces -Iinclude/support
CPP_FILES := propertyfile/propertyfile.cpp \
propertyfile/propertyitem.cpp \
propertyfile/propertyfactory.cpp
OBJ := $(patsubst %.cpp,$(OBJDIR)/%.o, $(CPP_FILES))
SRC := $(patsubst %.cpp,$(SRCDIR)/%.o, $(CPP_FILES))
ASM := $(patsubst %.cpp, $(OBJDIR)/$*.asm, $(CPP_FILES))
LIBS:=
TARGET:= libsupport.a
all: $(TARGET)
$(TARGET): $(OBJ)
@echo "Linking..."
@$(LNK) rvs $(TARGET) $(OBJ)
@cp $(TARGET) ../lib
@cp -r include ..
clean:
rm -f $(OBJ) $(ASM) $(TARGET)
-include $(patsubst %.cpp,$(OBJDIR)/%.d, $(CPP_FILES))
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(OBJDIR)/%.d
@mkdir -p `dirname $@`
$(CC) $(CXXFLAGS) -S $< -o $(OBJDIR)/$*.asm $(INCLUDE_PATHS)
$(CC) $(CXXFLAGS) -c $< -o $@ $(INCLUDE_PATHS)
$(OBJDIR)/%.d: $(SRCDIR)/%.cpp
$(CC) $(CXXFLAGS) -MM -MT $@ -MF $(OBJDIR)/$*.d -c $< $(INCLUDE_PATHS)
我希望这能帮助其他用户。我发现的所有示例要么非常简单,单独列出了多个文件,而不是规则的一部分,但没有真正解释它是如何工作的,要么太复杂了,我无法找到它如何帮助我。如果上面的内容不正确,实际上您有几个例子 首先你写我的错误是,我假设模式%.o匹配任何以.o结尾的模式,但它不匹配;那不是真的。该模式不匹配任何以.o结尾的字符串。但是,在目标端匹配的模式字符%在先决条件端被替换为相同的字符串。因此,如果您有一个目标obj/task.o,并且它与模式%.o匹配,那么手册称之为obj/task的stem将是obj/task,当前提条件为%.c时,这意味着make将查找一个前提条件obj/task.c。因为没有一个,make也不知道如何构建一个,所以该规则被丢弃,因为它不适用。在编写模式规则时,必须编写它们,以便只有名称的相同部分与模式字符%匹配。必须明确指定所有不相同的部分,包括目录 其次,$OBJ:$SRC规则确实不正确。该行表示每个对象文件都依赖于所有源文件,因此每当任何单个源文件发生更改时,所有对象文件都将重新编译。这并不是你想要的,如果这是你不需要做的:你可以只写一个简单的shell脚本。我不知道你的意思,因为规则是空的,它调用模式规则;调用模式规则时不需要这个。目标依赖于$OBJ,由于模式的原因,每个对象文件依赖于其源文件。你根本不需要这条线 第三,我不知道为什么您要尝试构造.asm文件,而不是直接从源代码编译到对象,但是如果您真的想要它们,那么创建一个单独的模式规则来构建它们会更干净,更像是:创建一个模式规则$OBJDIR/%.o:$OBJDIR/%.asm和一个规则$OBJDIR/%.asm:$SRCDIR/%.c。如果希望ASM文件是构建的产品,则应将其声明为“全部”或“类似”的先决条件,否则它们将作为中间文件删除
第四,使用basename之类的东西是不必要的。有很多自动生成变量可以替代。例如,$*扩展到stem,因此可以编写$OBJDIR/$*.asm。当然,如果你为ASM文件制定了一个单独的模式规则,你可以只使用$@或$,如果上面的内容不正确,你实际上会遇到一些问题 首先你写我的错误是,我假设模式%.o匹配任何以.o结尾的模式,但它不匹配;那不是真的。该模式不匹配任何以.o结尾的字符串。但是,在目标端匹配的模式字符%在先决条件端被替换为相同的字符串。因此,如果您有一个目标obj/task.o,并且它与模式%.o匹配,那么手册称之为obj/task的stem将是obj/task,当前提条件为%.c时,这意味着make将查找一个前提条件obj/task.c。因为没有一个,make也不知道如何构建一个,所以该规则被丢弃,因为它不适用。写作时 ng模式规则您必须编写它们,以便只有名称的相同部分与模式字符%匹配。必须明确指定所有不相同的部分,包括目录 其次,$OBJ:$SRC规则确实不正确。该行表示每个对象文件都依赖于所有源文件,因此每当任何单个源文件发生更改时,所有对象文件都将重新编译。这并不是你想要的,如果这是你不需要做的:你可以只写一个简单的shell脚本。我不知道你的意思,因为规则是空的,它调用模式规则;调用模式规则时不需要这个。目标依赖于$OBJ,由于模式的原因,每个对象文件依赖于其源文件。你根本不需要这条线 第三,我不知道为什么您要尝试构造.asm文件,而不是直接从源代码编译到对象,但是如果您真的想要它们,那么创建一个单独的模式规则来构建它们会更干净,更像是:创建一个模式规则$OBJDIR/%.o:$OBJDIR/%.asm和一个规则$OBJDIR/%.asm:$SRCDIR/%.c。如果希望ASM文件是构建的产品,则应将其声明为“全部”或“类似”的先决条件,否则它们将作为中间文件删除
第四,使用basename之类的东西是不必要的。有很多自动生成变量可以替代。例如,$*扩展到stem,因此可以编写$OBJDIR/$*.asm。当然,如果你为ASM文件制定一个单独的模式规则,你可以只使用$@或$Yeah,我同时发现了这一点,但这并不能解决问题的其余部分。你必须更改OBJ,使对象文件具有$OBJDIR前缀。您不是要求生成obj/task.o,而是要求只生成task.o。Make没有猜到你可能真的是指其他文件。如果要生成文件,那么目标文件名必须是该文件名。先决条件必须是文件名,没错。是的,经过多次修改,我终于发现了makefile的样子。不幸的是,我发现了很多例子,但都要么过于简单,要么过于复杂。我很惊讶,这样一个普通的东西在实际工作的示例中不容易找到。是的,我同时发现了这一点,但这并不能解决问题的其余部分。您必须更改OBJ,以便对象文件具有$OBJDIR前缀。您不是要求生成obj/task.o,而是要求只生成task.o。Make没有猜到你可能真的是指其他文件。如果要生成文件,那么目标文件名必须是该文件名。先决条件必须是文件名,没错。是的,经过多次修改,我终于发现了makefile的样子。不幸的是,我发现了很多例子,但都要么过于简单,要么过于复杂。我很惊讶,这样一个普通的东西不容易在实际工作的例子中找到。至少现在我了解了真正问题的一部分。对象文件位于obj目录中。当我把$OBJDIR/$OBJ作为依赖项时,它将扩展到OBJ/o1.oo2.o。。。虽然应该是obj/o1.o obj/o2.o…,但我必须在每个单独的文件上指定obj路径吗?至少现在我了解了真正问题的一部分。对象文件位于obj目录中。当我把$OBJDIR/$OBJ作为依赖项时,它将扩展到OBJ/o1.oo2.o。。。虽然它应该是obj/o1.o obj/o2.o…,但我必须在每个单独的文件上指定obj路径吗?感谢您对模式的解释。这真的帮了大忙。在您的示例中,有一个小错误,因为您在模式substation.c而不是.cpp中编写,但这是一个小问题。我留下的asm是这样的,因为我不想对此有单独的规则。我更喜欢生成asm输出,这样我就可以检查编译器到底在做什么大多数用户可以简单地删除它。如果我要创建一个单独的规则,我必须以单独的步骤编译到asm对象,这在这里没有意义。我现在用工作版本更新我上面的帖子。谢谢当然,你喜欢怎么做就怎么做。您的解决方案的问题是您显著增加了构建时间,因为您要两次运行大多数编译器工作。一旦程序集可用,几乎不需要将其转换为对象文件:大部分工作都在预处理、解析,尤其是优化以生成程序集。如果您想要程序集输出,最有效的方法是首先生成程序集,然后将程序集编译到目标文件中。感谢您对模式的解释。这真的帮了大忙。在您的示例中,有一个小错误,因为您在模式substation.c而不是.cpp中编写,但这是一个小问题。我留下的asm是这样的,因为我不想对此有单独的规则。我更喜欢生成asm输出,
这样我就可以检查编译器到底在做什么大多数用户可以简单地删除它。如果我要创建一个单独的规则,我必须以单独的步骤编译到asm对象,这在这里没有意义。我现在用工作版本更新我上面的帖子。谢谢当然,你喜欢怎么做就怎么做。您的解决方案的问题是您显著增加了构建时间,因为您要两次运行大多数编译器工作。一旦程序集可用,几乎不需要将其转换为对象文件:大部分工作都在预处理、解析,尤其是优化以生成程序集。如果需要程序集输出,最有效的方法是首先生成程序集,然后将程序集编译到对象文件中。
.SUFFIXES:
.SUFFIXES: .o .cpp
.SUFFIXES: .o .d
CC := g++
LNK:= ar
CXXFLAGS = -O2 -g -Wall -fmessage-length=0
OBJDIR:= obj
SRCDIR:= src
HDIR:= include
INCLUDE_PATHS:= -Iinclude -Iinclude/interfaces -Iinclude/support
CPP_FILES := propertyfile/propertyfile.cpp \
propertyfile/propertyitem.cpp \
propertyfile/propertyfactory.cpp
OBJ := $(patsubst %.cpp,$(OBJDIR)/%.o, $(CPP_FILES))
SRC := $(patsubst %.cpp,$(SRCDIR)/%.o, $(CPP_FILES))
ASM := $(patsubst %.cpp, $(OBJDIR)/$*.asm, $(CPP_FILES))
LIBS:=
TARGET:= libsupport.a
all: $(TARGET)
$(TARGET): $(OBJ)
@echo "Linking..."
@$(LNK) rvs $(TARGET) $(OBJ)
@cp $(TARGET) ../lib
@cp -r include ..
clean:
rm -f $(OBJ) $(ASM) $(TARGET)
-include $(patsubst %.cpp,$(OBJDIR)/%.d, $(CPP_FILES))
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(OBJDIR)/%.d
@mkdir -p `dirname $@`
$(CC) $(CXXFLAGS) -S $< -o $(OBJDIR)/$*.asm $(INCLUDE_PATHS)
$(CC) $(CXXFLAGS) -c $< -o $@ $(INCLUDE_PATHS)
$(OBJDIR)/%.d: $(SRCDIR)/%.cpp
$(CC) $(CXXFLAGS) -MM -MT $@ -MF $(OBJDIR)/$*.d -c $< $(INCLUDE_PATHS)
.SUFFIXES:
CXX := g++
CXXFLAGS := -O2 -g -Wall -fmessage-length=0
OBJDIR := obj
SRCDIR := src
TARGET := nohupshd
SRC := nohupshd.cpp task.cpp
DEP := src/task.h
LIBS :=
# ----
OBJ := $(patsubst %.cpp,$(OBJDIR)/%.o,$(SRC))
ASM := $(patsubst %.cpp,$(OBJDIR)/%.asm,$(SRC))
.PHONY: all clean
all: $(TARGET) $(ASM)
$(TARGET): $(OBJ)
$(CXX) -o $@ $^ $(LIBS)
clean:
rm -f $(OBJDIR)/* $(TARGET)
$(OBJDIR)/%.o : $(SRCDIR)/%.asm
$(CXX) $(CXXFLAGS) -c -x assembler-with-cpp $< -o $@
$(OBJDIR)/%.asm : $(SRCDIR)/%.cpp
$(CXX) $(CPPFLAGS) -S $< -o $@