背景
近期在研究如何在QML上注册一个OpenGL组件时候翻到了官方教程,按照步骤一步一步完成提示找不到符号:
Undefined symbols for architecture arm64:
"Squircle::tChanged()", referenced from:
Squircle::setT(double) in squircle.cpp.o
"vtable for SquircleRenderer", referenced from:
SquircleRenderer::~SquircleRenderer() in squircle.cpp.o
SquircleRenderer::SquircleRenderer() in squircle.cpp.o
NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
"vtable for Squircle", referenced from:
Squircle::Squircle() in squircle.cpp.o
NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.
后发现官网有提供实例项目:https://code.qt.io/cgit/qt/qtdeclarative.git/tree/examples/quick/scenegraph/openglunderqml?h=6.2 ,经测试,可以正常编译。
问题定位
搜索Qt
、vtable
和Undefined symbols
容易在Stack Overflow找到以下讨论:
https://stackoverflow.com/questions/14010922/qt-undefined-reference-to-vtable
似乎是Qt的meta-compiler,猜想有可能是meta-compiler时没搜索include_directories
的头文件。于是我们将官方提供的demo进行如下改动:
- 原项目文件移动到
src
并作为一个子模块add_subdirectory(src)
; squircle.h
移动include
并通过include_directories(include)
添加头文件。
编译报错。
原因分析
问题明确之后,我们加上include_directories
进一步搜索,发现Stack Overflow上已有相关讨论:https://stackoverflow.com/questions/68734345/qt5-undefined-reference-to-vtable-cmake-build-issue ,解决方案很简单,将squircle.h
添加到executable
即可。
另外,不建议使用include_directories
,而应使用target_include_directories
代替。
Never use include_directories in CMake ever. Use target_include_directories instead.
https://cmake.org/cmake/help/latest/command/include_directories.html