Search code examples
c++makefilemingwlinker-errorsfltk

How to link against libraries when using MingW and makefiles


I downloaded and built FLTK (v. 1.3.4.1) using MingW and cmake which worked perfectly. However I am having problems properly linking against FLTK resulting in lots of undefined references during linking. I do not have MSYS or any other shell for Windows installed which means using the 'fltk-config' script is not an option.

My knowledge of makefiles is rather sparse and the following has been built using the official documentation and various internet sources.

CC=g++
FLTK_INC=C:/frameworks/fltk-1.3.4-1
FLTK_BIN=C:/frameworks/fltk-1.3.4-1/bin
CFLAGS=-std=c++11 -Wall -I$(FLTK_INC) -v
LDFLAGS=-L$(FLTK_BIN)/lib
LDLIBS=-lfltk
EXT=cc
SOURCES=$(wildcard src/*.$(EXT))
OBJECTS=$(SOURCES:.$(EXT)=.o)
EXECUTABLE=hello

all: $(SOURCES) $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
    $(CC) $(LDFLAGS) $(OBJECTS) -o $@

.$(EXT).o:
    $(CC) $(CFLAGS) $< -o $@

Is there something obviously wrong with this makefile or does the error lie somwehere else?


Solution

  • Is there something obviously wrong with this makefile or does the error lie somwehere else?

    There are two things wrong with this makefile.

    Thing 1

    LDFLAGS=-L$(FLTK_BIN)/lib
    LDLIBS=-lfltk
    

    You have conventional GNU Make settings of linkage options:

    LDFLAGS=-L$(FLTK_BIN)/lib
    

    $(LDFLAGS) should occur at an appropriate position in your linkage recipe to tell the linker that it should search in the directory $(FLTK_BIN)/lib for any libraries specified with -l option (before searching in its default directories).

    LDLIBS=-lfltk
    

    $(LDLIBS) should occur at an appropriate position in your linkage recipe to tell the linker that it should link the shared library libfltk.so or failing that, the static library libfltk.a. (On Windows, other extensions are accepted).

    Your linkage recipe:

    $(EXECUTABLE): $(OBJECTS)
        $(CC) $(LDFLAGS) $(OBJECTS) -o $@
    

    has $(LDFLAGS) at an appropriate position but does not have $(LDLIBS) anywhere. The linker therefore makes no attempt to link libfltk. That very likely explains the undefined reference errors that you refer to, although I can't be absolutely sure since you haven't revealed what they are.

    The linkage recipe ought to be:

    $(EXECUTABLE): $(OBJECTS)
        $(CC) $(LDFLAGS) $(OBJECTS) -o $@ $(LDLIBS)
    

    or more conventionally:

    $(EXECUTABLE): $(OBJECTS)
        $(CC) $(LDFLAGS) $^ -o $@ $(LDLIBS)
    

    Thing 2

    Your compile recipe:

    .$(EXT).o:
        $(CC) $(CFLAGS) $< -o $@
    

    is not actually a compile recipe. It is a compile-and-link recipe. gcc/g++ will always attempt to perform a linkage unless the commandline options include -c ( = compile only). Since the recipe (correctly) does not include any of the necessary linkage options - $(LDFLAGS), $(LDLIBS) - the premature attempted linkage fails and the build gets not further. The commandline you have logged as producing the linkage errors:

    g++ -std=c++14 -Wall -IC:/frameworks/fltk-1.3.4-1 -v src/hw.cc -o src/hw.o
    

    is a substitution instance of your "compile" recipe:

    $(CC) $(CFLAGS) $< -o $@
    

    and not of your linkage recipe:

    $(CC) $(LDFLAGS) $(OBJECTS) -o $@
    

    To correct the compile recipe, make it:

    $(CC) $(CFLAGS) $< -c -o $@
    

    The GNU Make documentation is good.