简体   繁体   English

C ++ Makefile错误-没有使目标'%.cpp'的规则

[英]C++ Makefile error - No rule to make target '%.cpp'

Good day, I am running through a tutorial to write my own makefiles, I found the tutorial here: 美好的一天,我正在运行一个教程来编写自己的makefile,在这里找到了该教程:

http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/ http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/

I know this tutorial is for C makefiles, however I believe that the similiarities between C and C++ would mean there is little difference in how the makefiles function (for instance, I am using g++ rather than gcc). 我知道本教程适用于C makefile,但是我相信C和C ++之间的相似之处意味着makefile的功能几乎没有区别(例如,我使用g ++而不是gcc)。 I hope my assumption on this point isn't a factor, since each of the previous 4 tutorials appear to have worked just fine. 我希望我对这一点的假设不是一个因素,因为前4个教程中的每一个似乎都工作得很好。

When running through Makefile 5 in the tutorial, I am getting an error regarding the construction of the object files from the .cpp files: 在本教程中遍历Makefile 5时,从.cpp文件构造目标文件时出现错误:

make: *** No rule to make target '%.cpp', needed by 'obj'. Stop.

I cannot seem to figure out why this is happening, very confusing and frustrating as I feel like this shouldn't be happening. 我似乎无法弄清楚为什么会这样,非常令人困惑和沮丧,因为我觉得这不应该发生。 I include my full Makefile below, any assistance would be greatly appreciated: 我将完整的Makefile包含在下面,非常感谢您的协助:

 # Example Makefile                                                                                                                                                                                             
 # ----------------
 # Please remember to turn off the vim option: 'expandtab' so that tabs are 
 # actually displayed as tabs (do so like this - :set noexpandtab )
 #

 # This file specifies dependencies, which means that the two c++ files must
 # be compiled before the executable is built

 # ------------------
 # Makefile Constants
 # ------------------

 # Directory constants
 IDIR =../include  # Specifies location of include directory
 ODIR =obj        # Specifies location of object directory
 LDIR =../lib      # Specifies location of library directory

 LIBS=-lm  # ?

 # Options constants
 CC=g++            # Specifies the specific C compiler to use, g++ specifies C++ compiler
 CFLAGS=-I$(IDIR)  # List of flags to pass to compilation command

 # Dependency Constants
 DEP_FILES=helloMake.h                      # Specifies dependency files
 DEPS=$(patsubst %,$(IDIR)/%,$(DEP_FILES))  # Specifies path to dependencies and dependency files

 # Object constants
 OBJ_FILES=helloMake.o helloFunc.o         # Specify object files
 OBJ=$(patsubst %,$(ODIR)/%,$(OBJ_FILES))  # Specifies path to objects and object files


 # -----------
 # Compilation
 # -----------

 # Specify rules to make object files
 $(ODIR)/%.o: %.cpp $(DEPS)       # Specifies that .o files depend on the .cpp version of the file and the .h files included in the DEPS macro
     $(CC) -c -o $@ $< $(CFLAGS)  # The -c flag says to generate the object file, the -o $@ says to put the output of the compilation in the
                                  # file named on the left side of the : the $< is the first item in the dependencies list

 # Specify rules to make target executable
 helloMake: $(OBJ)                     # Target : Dependencies
     $(CC) -o $@ $^ $(CFLAGS) $(LIBS)  # This is the actual compilation command

 .PHONY: clean  # Prevent the make command from attempting to do something with a file named 'clean'

 # Specify rules to clean the object files
 clean:
     rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~  # Removes all compiled object files

This "simple" tutorial unfortunately promotes bad practices. 不幸的是,此“简单”教程会提倡不良做法。

Basically, you first need a correct C Makefile: 基本上,您首先需要一个正确的C Makefile:

# Specify the final target name
EXE := helloMake

# Specify the source files
# Effectively list all source files in the current directory
SRC := $(wildcard *.c)

# From the source file list, get the corresponding object file list
# This is a clearer syntax for $(patsubst %.c,%.o,$(SRC))
OBJ := $(SRC:.c=.o)

# From the object file list, get the dependency file list to handle automatic
# recompilation when a header file is modified
DEP := $(OBJ:.o=.d)

# Specify preprocessor flags (this is a built-in variable)
CPPFLAGS := -I../include
# Required flags to enable the automatic dependency generation by the compiler
CPPFLAGS += -MMD -MP

# Specify compiler flags (this is a built-in variable)
# Here some basic warning flags
CFLAGS := -Wall -W -pedantic

# Specify linker flags (this is a built-in variable)
LDFLAGS := -L../lib

# Specify linker libraries (this is a built-in variable)
# m is the maths library
LDLIBS := -lm

# Tell make that these target are not real files
.PHONY: all clean

# Now the standard primary rule
all: $(EXE)

# How do we make $(EXE) ? Remember the recipe describe the linking phase
$(EXE): $(OBJ)
    $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@

# Let's clean up the mess
clean:
    $(RM) $(EXE) $(OBJ) $(DEP)

# Don't forget to include the dependency files to let make know when to recompile
-include $(DEP)

Then you need to know the difference between a C Makefile and a C++ Makefile: 然后,您需要了解C Makefile和C ++ Makefile之间的区别:

  • Use $(CXX) instead of $(CC) , 使用$(CXX)代替$(CC)
  • Use $(CXXFLAGS) instead of $(CFLAGS) , 使用$(CXXFLAGS)代替$(CFLAGS)
  • Use .cpp instead of .c . 使用.cpp而不是.c

And you're done. 这样就完成了。

# Specify the final target name
EXE := helloMake

# Specify the source files
# Effectively list all source files in the current directory
SRC := $(wildcard *.cpp)

# From the source file list, get the corresponding object file list
# This is a clearer syntax for $(patsubst %.cpp,%.o,$(SRC))
OBJ := $(SRC:.cpp=.o)

# From the object file list, get the dependency file list to handle automatic
# recompilation when a header file is modified
DEP := $(OBJ:.o=.d)

# Specify preprocessor flags (this is a built-in variable)
CPPFLAGS := -I../include
# Required flags to enable the automatic dependency generation by the compiler
CPPFLAGS += -MMD -MP

# Specify compiler flags (this is a built-in variable)
# Here some basic warning flags
CXXFLAGS := -Wall -W -pedantic

# Specify linker flags (this is a built-in variable)
LDFLAGS := -L../lib

# Specify linker libraries (this is a built-in variable)
# m is the maths library
LDLIBS := -lm

# Tell make that these target are not real files
.PHONY: all clean

# Now the standard primary rule
all: $(EXE)

# How do we make $(EXE) ? Remember the recipe describe the linking phase
$(EXE): $(OBJ)
    $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@

# Let's clean up the mess
clean:
    $(RM) $(EXE) $(OBJ) $(DEP)

# Don't forget to include the dependency files to let make know when to recompile
-include $(DEP)

Edit: To be able to relocate the build files ( .o and .d files), you need a few adjustments: 编辑:为了能够重新定位生成文件( .o.d文件),您需要进行一些调整:

# Specify the final target name
EXE := helloMake

# Specify the source files
# Effectively list all source files in the current directory
SRC := $(wildcard *.cpp)

# Specify where to put the build temporary files
BLD := obj

# From the source file list, get the corresponding object file list
# This is a clearer syntax for $(patsubst %.cpp,$(BLD)/%.o,$(SRC))
OBJ := $(SRC:%.cpp=$(BLD)/%.o)

# From the object file list, get the dependency file list to handle automatic
# recompilation when a header file is modified
DEP := $(OBJ:.o=.d)

# Specify preprocessor flags (this is a built-in variable)
CPPFLAGS := -I../include
# Required flags to enable the automatic dependency generation by the compiler
CPPFLAGS += -MMD -MP

# Specify compiler flags (this is a built-in variable)
# Here some basic warning flags
CXXFLAGS := -Wall -W -pedantic

# Specify linker flags (this is a built-in variable)
LDFLAGS := -L../lib

# Specify linker libraries (this is a built-in variable)
# m is the maths library
LDLIBS := -lm

# Tell make that these target are not real files
.PHONY: all clean

# Now the standard primary rule
all: $(EXE)

# How do we make $(EXE) ? Remember the recipe describe the linking phase
$(EXE): $(OBJ)
    $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@

# The build directory is custom so we need to tell make how to do it
# The build directory must exist before trying to compile
$(BLD)/%.o: %.cpp | $(BLD)
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ -c $<

# Simple rule to create the build directory if needed
$(BLD):
    mkdir $@

# Let's clean up the mess, we can just remove the build directory alonside the executable
clean:
    $(RM) -r $(BLD) $(EXE)

# Don't forget to include the dependency files to let make know when to recompile
-include $(DEP)

The % syntax is not standard make but an extended feature provided by eg GNU make (otherwise, you'd have to write particular rules for every source file or use something like the autotools that generate huge (but portable) Makefile s). %语法不是标准的make而是GNU make提供的扩展功能(否则,您必须为每个源文件编写特定的规则,或者使用诸如autotools类的autotools来生成庞大 (但可移植)的Makefile )。 So, you should make sure you're using a make utility supporting this. 因此,您应该确保使用支持此功能的make实用程序。 If that's not the problem, are you sure you actually HAVE *.cpp files in your current directory? 如果那不是问题,那么您确定您当前目录中确实有*.cpp文件吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM