在 Linux 中构建共享库时如何使链接器因未定义的引用而失败

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

我正在尝试在 Ubuntu 中用 C++ 构建一个共享库(我将在运行时使用 dlopen 加载它),但我注意到共享库构建得很好,即使有一些缺少的依赖项。如果我要构建一个可执行文件,我会得到一个 undefined reference linker 错误,这是我希望在这里看到的。

这个例子中可能有一些细节太多了,但我不完全确定如何削减它并使其具有代表性。

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();
};

我构建共享库的命令行是

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

问题是我没有 Derived::foo() 调用的 OtherClass::bar() 的定义,但是 libtest_dll.so 构建时没有错误或警告。据我了解,在 Visual Studio in Windows 中,如果我要使用此代码构建 DLL,它将无法 link。如何使用 Ubuntu/Linux 中的 g++ 获得该行为?

运行 g++ 8.3.0-6 Ubuntu 19.04

当我构建并希望避免这种情况时,我使用以下选项编译库:-Wl,--no-allow-shlib-undefined -Wl,-z,defs

第一个选项在代码中没有定义符号的情况下导致共享库link失败,当与第二个选项结合使用时,导致linker 报告丢失的符号。

这可以很好地防止在 运行 时间丢失符号,方法是在 link 时间检测它们。但是,我确实需要 link .so 及其使用的所有库,否则将无法构建。

样本 (src.c):

#include <math.h>

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

构建缺少符号:

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 在 libm.so:

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

它与缺少内部符号的行为相同。