我的代码应该在Qt 5.4之前和之后的平台上编译和运行,其中引入了QOpenGLWidget,取代了QGLWidget。我以为我可以编写这样的代码来支持两者:
#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
# define USE_Q_OPEN_GL_WIDGET
#endif
#ifdef USE_Q_OPEN_GL_WIDGET
# include <QOpenGLWidget>
#else
# include <QGLWidget>
#endif
class GLWidget :
#ifdef USE_Q_OPEN_GL_WIDGET
public QOpenGLWidget
#else
public QGLWidget
#endif
{
Q_OBJECT
public:
[...]
但是这不会飞,因为moc
似乎不理解预处理程序指令并且会为错误的类生成代码。
我尝试通过向add_custom_command
添加CMakeLists.txt
指令来解决此问题,该指令会在将文件传递给moc之前对文件运行${CMAKE_CXX_COMPILER}" -E -P -x c++-header ...
。但是这似乎无法正常工作,因为预处理器将删除神奇的Q_OBJECT
行,表明在运行C预处理器之前必须运行<{1}} 。
我还有其他选择吗?
我必须使用两个几乎相同的头文件(除了两行),然后在构建时在cmake中选择正确的头文件吗?
修改的
要测试此问题,请尝试以下操作:
moc
创建一个chroot):然后创建包含以下内容的sudo debootstrap trusty ubuntu-trusty
glwidget.h
然后运行:
#ifndef GLWIDGET_H
#define GLWIDGET_H
#include <QtGlobal>
#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
# define USE_Q_OPEN_GL_WIDGET
#endif
#ifdef USE_Q_OPEN_GL_WIDGET
# include <QOpenGLWidget>
#else
# include <QGLWidget>
#endif
class GLWidget :
#ifdef USE_Q_OPEN_GL_WIDGET
public QOpenGLWidget
#else
public QGLWidget
#endif
{
Q_OBJECT
};
#endif
所以你看到即使qt 5.2.1没有QOpenGL,moc也会解释预处理器指令
我们可以将版本检查更改为更简单的
$ moc -v
moc 5.2.1
$ moc glwidget.h | grep QGL || echo "not found"
not found
$ moc glwidget.h | grep QOpenGL >/dev/null && echo "found!"
found!
如果我们再次使用该检查,那么在Ubuntu trusty中的qt 5.2.1中的moc会生成正确的结果
所以我们认为我们找到了解决方案并尝试在相同的代码上运行来自更新的qt发行版的moc。这次我在Debian unstable中使用qt 5.5.1中的moc,我得到了:
#if QT_VERSION >= 0x050400
最有趣的是,如果在qt 5.5.1下我将版本检查宏mack转为使用
$ moc -v
moc 5.5.1
$ moc glwidget.h | grep QOpen || echo "not found"
not found
$ moc foo.h | grep QGL > /dev/null && echo "found"
found
然后它确实有效!
总而言之,moc确实理解了一些预处理器指令,但它确实理解的那些指令在qt 5.4之前和之后的版本之间是不同的。似乎并不存在两者都能理解的通用预处理器指令。因此,我没有看到使用预处理器指令解决此问题的方法。
答案 0 :(得分:1)
您可以使用CMake生成此标头。将此代码放入其中:
#include <@GL_CLASS@>
class GLWidget : @GL_CLASS@
{
Q_OBJECT
public:
[...]
然后在CMakeLists.txt中执行此操作:
set(GL_CLASS <depending on Qt version>)
include_directories(${CMAKE_CURRENT_BINARY_DIR}) #this is because configure_file produces its output in the build dir
configure_file(yourheader.h output.h @ONLY)
最后,在代码中使用#include "output.h"
。