-1

I am currently learning c++. I wrote the below Makefile to compile my program:

NAME    =   test
CC  =   c++
CFLAGS  =   -Wall -Wextra -Werror -std=c++98
SRCS    =   test.cpp
OBJS    =   ${SRCS:.cpp=.o}

all:        ${NAME}

%.o:        ${SRCS}
        ${CC} ${CFLAGS} -c $< -o $@

${NAME}:    ${OBJS}
        ${CC} ${CFLAGS} ${OBJS} -o ${NAME}

clean:      
        rm ${OBJS}

fclean:     clean
        rm ${NAME}

re:     fclean
        all
.PHONY:     all clean fclean re .c.o 

The Makefile works fine until I use the touch test.cpp command to see if it relinks as I intended to.

My Makefile then first recompiles test.cpp as it should, then it tries to link Makefile.o and output a file Makefile.

Below is the output display on my terminal:

c++ -Wall -Wextra -Werror -std=c++98 -c test.cpp -o Makefile.o
c++   Makefile.o   -o Makefile
rm Makefile.o
Makefile:1: warning: NUL character seen; rest of line ignored
Makefile:1: *** missing separator.  Stop.

On top of that, my entire Makefile gets replaced by random strings and characters (not really random but I have no idea where are they from, and a whole bunch of NUL characters), here is a screenshot of what it looks like:

enter image description here

I code under WSL2, Windows 11, Ubuntu 20.04, in VSCode.

I would really appreciate some idea, thanks!

I solved the problem by removing the %.o rule, so I just compiled with ${CC} ${CFALGS} ${SRCS} -o ${NAME}.

But I still want to know why compiling to object files first caused the problem

Marcus
  • 9
  • 1

1 Answers1

1

You guessed correctly that the problem is in the %.o rule. Look:

SRCS    =   test.cpp
...
%.o:        ${SRCS}
    ${CC} ${CFLAGS} -c $< -o $@

That pattern rule tells Make that the way to build any object file is to compile test.cpp. And Make always checks to see whether the makefile can be rebuilt, and sure enough, it can be, by compiling test.cpp and linking the resulting object file. So you wind up with a makefile which is not a makefile, it is in fact an executable binary file which ought to have been named test (which is a bad name, but that's another story).

The fix is easy:

%.o: %.cpp
    ${CC} ${CFLAGS} -c $< -o $@
Beta
  • 96,650
  • 16
  • 149
  • 150
  • I see, if I understood well, the `%` character here means compile any .cpp file to any corresponding .o file right? – Marcus Jun 21 '23 at 16:28
  • @Marcus: Not quite. See [the manual](https://www.gnu.org/software/make/manual/make.html#Pattern-Rules). – Beta Jun 21 '23 at 23:19