Search code examples
cgccaudiomakefilestatic-libraries

GNU Make gcc, order of options


I'm trying to figure out what way make is processing options on a gcc command:

I'm rebuilding one of Richard Dobson's programs to convert a soundfile to float, and it requires linking a static library which is living in $HOME/.local/lib

the project builds no problem if I run gcc -Wl,-rpath=$HOME/.local/lib -lm -o sf2float sf2float.c -lportsf

There are a couple of really useful posts elsewhere on stack exchange and also https://nullprogram.com/blog/2017/06/19/

I'd really like to figure out how to run this command from within a makefile.

I've tried a few different variations of the following makefile:

SHELL=bash

CC = gcc
CFLAGS = -Wall
LDFLAGS = -Wl,-rpath=$$HOME/.local/lib -lm -lportsf

OBJECTS = sf2float.o
BINARY = sf2float

all: sf2float

example: $(OBJECTS)
    $(CC) $(CFLAGS) $(OBJECTS) -o $(BINARY) $(LDFLAGS)

clean:
    rm -f $(BINARY) $(OBJECTS)

Which returns a slightly different variation of order of the compiler options, and then a bunch of errors after not finding the static library:

gcc -Wl,-rpath=$HOME/.local/lib -lm -lportsf  sf2float.o   -o sf2float
/usr/bin/ld: sf2float.o: in function `main':
sf2float.c:(.text+0x64): undefined reference to `psf_init'
/usr/bin/ld: sf2float.c:(.text+0x9d): undefined reference to `psf_sndOpen'
/usr/bin/ld: sf2float.c:(.text+0xfd): undefined reference to `psf_getFormatExt'
/usr/bin/ld: sf2float.c:(.text+0x15b): undefined reference to `psf_sndCreate'
/usr/bin/ld: sf2float.c:(.text+0x210): undefined reference to `psf_sndReadFloatFrames'
/usr/bin/ld: sf2float.c:(.text+0x23b): undefined reference to `psf_sndWriteFloatFrames'
/usr/bin/ld: sf2float.c:(.text+0x268): undefined reference to `psf_sndReadFloatFrames'
/usr/bin/ld: sf2float.c:(.text+0x2c7): undefined reference to `psf_sndReadPeaks'
/usr/bin/ld: sf2float.c:(.text+0x38f): undefined reference to `psf_sndClose'
/usr/bin/ld: sf2float.c:(.text+0x39f): undefined reference to `psf_sndClose'
/usr/bin/ld: sf2float.c:(.text+0x3ca): undefined reference to `psf_finish'
collect2: error: ld returned 1 exit status
make: *** [<builtin>: sf2float] Error 1

It looks like I'm getting the order of the libraries a bit mixed up and to be honest, I'm just not totally sure what's going on here. The project is building as I mention above, but I'd like to understand the issue with make a bit more clearly moving forward. Any help much appreciated!


Solution

  • You have two problems which are causing your issue.

    The first one is a make problem: you have asked make to build sf2float because you have all: sf2float as your first target.

    But, you haven't told make how to build sf2float. You told it how to build a target called example, which you never listed as a prerequisite of anything:

    example: $(OBJECTS)
    

    So, make is not using your rule at all. Luckily (?) make has built-in rules that know how to create a binary from an object file of the same name. That built-in rule looks like this (basically):

    % : %.o
            $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
    

    That gives you the command line you see:

    gcc -Wl,-rpath=$HOME/.local/lib -lm -lportsf  sf2float.o   -o sf2float
    

    This gives you the errors you see because you have the libraries on the link line BEFORE the object file, and GCC like most linkers is a single-pass linker.

    To fix this you should do one of two things (or maybe both):

    By convention, the LDFLAGS make variable is used for linker flags, like -Wl..., and the LDLIBS make variable is used for libraries, like -lm. So to follow convention, you would write:

    LDFLAGS = -Wl,-rpath=$$HOME/.local/lib
    LDLIBS = -lportsf -lm
    

    And/or, if you want to use your rule instead of the built-in rule, you should change the target to be sf2float (or, use the $(BINARY) variable everywhere).