0
votes

I am trying to build a dummy C project using GNU Make. I use the following rules to build the object files from the c files and the output from the object files :

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 $@

The output when I execute the target all is as follows :

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

The main.c source file has the following code :

#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;
}

The alpha.c source file has the following code :

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

Where $(OBJECTS) is the relative path of all the object files that are supposed to be generated and $(EXEC) and $(EXEOUT) are the outputs. The VPATH contains relative paths. All the needed prerequisites (.c and.h files) can be found among the paths in VPATH and in INCLUDES in the compilation command. That is the exact code I use to build this dummy project which contains only two .c files main.c and alpha.c and main.c uses alpha.c. When the source files are in the same folder as the makefile this dummy project builds, but when I put the source files in the src folder and create a obj folder for the object files to be generated in and an exe folder for the final output to be generated in previously mentioned error appears. What could be the reason for the previously mentioned error?

1
Welcome to Stack Overflow. Please look at our intro section, with special attention to the page on minimal complete examples. The code you have posted is not sufficient for us to reproduce the error; there are pieces missing, like $(RELATIVE_OBJDIR) and $(CEXT), so the flaw could be anywhere. If you reduce this makefile down to a minimal complete example, the source of the error will probably become obvious along the way, and if not then you will have a minimal complete example you can show us.Beta

1 Answers

1
votes

@Beta is right that it's generally a bad idea to dump a huge makefile into StackOverflow and ask someone to fix it. You should instead try to reduce the problem as much as possible.

However in this case, your problem is here:

OBJDIR                      :=.

OBJECTS                     :=./obj/main.o

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

So after all the variables have been expanded, you get these rules:

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

Well, when make tries to match the pattern ./%.o with the target to be built ./obj/main.o, the stem % will match obj/main. Then it will try to find %.c which resolves to obj/main.c, which doesn't exist.

You should be using the OBJDIR variable in your OBJECTS variable assignment, like:

OBJECTS                     :=$(OBJDIR)/main.o

then it will work.