背景

近期在研究如何在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 ,经测试,可以正常编译。

问题定位

搜索QtvtableUndefined symbols容易在Stack Overflow找到以下讨论:
https://stackoverflow.com/questions/14010922/qt-undefined-reference-to-vtable
似乎是Qt的meta-compiler,猜想有可能是meta-compiler时没搜索include_directories的头文件。于是我们将官方提供的demo进行如下改动:

  1. 原项目文件移动到src并作为一个子模块add_subdirectory(src)
  2. 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
最后修改:2022 年 04 月 15 日
如果觉得我的文章对你有用,请随意赞赏