Home > other >  Easy gnu make makefile rule to build of GCC executable from multiple source files
Easy gnu make makefile rule to build of GCC executable from multiple source files

Time:11-02

I'm trying to make a simple as possible make file that uses the math library (fmax below, the rest is C cruft for this examlpe):

easy.c:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main(int argc, const char *argv[]) {
  double x=atof(argv[1]);
  double y=atof(argv[2]);
  double z=fmax(x,y);
  printf("max(%f,%f)=%f\n",x,y,z);
  return 0;
}

Makefile:

CFLAGS=-g
LDFLAGS=-lm

easy : easy.c

However this creates a link error (missing fmax). This is because make places the LDFLAGS first in the compile line:

 > make easy
cc -g  -lm  easy.c   -o easy
/usr/bin/ld: /tmp/ccmN5G9c.o: in function `main':
/home/user/projects/easy/easy.c:8: undefined reference to `fmax'
collect2: error: ld returned 1 exit status
make: *** [<builtin>: easy] Error 1

Of course, if I explicitly put the LDFLAGS at the end using an explicit rule, it works:

CFLAGS=-g
LDFLAGS=-lm

easy : easy.c
    $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)

Of course, understanding the Makefile is not nearly so easy now. Does anyone have a reason why the default rule does not put the link line at the end? Or is there an "easy" make that does allow a newcomer to link a number of source files into one executable (no lingering .o files)?

CodePudding user response:

You should be using LDLIBS not LDFLAGS. LDFLAGS is for linker flags (such as -L). LDLIBS is for linker libraries (such as -lm).

If you investigate the default rules (make -pf/dev/null) you'll find this one:

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

%: %.o
#  recipe to execute (built-in):
        $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@

(Ignore LOADLIBES as that's a deprecated name). Also see the documentation for LDLIBS and LDFLAGS.

  • Related