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!
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).