我正在使用 Qt 4.6、CMake 2.8 和 Visual Studio 2008 for Windows 平台开发一个大型项目。
就构建系统而言,这都是标准的东西:我使用 CMake 的 QT4_WRAP_CPP 宏从头文件生成 moc 文件,然后将其链接到 add_executable 中的最终可执行文件中代码>命令。一切都按预期进行。
此设置的唯一限制是我无法在 .cpp 文件中使用 Q_OBJECT
定义小部件或助手。这对于小型的、特定于上下文的帮助器类来说非常方便,这些类应该出现在它们使用的地方旁边。
我尝试将整个源文件列表(.h 和 .cpp)传递给 QT4_WRAP_CPP
,而不仅仅是头文件,但是这不起作用(链接失败,因为一些与 moc 相关的符号未定义)。
我认为问题在于,对于给定的一对文件 foo.h 和 foo.cpp,QT4_WRAP_CPP
宏将生成相同的 moc文件(moc_foo.cxx)位于同一目录中,显然这意味着第一个文件将被第二个文件覆盖,因此符号将在链接时丢失。
有没有办法解决或解决这个问题?例如,我尝试为表单的 foo.cpp 添加特定规则
QT4_GENERATE_MOC(directory/foo.cpp directory/foo.moc)
,然后添加
#include "foo.moc"
在 foo.cpp 的末尾。我认为这应该可行,但遗憾的是 Visual Studio 只允许每个文件有一个构建规则,并且 .cpp 文件已经有一个构建规则(编译到目标文件),所以这种方法不起作用,至少使用 Visual Studio 是这样。
我的另一个想法是基于 QT4_WRAP_CPP
(在 share/cmake-2.8/Modules/Qt4Macros.h 中定义)创建一个新的宏,例如 QT4_WRAP_CPP_WITH_PREFIX
。 cmake),这将需要一个额外的前缀参数,并将此前缀添加到生成的 moc 文件中。这样,我将使用不同的前缀调用 QT4_WRAP_CPP_WITH_PREFIX
两次,一次针对 .h 文件,一次针对 .cpp 文件。我只是不喜欢这种方法,因为我会搞乱 CMake 的 Qt 支持的内部结构,而不是使用公共 API。
还有更好的主意吗?
I'm developing a large project using Qt 4.6, CMake 2.8 and Visual Studio 2008 for the Windows platform.
As far the build system goes, it's all standard stuff: I'm using CMake's QT4_WRAP_CPP
macro to generate moc files from header files, which are then linked into the final executable in the add_executable
command. Everything is working as expected.
The only restriction with this setup is that I can't define widgets or helper using Q_OBJECT
in .cpp files. This would be very convenient for small, context-specific helpers classes that should appear right next to where they're used.
I tried to pass the whole list of source files (both .h and .cpp) to QT4_WRAP_CPP
, instead of just the header files, but that doesn't work (linking fails because some moc-related symbols are undefined).
I think the problem is that, for a given pair of files foo.h and foo.cpp, the QT4_WRAP_CPP
macro will generate the same moc file (moc_foo.cxx) in the same directory, and obviously that means the first file will be overwritten by the second one, and as a result symbols will be missing at link-time.
Is there a way to fix or work around that problem? For instance, I tried to add a specific rule for foo.cpp of the form
QT4_GENERATE_MOC(directory/foo.cpp directory/foo.moc)
and then add
#include "foo.moc"
at the end of foo.cpp. I think this ought to work, but alas Visual Studio only allows one build rule per file, and .cpp files already have a build rule (compilation to object file), so this approach doesn't work, at least with Visual Studio.
Another idea that I had was to create a new macro, say QT4_WRAP_CPP_WITH_PREFIX
, based on QT4_WRAP_CPP
(which is defined in share/cmake-2.8/Modules/Qt4Macros.cmake), that would take an additional prefix argument and would add this prefix to the generated moc files. That way, I would call QT4_WRAP_CPP_WITH_PREFIX
twice, once for .h files and once for .cpp files, with different prefixes. What I just dislike about this approach is that I'd be messing with the internals of CMake's Qt support, instead of using the public API.
Any better idea?
发布评论
评论(3)
最近版本的 CMake 有“automoc”,这对我来说就像一个魅力:
http://blogs.kde.org/2011 /11/01/cool-new-stuff-cmake-286-automoc
只需在 CMakeLists.txt 中添加:
然后在 cpp(例如 example.cpp)文件中添加:
(*.moc 必须与 cpp 匹配文件名)。
Recent versions of CMake have "automoc" which worked like a charm for me:
http://blogs.kde.org/2011/11/01/cool-new-stuff-cmake-286-automoc
Simply add in the CMakeLists.txt:
and then in the cpp (e.g. example.cpp) file:
(the *.moc must match the cpp file's name).
参考文档“使用 MOC”(http://doc.qt.nokia.com/4.1/moc.html),您只需在实现文件末尾导入“foo.moc”即可。由于您无法相应地调整构建规则,请尝试导出 .pro 文件并按照诺基亚文档的建议应用构建规则。
Referring to the documentation "Using the MOC" (http://doc.qt.nokia.com/4.1/moc.html), you'd only need to import "foo.moc" at the end of your implementation file. As you can not tweak the build rules correspondingly, try to export a .pro file and apply the build rule as suggested by the nokia document.
扩展@DavidDoria,因为我无法对他的回复发表评论:最近版本的 CMake 稍微改变了语法(参见 此处):
#include.cpp>; // 或 #include "moc_.cpp"
Extending on @DavidDoria, since I cannot make a comment to his response: Recent versions of CMake have changed the syntax slightly (see here):
#include <moc_<header_base>.cpp> // or #include "moc_<header_base>.cpp"