MAKEFILE:使用递归子文件夹搜索中的源文件时出现“没有规则来创建目标...”错误

问题描述 投票:0回答:1

我正在尝试构建一个 makefile,以便在 Linux 下编译一个在 Windows 上使用 Code::Blocks 编写的程序(因此,我没有可用的 makefile 可供查看)。

项目很大,源文件位于各个子目录中,所以我这样制作了我的makefile:

# Main project folder
MyProject_PATH := ~/MyProject/
# Main Source Folder
SRC_PATH := $(MyProject_PATH)src
# All Source subfolders 
SRC_DIRS := $(shell find $(SRC_PATH) -type d)

# - Output folders
OBJ_PATH := $(MyProject_PATH)LINUXmake/obj-arm
BIN_PATH := $(MyProject_PATH)LINUXmake/bin-arm
# - Final executable name 
EXE      := $(BIN_PATH)/MyProject-arm

# get all .c and .cpp files
SRC   := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.c) $(wildcard $(dir)/*.cpp))
# Define object files for each source file
OBJ := $(patsubst %.c,$(OBJ_PATH)/%.o,$(notdir $(SRC:.c=.o)))
OBJ := $(patsubst %.cpp,$(OBJ_PATH)/%.o,$(notdir $(OBJ:.cpp=.o)))

然后我有这些规则部分:

.PHONY: all show clean

# Rules for compiling .c files
%.o: %.c
    @echo "Compiling C file: $<"
    $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@

# Rules for compiling .cpp files
%.o: %.cpp
    @echo "Compiling C++ file: $<"
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@

# Rule to build the final target
$(EXE): $(OBJ)
    @echo "Linking objects to create target: $@"
    $(CXX) $(LDLIBS) $^ -o $@

# Rule to create output directories
$(shell mkdir -p $(OBJ_PATH) $(BIN_PATH))

# Rule to clean object files and the target
clean:
    $(RM) -r $(OBJ_PATH) $(BIN_PATH)

show:
    @printf "\nPaths: $(OBJ_PATH) $(BIN_PATH)\n"
    @printf "\nSource files:\n$(SRC)"
    @printf "\n\nObject files:\n$(OBJ)"
    @printf "\n\nCompiler:\n$(CC)"
    @printf "\n\nC++ Compiler:\n$(CXX)"
    @printf "\n\nC Flags:\n$(CFLAGS)"
    @printf "\n\nC++ Flags:\n$(CXXFLAGS)"
    @printf "\n\nInclude Flags:\n$(CPPFLAGS)"
    @printf "\n\nLinked Libraries:\n$(LDLIBS)"
    @echo   ""

但我总是收到此错误:

make: *** No rule to make target 'cKeyboard.o', needed by '/home/buster/MyProject/LINUXmake/bin-arm/MyProject'.  Stop.

如果我使用“show”目标,我会得到以下输出:

Paths: ~/MyProject/LINUXmake/obj-arm ~/MyProject/LINUXmake/bin-arm

Source files:
 /home/buster/MyProject/src/cKeyboard.cpp /home/buster/MyProject/src/GUI_MainForm.cpp /home/buster/MyProject/src/MyProject_bitmaps.cpp /home/buster/MyProject/src/CommManager.cpp /home/buster/MyProject/src/cMSX.cpp /home/buster/MyProject/src/fMainForm.cpp /home/buster/MyProject/src/MSX_PG.cpp /home/buster/MyProject/src/MsgManager.cpp  /home/buster/MyProject/src/ClassiEventi/cBaseObjWithEvents.cpp  /home/buster/MyProject/src/cMSXTool/cMSXTool.cpp  /home/buster/MyProject/src/Comm/X_OS_Socket.cpp /home/buster/MyProject/src/Comm/serialib.cpp /home/buster/MyProject/src/Comm/BBBSerial.cpp    /home/buster/MyProject/src/CustomControls/cCCDCalibration/cCCDCal.cpp  /home/buster/MyProject/src/CustomControls/TAntiAliasedGauge/TAntiAliasedGauge.cpp  /home/buster/MyProject/src/CustomControls/TGradientButton/wxGradientButton.cpp /home/buster/MyProject/src/CustomControls/TGradientButton/wxGradientSwitch.cpp  /home/buster/MyProject/src/CustomControls/TPacket/cPacchetto.cpp /home/buster/MyProject/src/CustomControls/TPacket/TPacket.cpp /home/buster/MyProject/src/CustomControls/TPacket/cSigaretta.cpp    /home/buster/MyProject/src/CustomControls/TScannerImage/TScannerImage.cpp /home/buster/MyProject/src/CustomControls/TScannerImage/cResampler.cpp /home/buster/MyProject/src/CustomControls/TScannerImage/resampler.cpp  /home/buster/MyProject/src/CustomControls/TSigaTollerance/TSigaTolerance.cpp  /home/buster/MyProject/src/CustomControls/wxActiveArea/wxActiveArea.cpp  /home/buster/MyProject/src/CustomControls/wxPanelSensorBar/wxPanelSensorBar.cpp  /home/buster/MyProject/src/CustomControls/wxPngAnimator/wxpnganimator.cpp  /home/buster/MyProject/src/GUI_MainformParts/GUI_XMLManager.cpp /home/buster/MyProject/src/GUI_MainformParts/GUI_MSXT.cpp /home/buster/MyProject/src/GUI_MainformParts/GUI_MSXT (2).cpp /home/buster/MyProject/src/GUI_MainformParts/GUI_UnusedControlEvents.cpp /home/buster/MyProject/src/GUI_MainformParts/GUI_GraphReader.cpp /home/buster/MyProject/src/GUI_MainformParts/GUI_TextBoxManagement.cpp /home/buster/MyProject/src/GUI_MainformParts/GUI_Charts.cpp /home/buster/MyProject/src/GUI_MainformParts/GUI_FileBrowser.cpp /home/buster/MyProject/src/GUI_MainformParts/GUI_RealTimeClock.cpp /home/buster/MyProject/src/GUI_MainformParts/GUI_SystemPages.cpp /home/buster/MyProject/src/GUI_MainformParts/GUI_KeysManagement.cpp /home/buster/MyProject/src/GUI_MainformParts/_DEBUG_STUFFS.cpp /home/buster/MyProject/src/I2C/24cXX.c /home/buster/MyProject/src/I2C/24cXX.cpp /home/buster/MyProject/src/I2C/i2cfunc.cpp  /home/buster/MyProject/src/MsxData/MsxGraph.cpp  /home/buster/MyProject/src/MSX_ClassParts/MSX_SendCommands.cpp /home/buster/MyProject/src/MSX_ClassParts/cTendenzaScarti.cpp /home/buster/MyProject/src/MSX_ClassParts/CCD_Averages.cpp /home/buster/MyProject/src/MSX_ClassParts/MSX_SalvaGrafici.cpp  /home/buster/MyProject/src/Utilities/Utilities.cpp /home/buster/MyProject/src/Utilities/StringUtils.cpp /home/buster/MyProject/src/Utilities/cGraphFile.cpp

Object files:
cKeyboard.o GUI_MainForm.o MyProject_bitmaps.o CommManager.o cMSX.o fMainForm.o MSX_PG.o MsgManager.o cBaseObjWithEvents.o cMSXTool.o X_OS_Socket.o serialib.o BBBSerial.o cCCDCal.o TAntiAliasedGauge.o wxGradientButton.o wxGradientSwitch.o cPacchetto.o TPacket.o cSigaretta.o TScannerImage.o cResampler.o resampler.o TSigaTolerance.o wxActiveArea.o wxPanelSensorBar.o wxpnganimator.o GUI_XMLManager.o GUI_MSXT.o GUI_MSXT (2).o GUI_UnusedControlEvents.o GUI_GraphReader.o GUI_TextBoxManagement.o GUI_Charts.o GUI_FileBrowser.o GUI_RealTimeClock.o GUI_SystemPages.o GUI_KeysManagement.o _DEBUG_STUFFS.o 24cXX.o 24cXX.o i2cfunc.o MsxGraph.o MSX_SendCommands.o cTendenzaScarti.o CCD_Averages.o MSX_SalvaGrafici.o Utilities.o StringUtils.o cGraphFile.o

我显然错过了一些东西,但我无法排序。 我该怎么办?

gcc makefile
1个回答
0
投票

此模式规则:

%.o: %.cpp
    @echo "Compiling C file: $<"
    $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
    

表示:对于匹配

<SOMETHING>.c
的文件,将文件
<SOMETHING>.o
制作为 运行每行的扩展:

    @echo "Compiling C file: $<"
    $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
    

作为 shell 命令。

您的第一个源文件,如您的

make show
输出所示,是:

/home/buster/MyProject/src/cKeyboard.cpp

因此模式规则告诉

make
如何制作:

/home/buster/MyProject/src/cKeyboard.o

但是您的

$(EXE)
目标所需的第一个目标文件,也如图所示 通过
make show
,是:

cKeyboard.o

(=

./cKeyboard.o
) 并且没有规则可以做到这一点。此外, 你不想成功。您要制作的文件:

/home/buster/MyProject/src/cKeyboard.cpp

显然是:

$(OBJ_PATH)/cKeyboard.o 
    = ~/MyProject/LINUXmake/obj-arm 
    =  /home/buster/MyProject/LINUXmake/obj-arm/cKeyboard.o
    

所以至少实现这一点的模式规则是:

$(OBJ_PATH)/%.o: $(SRC_PATH)/%.cpp
    @echo "Compiling C file: $<"
    $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
    

显然,同样的错误会影响

%.o: %.c
的规则。

但是,你为什么要生成:

$(OBJ) = cKeyboard.o ...

而不是你需要的:

$(OBJ) = ~/MyProject/LINUXmake/obj-arm/cKeyboard.o ...

?这让我们想到:

OBJ := $(patsubst %.c,$(OBJ_PATH)/%.o,$(notdir $(SRC:.c=.o)))
OBJ := $(patsubst %.cpp,$(OBJ_PATH)/%.o,$(notdir $(OBJ:.cpp=.o)))

为了简单起见,我们假设:

/home/buster/MyProject/src/cKeyboard.cpp

是唯一的源文件。那么第一个

OBJ
作业意味着:找到展开式中的所有单词:

$(notdir $(SRC:.c=.o))
    = $(notdir $(/home/buster/MyProject/src/cKeyboard.cpp:.c=.o)
    = $(notdir /home/buster/MyProject/src/cKeyboard.cpp)    # Because there was no `.c=.o` substitution
    = cKeyboard.cpp
    

然后替换结果中的任何单词:

cKeyboard.cpp
    

<SOMETHING>.c
$(OBJ_PATH)/<SOMETHING>.o
相匹配。里面没有字:

cKeyboard.cpp

那场比赛

<SOMETHING>.c
,所以第一个
OBJ
作业的最终结果 仍然存在

cKeyboard.cpp

第二个

OBJ
作业的意思是:找到以下位置的所有单词:

$(notdir $(OBJ:.cpp=.o))
    = $(notdir $(cKeyboard.cpp:.cpp=.o)
    = $(notdir cKeyboard.o)
    = cKeyboard.o
    

然后替换结果中的任何单词:

cKeyboard.o

<SOMETHING>.cpp
$(OBJ_PATH)/<SOMETHING>.o
相匹配。没有 中的单词:

cKeyboard.o

匹配

<SOMETHING>.cpp
,所以第二个
OBJ
作业的最终结果 剩下:

cKeyboard.o

错误。

获得正确结果的一种方法是:

COBJ := $(patsubst %.c,$(OBJ_PATH)/%.o,$(notdir $(filter %.c,$(SRC))))
CXXOBJ := $(patsubst %.cpp,$(OBJ_PATH)/%.o,$(notdir $(filter %.cpp,$(SRC))))
OBJ := $(COBJ) $(CXXOBJ)

顺便说一句,我建议您通常不要采取这种“抓住任何东西”的方法来 提供 make 应考虑并指定的源文件 他们分别:

SRCS :=  $(MyProject_PATH)src/cKeyboard.cpp \
        $(MyProject_PATH)src/GUI_MainForm.cpp \
        ...

即使这看起来很艰难且乏味,如果你起步较晚的话。完成最初繁琐的列表后,添加新文件或删除多余的文件
很容易。构建系统应该明确并清楚地显示
对于维护人员来说,到底应该存在哪些源文件,而不是构建
任何程序可能由某些人捕获的任何源文件产生
某种拖网 - 或者未能实现这一目标。

© www.soinside.com 2019 - 2024. All rights reserved.