undefined reference to `main' for shared library

huangapple go评论66阅读模式
英文:

undefined reference to `main' for shared library

问题

我正在尝试用 cmake 编译一个 C++ 共享库。这是来自第三方代码的最小可重现示例,演示了问题:

CMakeLists.txt 内容:

cmake_minimum_required(VERSION 3.5)
project(foobar)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} \
    -I/usr/include/c++/ \
    -I${CMAKE_INCLUDE_PATH}")

foobar.cpp 内容:

class Foobar {
public:
    Foobar() {}
    virtual ~Foobar() {}
};

我遇到了这个链接错误,这是没有意义的,因为共享库不需要 main 函数:

$ cmake .
...
$ make
[ 50%] Building CXX object CMakeFiles/foobar.dir/src/foobar.cpp.o
[100%] Linking CXX shared library libfoobar.so
/usr/lib/gcc-cross/aarch64-linux-gnu/11/../../../../aarch64-linux-gnu/bin/ld: /usr/lib/gcc-cross/aarch64-linux-gnu/11/../../../../aarch64-linux-gnu/lib/../lib/Scrt1.o: in function `_start':
(.text+0x1c): undefined reference to `main'
/usr/lib/gcc-cross/aarch64-linux-gnu/11/../../../../aarch64-linux-gnu/bin/ld: (.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/foobar.dir/build.make:97: libfoobar.so] Error 1
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/foobar.dir/all] Error 2
make: *** [Makefile:91: all] Error 2

用略有不同的标志顺序,我遇到了这个链接错误:

relocation XYZ against `vtable for Foobar::~Foobar' can not be used 
when making a shared object; recompile with -fPIC
英文:

I am trying to compile a C++ shared library with cmake. Here is a minimal reproducible example from this third-party code demonstrating the issue:

Content of CMakeLists.txt:

cmake_minimum_required(VERSION 3.5)
project(foobar)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} \
    -I/usr/include/c++/ \
    -I${CMAKE_INCLUDE_PATH} ")

add_library(foobar SHARED src/foobar.cpp)

Content of foobar.cpp:

class Foobar {
public:
    Foobar() {}
    virtual ~Foobar() {}
};

I am getting this linking error which doesn't make sense, since shared libraries don't need a main function:

$ cmake .
...
$ make
[ 50%] Building CXX object CMakeFiles/foobar.dir/src/foobar.cpp.o
[100%] Linking CXX shared library libfoobar.so
/usr/lib/gcc-cross/aarch64-linux-gnu/11/../../../../aarch64-linux-gnu/bin/ld: /usr/lib/gcc-cross/aarch64-linux-gnu/11/../../../../aarch64-linux-gnu/lib/../lib/Scrt1.o: in function `_start':
(.text+0x1c): undefined reference to `main'
/usr/lib/gcc-cross/aarch64-linux-gnu/11/../../../../aarch64-linux-gnu/bin/ld: (.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/foobar.dir/build.make:97: libfoobar.so] Error 1
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/foobar.dir/all] Error 2
make: *** [Makefile:91: all] Error 2

With a slightly different flag order, I am getting this linking error:

relocation XYZ against `vtable for Foobar::~Foobar' can not be used 
when making a shared object; recompile with -fPIC

答案1

得分: 0

以下是您要翻译的内容:

问题在于CMake变量CMAKE_INCLUDE_PATH默认为空,因此将-I${CMAKE_INCLUDE_PATH}添加到CMAKE_CXX_FLAGS会导致调用g++时使用缺少目录路径参数的标志-I,然后g++将下一个参数-shared解释为包含目录的路径(Linux目录名称可以以破折号开头,因此g++无法知道下一个参数不是目录名称)。调用make VERBOSE=1会显示该问题:

aarch64-linux-gnu-g++ -fPIC -I/usr/include/c++/ -I -shared -Wl,-soname,libfoobar.so -o libfoobar.so CMakeFiles/foobar.dir/src/foobar.cpp.o

因此,g++不是尝试编译共享库,而是可执行文件,并且会因缺少主函数而报错。

稍微不同的变体是在编译C++文件时,-fPIC直接位于-I之后,然后链接器会抱怨C++文件未使用-fPIC编译,需要重新使用-fPIC重新编译。

英文:

The issue is that the CMake variable CMAKE_INCLUDE_PATH is empty per default, and therefore adding -I${CMAKE_INCLUDE_PATH} to CMAKE_CXX_FLAGS causes g++ to be called with a flag -I missing a parameter for the directory path. g++ then interprets the next parameter -shared as the path of the include directory (linux directory names can start with a dash, so g++ has no way to know that the next parameter is not the name of the directory). Calling make VERBOSE=1 shows the issue:

aarch64-linux-gnu-g++ -fPIC -I/usr/include/c++/ -I -shared -Wl,-soname,libfoobar.so -o libfoobar.so CMakeFiles/foobar.dir/src/foobar.cpp.o

Thus g++ is not trying to compile a shared library, but an executable file, and complains about the lack of a main function.

A slightly different variant of this is when -fPIC is directly after -I while compiling the c++ file, then the linker complains that the c++ file was compiled without -fPIC and needs to be recompiled with -fPIC.

huangapple
  • 本文由 发表于 2023年5月22日 19:38:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76305778.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定