Search code examples
cubuntucompiler-constructionmakefile

Why does my C Compiler have trouble finding some header files?


I'm working my way through Zed Shaw's Learn C the Hard Way book and I'm currently trying to work with the bstring library, writing tests for some of the more common functions from the library to learn them better. I was working on this on OS X at first, but now need to work on an Ubuntu box and the compiler is giving me grief.

Here's the Makefile: http://pastebin.com/bxCcH0w5

Here's what I have so far for the unit tests (I've omitted the function that actually runs the tests; mu_assert is a macro in minunit.h):

#include "minunit.h"
#include <lcthw/bstrlib.h>

char *test_bfromcstr()
{
    char *test = "asdf";
    bstring res = NULL;
    res = bfromcstr(test);

    mu_assert(res != NULL, "bstring should not be NULL.");
    mu_assert(blength(res) == (int) strlen(test), "bstring length should match our test data");
    mu_assert(strcmp((char *)bdata(res),test) == 0, "bstring data should be same.");

    bdestroy(res);

    return NULL;
}

char *test_blk2bstr()
{
    char *test = "qwerty";
    int L = 6;
    bstring res = NULL;
    res = blk2bstr(test, L);

    mu_assert(res != NULL, "bstring should not be NULL.");
    mu_assert(blength(res) == L, "bstring length should match our test data");
    mu_assert(strcmp((char *)bdata(res),test) == 0, "bstring data should be same.");

    bdestroy(res);

    return NULL;
}

This code compiles cleanly in OS X, but here's the error I get on Ubuntu:

liblcthw(master*) $ make
ar rcs build/liblcthw.a src/lcthw/bstrlib.o src/lcthw/darray_algos.o src/lcthw/darray.o src/lcthw/list_algos.o src/lcthw/list.o src/lcthw/radixmap.o
ranlib build/liblcthw.a
cc -shared -o build/liblcthw.so src/lcthw/bstrlib.o src/lcthw/darray_algos.o src/lcthw/darray.o src/lcthw/list_algos.o src/lcthw/list.o src/lcthw/radixmap.o
cc -g -O2 -Wall -Wextra -Isrc/ -rdynamic -DNDEBUG  build/liblcthw.a    tests/bstr_tests.c   -o tests/bstr_tests
tests/bstr_tests.c: In function ‘test_bfromcstr’:
tests/bstr_tests.c:12:2: warning: null argument where non-null required (argument 1) [-Wnonnull]
tests/bstr_tests.c:12:2: warning: null argument where non-null required (argument 1) [-Wnonnull]
tests/bstr_tests.c:12:2: warning: null argument where non-null required (argument 1) [-Wnonnull]
tests/bstr_tests.c:12:2: warning: null argument where non-null required (argument 1) [-Wnonnull]
tests/bstr_tests.c:12:2: warning: null argument where non-null required (argument 1) [-Wnonnull]
tests/bstr_tests.c:12:2: warning: null argument where non-null required (argument 1) [-Wnonnull]
tests/bstr_tests.c: In function ‘test_blk2bstr’:
tests/bstr_tests.c:28:2: warning: null argument where non-null required (argument 1) [-Wnonnull]
tests/bstr_tests.c:28:2: warning: null argument where non-null required (argument 1) [-Wnonnull]
tests/bstr_tests.c:28:2: warning: null argument where non-null required (argument 1) [-Wnonnull]
tests/bstr_tests.c:28:2: warning: null argument where non-null required (argument 1) [-Wnonnull]
tests/bstr_tests.c:28:2: warning: null argument where non-null required (argument 1) [-Wnonnull]
tests/bstr_tests.c:28:2: warning: null argument where non-null required (argument 1) [-Wnonnull]
tests/bstr_tests.c: In function ‘main’:
tests/bstr_tests.c:136:1: warning: parameter ‘argc’ set but not used [-Wunused-but-set-parameter]
/tmp/ccZEG4Lr.o: In function `test_bfromcstr':
/home/blochs/cproject/liblcthw/tests/bstr_tests.c:8: undefined reference to `bfromcstr'
/home/blochs/cproject/liblcthw/tests/bstr_tests.c:14: undefined reference to `bdestroy'
/tmp/ccZEG4Lr.o: In function `test_blk2bstr':
/home/blochs/cproject/liblcthw/tests/bstr_tests.c:24: undefined reference to `blk2bstr'
/home/blochs/cproject/liblcthw/tests/bstr_tests.c:30: undefined reference to `bdestroy'
collect2: ld returned 1 exit status
make: *** [tests/bstr_tests] Error 1
liblcthw(master*) $

EDIT

Based on a comment that has since been deleted, I modified the Makefile to include -lBuild in CFLAGS and to add -llcthw at the end of the cc command (Thanks, gcc, for caring where an option flag is...). The tests files now compile, but the tests themselves fail with this error:

liblcthw(master*) $ make
cc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG  -fPIC   -c -o src/lcthw/bstrlib.o src/lcthw/bstrlib.c
cc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG  -fPIC   -c -o src/lcthw/darray_algos.o src/lcthw/darray_algos.c
cc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG  -fPIC   -c -o src/lcthw/darray.o src/lcthw/darray.c
cc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG  -fPIC   -c -o src/lcthw/list_algos.o src/lcthw/list_algos.c
cc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG  -fPIC   -c -o src/lcthw/list.o src/lcthw/list.c
cc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG  -fPIC   -c -o src/lcthw/radixmap.o src/lcthw/radixmap.c
ar rcs build/liblcthw.a src/lcthw/bstrlib.o src/lcthw/darray_algos.o src/lcthw/darray.o src/lcthw/list_algos.o src/lcthw/list.o src/lcthw/radixmap.o
ranlib build/liblcthw.a
cc -shared -o build/liblcthw.so src/lcthw/bstrlib.o src/lcthw/darray_algos.o src/lcthw/darray.o src/lcthw/list_algos.o src/lcthw/list.o src/lcthw/radixmap.o
cc -g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG  -Lbuild tests/bstr_tests.c -o tests/bstr_tests -llcthw -lbsd
tests/bstr_tests.c: In function ‘test_bfromcstr’:
tests/bstr_tests.c:12:2: warning: null argument where non-null required (argument 1) [-Wnonnull]
tests/bstr_tests.c:12:2: warning: null argument where non-null required (argument 1) [-Wnonnull]
tests/bstr_tests.c:12:2: warning: null argument where non-null required (argument 1) [-Wnonnull]
tests/bstr_tests.c:12:2: warning: null argument where non-null required (argument 1) [-Wnonnull]
tests/bstr_tests.c:12:2: warning: null argument where non-null required (argument 1) [-Wnonnull]
tests/bstr_tests.c:12:2: warning: null argument where non-null required (argument 1) [-Wnonnull]
tests/bstr_tests.c: In function ‘test_blk2bstr’:
tests/bstr_tests.c:28:2: warning: null argument where non-null required (argument 1) [-Wnonnull]
tests/bstr_tests.c:28:2: warning: null argument where non-null required (argument 1) [-Wnonnull]
tests/bstr_tests.c:28:2: warning: null argument where non-null required (argument 1) [-Wnonnull]
tests/bstr_tests.c:28:2: warning: null argument where non-null required (argument 1) [-Wnonnull]
tests/bstr_tests.c:28:2: warning: null argument where non-null required (argument 1) [-Wnonnull]
tests/bstr_tests.c:28:2: warning: null argument where non-null required (argument 1) [-Wnonnull]
tests/bstr_tests.c: In function ‘main’:
tests/bstr_tests.c:136:1: warning: parameter ‘argc’ set but not used [-Wunused-but-set-parameter]
sh ./tests/runtests.sh
Running unit tests:
ERROR in test tests/bstr_tests: here's tests/tests.log
------
./tests/bstr_tests: error while loading shared libraries: liblcthw.so: cannot open shared object file: No such file or directory
make: *** [tests] Error 1
liblcthw(master*) $

WTF.


Solution

  • To statically link the library

    Try putting the reference to the library build/liblcthw.a after tests/bstr_tests.c in gcc's command line options, like so:

    cc -g -O2 -Wall -Wextra -Isrc/ -rdynamic -DNDEBUG -o tests/bstr_tests tests/bstr_tests.c build/liblcthw.a
    

    To dynamically link the library

    cc -g -O2 -Wall -Wextra -Isrc/ -rdynamic -DNDEBUG -o tests/bstr_tests tests/bstr_tests.c -Lbuild -llcthw
    

    Also add the path to the shared object liblcthw.so to the variable LD_LIBRARY_PATH of the environment in which you try to run the final executable.