3

I am trying to learn to C programing using Zed Shaw's Learn C the hard way. I have been working on ex26 where we create a program "devpkg" used to install software. This exercise requires installing Apache Portable Runtime library. After writing the code for this exercise I could not get program to compile using the following makefile:

    PREFIX?=/user/local
    CFLAGS=-g -Wall -I${PREFIX}/apr/include/apr-1 -I{PREFIX}/apr/include/apr-util-1
    LDFLAGS=-L${PREFIX}/apr/lib -lapr-1 -pthread -laprutil-1

    all: devpkg

    install: all
             install -d${DESTDIR}/${PREFIX}/bin/
             install devpkg ${DESTDIR}/${PREFIX}/bin/

    clean:
            rm -f *.o
            rm -f devpkg
            rm -f *.dSYM

This makefile did not seem to work as when I used "$make devpkg" not all of the APR library functions were declared. As a side note I am running this on a Ubuntu virtual machine. A solution given in the text says to alter a config file and then "run ldconfig" to help the linker find the appropriate library.
I do not understand the man page for ldconfig well enough to correctly utilize the function. How do run ldconfig correctly?

Also after some digging I found a reference that using "LDLIBS" instead of "LDFLAGS" in the makefile fixed the problem. I altered the makefile and the program compiled.

What is the difference between "LDFLAGS" and "LDLIBS" that allowed the C compiler to correctly link to the APR library? Is there a handy list of commands somewhere that can help me better understand how a makefile is correctly generated?

Thanks for your time.

Mat
  • 202,337
  • 40
  • 393
  • 406

2 Answers2

3

From the GNU Make Manual, section 10.2 Catalogue of Implicit Rules:

Linking a single object file
n is made automatically from n.o by running the linker (usually called ld) via the C compiler. The precise recipe used is '$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)'.

As you can see, LDFLAGS comes before your object file and LDLIBS after. Sometimes that order can matter - apparently it does in your case.

Editorial note: While it might sometimes be convenient to use make's implicit rule support, it almost always ends up more confusing down the road. I'd urge you to write a complete makefile - it'll help you understand what's going on better and hopefully avoid this sort of problem in the future.

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
  • Thanks I think I get it now. Also thank you for pointing me to the GNU make manual. I'll try rewriting the makefile. – user2073935 Mar 02 '13 at 02:02
3

I just wanted to add this answer as an alternative to changing "LDFLAGS" to "LDLIBS". The above solution did work in my case but I found an alternative (though less direct) solution before I saw this thread which others may find useful or interesting. When compiling I was seeing lots of "undefined reference" errors e.g.:

/MyCode/LCTHW/devpkg/devpkg.c:18: undefined reference to `apr_pool_initialize'

After much trial and error, I changed the makefile thus (still using LDFLAGS):

CC=gcc
PREFIX?=/usr/local
CFLAGS=-g   -Wall   -I$(PREFIX)/apr/include/apr-1   -I$(PREFIX)/apr/include/apr-util-1
LDFLAGS=-L$(PREFIX)/apr/lib -lapr-1 -laprutil-1 -pthread
OBJECTS=bstrlib.o   db.o    shell.o commands.o  devpkg.o

all:    devpkg

devpkg: $(OBJECTS)
    $(CC)   $(CFLAGS)   $(OBJECTS)  -o  devpkg  $(LDFLAGS)

install:    all
    install -d $(DESTDIR)/$(PREFIX)/bin/
    install devpkg $(DESTDIR)/$(PREFIX)/bin/

clean:
    rm -f *.o
    rm -f devpkg
    rm -rf *.dSYM

I then had to add a .conf file to /etc/ld.so.conf.d containing the path to the apr libraries, namely

/usr/local/apr/lib

And then run

sudo ldconfig

so the system would pick up the new .conf file and so know where to find the library. From what I have read, it seems this last step was necessary because the library wasn't stored in /usr/local/lib. If I remove the .conf file and re-run ldconfig to update, the program compiles but then fails to find the libraries at run-time (whether compiled with my makefile or OP's).

While I don't fully understand my solution, it at least allowed me to compile and run the program with no errors. Hopefully this solution will be of interest to others, and maybe somebody more knowledgeable will be able to explain in more detail why it works.

WhoBuntu
  • 304
  • 2
  • 4