【问题标题】:No rule to make target error output while building C project using GNU Make使用 GNU Make 构建 C 项目时没有规则输出目标错误
【发布时间】:2020-11-17 15:57:58
【问题描述】:

我正在尝试使用 GNU Make 构建一个虚拟 C 项目。我使用以下规则从 c 文件和目标文件的输出构建目标文件:

AT := @

#Initial tools to get the absolute paths.
TOOLSDIR                    := ./tools/bin
SHELL                       := $(TOOLSDIR)/sh
CYGPATH                     := $(TOOLSDIR)/cygpath

# Defining used tools
TOOLSDIR                    := $(shell $(CYGPATH) -am "$(TOOLSDIR)")
SCRIPTDIR                   := $(shell $(CYGPATH) -am "$(SCRIPTDIR)")
LIBDIR                      := $(shell $(CYGPATH) -am "$(LIBDIR)")

#Defining Env Variable responsible for Removing non-ansi characters in error output
LC_ALL=C

SHELL                       := $(shell $(CYGPATH) -am "$(SHELL)")
CYGPATH                     := $(shell $(CYGPATH) -am "$(CYGPATH)")
TEST                        := $(shell $(CYGPATH) -am "$(TOOLSDIR)/test")
RM                          := $(shell $(CYGPATH) -am "$(TOOLSDIR)/rm") -f
PERL                        := $(shell $(CYGPATH) -am "$(TOOLSDIR)/perl")
FIND                        := $(shell $(CYGPATH) -am "$(TOOLSDIR)/find")
MKDIR                       := $(shell $(CYGPATH) -am "$(TOOLSDIR)/mkdir")

PERL5LIB                    := $(LIBDIR)/perl5/site_perl/5.14/x86_64-cygwin-threads;$(LIBDIR)/perl5/site_perl/5.14;$(LIBDIR)/perl5/5.14/x86_64-cygwin-threads;$(LIBDIR)/perl5/5.14

# Defining perl script to convert dependencies genereted by the compiler to unix path
FIXDEPS_SCRIPT              := "$(SCRIPTDIR)/fixdeps.pl"
ZAPEXEC_SCRIPT              := "$(SCRIPTDIR)/ZAP_Command.pl"

DEPFIX                      := $(PERL) $(FIXDEPS_SCRIPT)
ZAPEXE                      := $(PERL) $(ZAPEXEC_SCRIPT)
CREATE_IAR_PROJ             := $(PERL) $(IARWKSP_SCRIPT)

COMP_DIR                    :=C:\ghs\comp_201355

OBJDIR                      :=.

CC                          := "$(COMP_DIR)/ccrh850.exe"
AS                          := "$(COMP_DIR)/ccrh850.exe"
LD                          := "$(COMP_DIR)/ccrh580.exe"
GSREC                       := "$(COMP_DIR)/gsrec.exe"
GMEM                        := "$(COMP_DIR)/gmemfile.exe"

CEXT                        :=c
CCEXT                       :=C
ASMEXTC                     := S
ASMEXTS                     := s
ASMEXT                      := 850
ASMEXT_DEFAULT              := asm
DBGEXT                      := dla
DBGEXT_DEFAULT              := dnm 
OBJEXT                      := o
EXEEXT                      := elf
LSTEXT                      := lst
DEPEXT                      := dd
INCOPT                      := -I

EXEMAP                      := ./exe/PROJECT_NAME.map

CFLAGS                      :=-c -G  -Onone  -no_callt -sda=all -large_sda -reserve_r2 -Wundef --short_enum -dual_debug \
-delete -preprocess_assembly_files --no_wrap_diagnostics -registermode=32 -keeptempfiles -prepare_dispose -ansi  \
-full_debug_info -noobj -Wimplicit-int -Wshadow -Wtrigraphs -inline_prologue -DOS_MEMMAP=0 -DOS_MULTICORE=OS_SINGLE \
-DOS_USE_CLZ_QUEUE_ALGORITHM=1 -DOS_DEVELOPMENT_SANITY_CHECKS=0 -DOS_KERNEL_TYPE=OS_FUNCTION_CALL -DOS_USE_TRACE=0 -MD \
-DAUTOSAR_USED -DRENESAS  -DF1K   -DR7F701583xAFP --long_long  -cpu=rh850 -DTS_ARCH_FAMILY=TS_RH850 \
-DTS_ARCH_DERIVATE=TS_RH850F1L -DRH850F1L=1 -DOS_CPU=OS_RH850F1L -DOS_TOOL=OS_ghs -DOS_ARCH=OS_RH850

VPATH                       :=./ ./obj ./src ./exe

INCLUDES                    :=-I"./" -I"./obj" -I"./src" -I"./exe"
OBJECTS                     :=./obj/main.o

.PHONY: all release debug

EXEC                        := ./exe/PROJECT_NAME.hex
EXEOUT                      := ./exe/PROJECT_NAME.out
    
all: debug release

release: $(EXEC)
debug: release

$(EXEC): $(EXEOUT)
    @echo '************************************'
    @echo 'Using GSREC to Convert .out to .hex'
    $(AT)$(GSREC) -o$(EXEC) $(EXEOUT)
    @echo 'Generation Done'
    @echo '************************************'

$(EXEOUT): $(OBJECTS)
    @echo '************************************'
    @echo 'Building .out file'
    @echo $(EXEOUT)
    $(AT)$(CC) $(LDFLAGS) -o $(EXEOUT) $(OBJECTS)
    @echo '************************************'

$(OBJDIR)/%.$(OBJEXT): %.$(CEXT)
    @echo 'Compiling: $<'
    $(AT)$(CC) $(CFLAGS) $(INCLUDES) -filetype.c $(shell $(CYGPATH) -am "$<")  -o $@

我执行目标all时的输出如下:

make: *** No rule to make target 'obj/main.o', needed by 'exe/PROJECT_NAME.out'.  Stop.

main.c 源文件代码如下:

#include <stdio.h>
#include <stdlib.h>
#include "alpha.c"

void second(void);
int main()
{
  printf("Second module, I send you greetings!n");
  second();
  return 0;
}

alpha.c 源文件的代码如下:

#include <stdio.h>
void second(void)
{
  puts("Glad to be here!");
}

其中$(OBJECTS) 是应该生成的所有目标文件的相对路径,$(EXEC)$(EXEOUT) 是输出。 VPATH 包含相对路径。所有需要的先决条件(.c 和.h 文件)都可以在编译命令的VPATHINCLUDES 的路径中找到。这就是我用来构建这个虚拟项目的确切代码,它只包含两个 .c 文件 ma​​in.calpha.c ma​​in.c 使用 alpha.c。当源文件与这个虚拟项目构建的 makefile 位于同一文件夹中时,但是当我将源文件放在 src 文件夹中并创建一个 obj 文件夹用于生成目标文件,并出现 exe 文件夹用于生成上述错误中的最终输出。前面提到的错误可能是什么原因?

【问题讨论】:

  • 欢迎来到 Stack Overflow。请查看我们的intro section,特别注意minimal complete examples 上的页面。您发布的代码不足以让我们重现错误;缺少部分,例如$(RELATIVE_OBJDIR)$(CEXT),因此缺陷可能在任何地方。如果您将此 makefile 缩减为一个最小的完整示例,那么错误的来源可能会在此过程中变得明显,如果不是,那么您将有一个可以向我们展示的最小完整示例。

标签: makefile gnu-make


【解决方案1】:

@Beta 是正确的,将一个巨大的 makefile 转储到 StackOverflow 并请人修复它通常是一个坏主意。相反,您应该尽量减少问题。

但是在这种情况下,您的问题就在这里:

OBJDIR                      :=.

OBJECTS                     :=./obj/main.o

$(EXEOUT): $(OBJECTS)
    ...
$(OBJDIR)/%.$(OBJEXT): %.$(CEXT)
    ...

所以在所有变量都展开之后,你得到了这些规则:

./exe/PROJECT_NAME.out: ./obj/main.o
    ...
./%.o: %.c
    ...

好吧,当 make 尝试将模式 ./%.o 与要构建的目标 ./obj/main.o 匹配时,主干 % 将匹配 obj/main。然后它会尝试找到解析为obj/main.c%.c,而obj/main.c并不存在。

您应该在OBJECTS 变量赋值中使用OBJDIR 变量,例如:

OBJECTS                     :=$(OBJDIR)/main.o

然后它会工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-10
    • 1970-01-01
    • 1970-01-01
    • 2014-06-13
    • 2016-12-17
    • 2016-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多