英文:
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
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论