Why am I getting `undefined reference to xxx` errors when all libraries and references needed are accounted for?

286 Views Asked by At

Essentially I am trying to use the redland rdf libraries but I cannot link to them. When I try a simple basic program which uses the redland libraries I get these errors:

/usr/local/lib/librdf.a(rdf_init.o): In function `librdf_free_memory':
/home/ciaran/Software/redland/redland-1.0.17/src/rdf_init.c:671: undefined reference to `raptor_free_memory'
/usr/local/lib/librdf.a(rdf_init.o): In function `librdf_alloc_memory':
/home/ciaran/Software/redland/redland-1.0.17/src/rdf_init.c:689: undefined reference to `raptor_alloc_memory'
/usr/local/lib/librdf.a(rdf_init.o): In function `librdf_calloc_memory':
/home/ciaran/Software/redland/redland-1.0.17/src/rdf_init.c:707: undefined reference to `raptor_calloc_memory'

At first glance, you might just think I have a missing link library, which is what I thought until I inspected further (see below), however, the libraries are all accounted for.

A proper minimal working example is difficult in this instance because it requires getting and building the libraries that I'm trying to use. However, I've created a GitHub repository

$ git clone [email protected]:CiaranWelsh/RedlandBuildTest.git

that contains the source files necessary for building the Redland libraries as well as the example code I'm using (which breaks).

In order to build the libraries, you will also need

    $ sudo apt install automake autoconf libtool gtk-doc-tools
    $ sudo apt install libxml2 libxml2-dev libxslt libxslt-dev libcurl4-openssl-dev libltdl-dev

Note, I'm working on Ubuntu-18.04 on windows subsystem for Linux.

To get, build and install the libraries I'm using these terminal commands:

#raptor2
wget "http://download.librdf.org/source/raptor2-2.0.15.tar.gz" 
tar -xvf raptor2-2.0.15.tar.gz
cd raptor2-2.0.15
./autogen.sh 
make
sudo make install
# redland (librdf)
wget "http://download.librdf.org/source/redland-1.0.17.tar.gz" 
tar -xvf redland-1.0.17.tar.gz
cd redland-1.0.17 
./autogen.sh
make
sudo make install
# rasqal
wget "http://download.librdf.org/source/rasqal-0.9.33.tar.gz" 
tar -xvf rasqal-0.9.33.tar.gz
cd rasqal-0.9.33
./autogen.sh 
make 
sudo make install

Which are available in the github repository as shell scripts (get-raptor.sh, get-rasqal.sh and get-librdf.sh).

And my minimal CMake script (also in the repository):

cmake_minimum_required(VERSION 3.15)
project(RedlandBuildTest)

set(CMAKE_CXX_STANDARD 14)

find_library(RAPTOR2_STATIC_LIBRARY
        NAMES libraptor2.a
        PATHS /usr/local/lib
        )

find_path(RAPTOR2_INCLUDE_DIR
        NAMES raptor2.h
        PATHS /usr/local/include/raptor2
        )
find_library(RASQAL_STATIC_LIBRARY
        NAMES librasqal.a
        PATHS /usr/local/lib
        )

find_path(RASQAL_INCLUDE_DIR
        NAMES rasqal.h
        PATHS /usr/local/include/rasqal
        )

find_library(LIBRDF_STATIC_LIBRARY
        NAMES librdf.a
        PATHS /usr/local/lib
        )

find_path(LIBRDF_INCLUDE_DIR
        NAMES librdf.h
        PATHS /usr/local/include
        )

add_executable(RedlandBuildTest main.c)

target_include_directories(RedlandBuildTest PRIVATE
        ${RAPTOR2_INCLUDE_DIR}
        ${RASQAL_INCLUDE_DIR}
        ${LIBRDF_INCLUDE_DIR}
        )

target_link_libraries(RedlandBuildTest PRIVATE
        ${RAPTOR2_STATIC_LIBRARY}
        ${RASQAL_STATIC_LIBRARY}
        ${LIBRDF_STATIC_LIBRARY}
        curl
        xml2
        xslt
        ltdl
        )

get_target_property(LINK_LIBRARIES RedlandBuildTest LINK_LIBRARIES)
get_target_property(INCLUDE_DIRECTORIES RedlandBuildTest INCLUDE_DIRECTORIES)

message(STATUS "

LINK_LIBRARIES      ${LINK_LIBRARIES}
INCLUDE_DIRECTORIES ${INCLUDE_DIRECTORIES}

")

message(STATUS "

    RAPTOR2_STATIC_LIBRARY   ${RAPTOR2_STATIC_LIBRARY}
    RAPTOR2_INCLUDE_DIR      ${RAPTOR2_INCLUDE_DIR}

    RASQAL_STATIC_LIBRARY    ${RASQAL_STATIC_LIBRARY}
    RASQAL_INCLUDE_DIR       ${RASQAL_INCLUDE_DIR}

    LIBRDF_STATIC_LIBRARY    ${LIBRDF_STATIC_LIBRARY}
    LIBRDF_INCLUDE_DIR       ${LIBRDF_INCLUDE_DIR}

")

And the output of the CMake command:

#(looks good)
LINK_LIBRARIES      /usr/local/lib/libraptor2.a;/usr/local/lib/librasqal.a;/usr/local/lib/librdf.a;curl;xml2;xslt;ltdl 
INCLUDE_DIRECTORIES /usr/local/include/raptor2;/usr/local/include/rasqal;/usr/local/include


    RAPTOR2_STATIC_LIBRARY   /usr/local/lib/libraptor2.a
    RAPTOR2_INCLUDE_DIR      /usr/local/include/raptor2

    RASQAL_STATIC_LIBRARY    /usr/local/lib/librasqal.a
    RASQAL_INCLUDE_DIR       /usr/local/include/rasqal

    LIBRDF_STATIC_LIBRARY    /usr/local/lib/librdf.a
    LIBRDF_INCLUDE_DIR       /usr/local/include

To build, I'm using CLion which just does this in the background:

mkdir build && cd build
CMake ..
make

Thus giving me linker errors. I have dug a little deeper by using nm to inspect the contents of the Redland libraries.

$nm -A librdf.a > librdf.a.nmoutput.txt
$nm -A libraptor2.a > libraptor2.a.nmoutput.txt
$nm -A librasqal.a > librasqal.a.nmoutput.txt 

The first offending undfined reference error

/usr/local/lib/librdf.a(rdf_init.o): In function `librdf_free_memory':
/home/ciaran/Software/redland/redland-1.0.17/src/rdf_init.c:671: undefined reference to `raptor_free_memory'

is in function librdf_free_memory, which is a defined reference inside librdf.a

# librdf.a.nmoutput.txt
...
librdf.a:rdf_init.o:0000000000000740 T librdf_free_memory
...

When we look for the undefined reference to raptor_free_memory, we se that it is indeed undefined inside librdf.a..

#librdf.a.nmoutput.txt
...
librdf.a:rdf_init.o:                 U raptor_free_memory
...

But this should be in libraptor2.a anyway, and if we look we see that it is indeed there and defined as it should be:

# libraptor2.a.nmoutput.txt
...
libraptor2.a:raptor_general.o:0000000000000863 T raptor_free_memory
...

My understanding is that the process of linking should essentially fill the undefined reference inside librdf.a with the definition inside libraptor.a, but this clearly is not happening.

Why is this happening?

1

There are 1 best solutions below

0
On BEST ANSWER

When your static libraries have dependencies on each other, the link order matters (see this response).

If librdf depends on the libraptor library (as indicated by the link error), the libraptor library should be listed after librdf when specified to the linker. Try re-arranging the list of libraries in your target_link_libraries() command to adhere to this ordering, based on your library dependencies.