LedHead
LedHead

Reputation: 247

How to make linker fail for undefined references when building shared library in Linux

I'm trying to build a shared library in C++ in Ubuntu (which I will load at runtime using dlopen), but I noticed that the shared library builds just fine even if there's some missing dependencies. If I were to build an executable I would get an undefined reference linker error, which is what I would like to see here.

There might be a little too much detail in this example, but I wasn't entirely sure how to pare it down and also make it representative.

Base.h

class Base{
 public:
 virtual void foo()=0;
};

extern "C" {
Base* CreateBase();
}
extern "C" {
void DestroyBase(Base* b);
}

Derived.h

#include "Base.h"

class Derived : public Base {
 public:
 void foo();
};

extern "C" {
Base* CreateBase() {
   return new Derived;
}
}
extern "C" {
void DestroyBase(Base* b) {
   delete b;
}
}

Derived.cc

#include "Derived.h"
#include "OtherClass.h"

#include <iostream>

void Derived::foo(){
  std::cout << "Derived::foo()" << std::endl;
  std::cout << "Calling OtherClass::bar()" << std::endl;
  OtherClass other;
  other.bar();
}

OtherClass.h

class OtherClass{
  public:
  void bar();
};

My command line to build the shared library is

g++ -shared -fPIC -o libtest_dll.so Derived.cc

The problem is that I have no definition of OtherClass::bar() which is called by Derived::foo(), but libtest_dll.so builds without error or warning. It's my understanding that in Visual Studio in Windows if I were to build a DLL out of this code, it would fail to link. How can I get that behavior using g++ in Ubuntu/Linux?

Running g++ 8.3.0-6 on Ubuntu 19.04

Upvotes: 2

Views: 1808

Answers (1)

Anya Shenanigans
Anya Shenanigans

Reputation: 94614

When I'm building and want to avoid this situation, I compile the library with the options: -Wl,--no-allow-shlib-undefined -Wl,-z,defs

The first option causes the link of the shared library to fail in the situation that a symbol is not defined in the code, when used in combination with the second option, which causes the linker to report the missing symbols.

This works well to prevent missing symbols at run-time by detecting them at link time. I do, however, need to link the .so with all the libraries it uses, as otherwise it will fail to build.

sample (src.c):

#include <math.h>

extern
double share_the_stuff(double val)
{
    return acos(val * val);
}

Build with missing symbol:

gcc -shared -o src.so src.c -Wl,--no-allow-shlib-undefined -Wl,-z,defs
/usr/bin/ld: /tmp/ccFmD5uY.o: in function `share_the_stuff':
src.c:(.text+0x17): undefined reference to `acos'
collect2: error: ld returned 1 exit status

link in libm.so:

gcc -shared -o src.so src.c -Wl,--no-allow-shlib-undefined -Wl,-z,defs -lm

It behaves the same with missing internal symbols.

Upvotes: 4

Related Questions