Home > Software design >  Compiling a minimal C program with implicit rules using Make
Compiling a minimal C program with implicit rules using Make

Time:06-02

This article shows the following example for compiling a minimal C program with implicit rules using make.

CC = gcc
CFLAGS = -g

blah: blah.o

blah.c:
    echo "int main() { return 0; }" > blah.c

clean:
    rm -f blah*

When I attempt to run this using make blah it seems to work fine and outputs an executable with the following being logged in standard output:

$ make blah
echo "int main() { return 0; }" > blah.c
gcc -g -c -o blah.o blah.c
gcc blah.o -o blah

I tried to adapt this for a minimal C program, and came up with the following Makefile:

blah: blah.o

blah.cc:
    echo "#include<iostream>\nint main() { std::cout << 123 << std::endl; }" >> blah.cc

clean:
    rm -f blah*

When I try `make blah, I run into an error:

echo "#include<iostream>\nint main() { std::cout << 123 << std::endl; }" >> blah.cc
g      -c -o blah.o blah.cc
cc   blah.o   -o blah
/usr/bin/ld: blah.o: warning: relocation against `_ZSt4cout' in read-only section `.text'
/usr/bin/ld: blah.o: in function `main':
blah.cc:(.text 0x10): undefined reference to `std::cout'
/usr/bin/ld: blah.cc:(.text 0x18): undefined reference to `std::ostream::operator<<(int)'
/usr/bin/ld: blah.cc:(.text 0x1f): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)'
/usr/bin/ld: blah.cc:(.text 0x2a): undefined reference to `std::ostream::operator<<(std::ostream& (*)(std::ostream&))'
/usr/bin/ld: blah.o: in function `__static_initialization_and_destruction_0(int, int)':
blah.cc:(.text 0x61): undefined reference to `std::ios_base::Init::Init()'
/usr/bin/ld: blah.cc:(.text 0x7c): undefined reference to `std::ios_base::Init::~Init()'
/usr/bin/ld: warning: creating DT_TEXTREL in a PIE
collect2: error: ld returned 1 exit status
make: *** [<builtin>: blah] Error 1

It seems to me that make is still running a cc command, which I suspect is why the error occurs.

Why is this happening and how can I fix it?

CodePudding user response:

On my system, the implicit rule for producing programs is:

%: %.o
        $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@

where

LINK.o = $(CC) $(LDFLAGS) $(TARGET_ARCH)

Check for yourself with make -np -f/dev/null.

You can either solve the problem by changing LINK.o to use $(CXX), or adding a recipe to the blah rule.

CodePudding user response:

C object files need to be linked with cc while C objects files need to be linked with c if you expect all the required libs to automatically included. Since the name for both is the same there can only be one automatic rule to link a binary. The default rule is to link C object files.

You can set CC = $(CXX) to change what the default rule uses to link.

  • Related