0

I am building a small static library that currently contains just a single object file. When I try to link it to a program I get a range of 'undefined reference' errors. All of the errors appear to be related to definitions in the .cpp file.

The library header file (except.hpp) is:

#ifndef FOD_REEF_EXCEPT
#define FOD_REEF_EXCEPT

#include <exception>
#include <string>

namespace REEF
{
    class REEFException : public std::exception
    {
    public:
        REEFException() = default;
        REEFException(const char* file, int line);
        virtual ~REEFException() = default;
        virtual const char* what() const noexcept;
        virtual const std::string What() const noexcept { return std::string(what()); }
        virtual const std::string Where() const noexcept;

    private:
        std::string     _where;
    };
}

#endif // FOD_REEF_EXCEPT

The implementation file (except.cpp) is:

#include "except.hpp"

const char* defaultExceptionMessage = "Undefined exception";

REEF::REEFException::REEFException(const char* file, int line)
{
    _where = "line " + std::to_string(line) + " in " + file;
}

const char* REEF::REEFException::what() const noexcept
{
    return defaultExceptionMessage;
}

const std::string REEF::REEFException::Where() const noexcept
{
    return _where;
}

I compile the object file (except.o) with:

g++ -c -std=c++17 -Wall -Wextra -I~/dev/project/fod -o obj/except.o src/except.cpp

and then create a library with:

ar rvs bin/libreef.a obj/except.o

This successfully creates ~/dev/project/fod/reef/bin/libreef.a. Running ar -t libreef.a shows

except.o

When I compile a test program, from a different directory, with

g++ -std=c++17 -Wall -Wextra -I~/dev/project/fod -L~/dev/project/fod/reef/bin -lreef src/test.cpp -o bin/test

I get a range of undefined reference errors:

test.cpp:46: undefined reference to `REEF::REEFException::REEFException(char const*, int)'
test.cpp:46: undefined reference to `typeinfo for REEF::REEFException'
/tmp/ccrlvFmY.o: In function `TestAsserts()':
test.cpp:133: undefined reference to `REEF::REEFException::REEFException(char const*, int)'
test.cpp:133: undefined reference to `typeinfo for REEF::REEFException'
test.cpp:135: undefined reference to `REEF::REEFException::REEFException(char const*, int)'
test.cpp:135: undefined reference to `typeinfo for REEF::REEFException'
/tmp/ccrlvFmY.o: In function `REEF::REEFException::REEFException()':
except.hpp:46: undefined reference to `vtable for REEF::REEFException'
/tmp/ccrlvFmY.o: In function `REEF::REEFException::~REEFException()':
except.hpp:59: undefined reference to `vtable for REEF::REEFException'
/tmp/ccrlvFmY.o:(.gcc_except_table+0x6c): undefined reference to `typeinfo for REEF::REEFException'
/tmp/ccrlvFmY.o:(.gcc_except_table+0xb0): undefined reference to `typeinfo for REEF::REEFException'

However, if I don't compile against the library but instead compile directly against except.o, like this

g++ -std=c++17 -Wall -Wextra -I~/dev/project/fod src/test.cpp ../obj/except.o -o bin/test

from the test directory then it compiles and runs just fine.

I can't work out why linking with the library is a problem, it's just a container for the object file isn't it? I know the linker is finding the correct library file because if I change it's name I get an error stating that it can't be found.

Can anyone help me? I have no more hair to lose.

M. Webb
  • 157
  • 11
  • 1
    So when you change your command to `g++ -std=c++17 -Wall -Wextra -I~/dev/project/fod -L~/dev/project/fod/reef/bin src/test.cpp -lreef -o bin/test` (note the change of order between test.cpp & -lreef) does it work? – UKMonkey Apr 20 '18 at 13:00
  • Yes, that seems to have done it. Is the g++ command line really that brittle? – M. Webb Apr 20 '18 at 13:05
  • I believe this should answer your question. https://stackoverflow.com/questions/45135/why-does-the-order-in-which-libraries-are-linked-sometimes-cause-errors-in-gcc (in short; it's not brittle; it just processes files in order because sometimes it matters) – UKMonkey Apr 20 '18 at 13:10

0 Answers0