我有一个使用 CMake 构建的 QT 项目。其中一个目标有 142 个文件需要moc. 当我使用qt5_wrap_cpp源文件并构建它时,该过程在大约 15 秒内完成:

set(CMAKE_AUTOMOC NO)
qt5_wrap_cpp(moc_files ${source_files})
list(APPEND source_files ${moc_files})
target_sources("${target}" PRIVATE "${source_files}")
Run Code Online (Sandbox Code Playgroud)
这里的每个任务都是为每个文件调用moc工具。
然而,当我使用AUTOMOC特征时,生成时间增加到 6 分钟:

set(CMAKE_AUTOMOC YES)
target_sources("${target}" PRIVATE "${source_files}")
Run Code Online (Sandbox Code Playgroud)
这里的cmake任务大致如下:
cmake.exe -E cmake_autogen <my_project_path>/<my_project>_autogen.dir Debug
Run Code Online (Sandbox Code Playgroud)
我再次运行该命令,在没有任何内容可生成的情况下,运行需要 0.3 秒。然而,当我删除一个 moc 文件时,该命令需要 2 秒才能运行。当需要生成5时是:
TotalSeconds : 11.3493687
超过11秒。当我删除所有 142 个 moc 文件时,执行时间为cmake_autogen:
TotalSeconds : 354.5894649
我没有在文档和 CMake 问题中找到任何与此相关的内容。我可以做些什么来AUTOMOC像单个文件处理一样高效地运行吗?
CMake版本3.10.2
Qt版本5.9.3
更新1。
在分析 CMake 之后,我注意到调用moc是最耗时的操作。命令行似乎有 247 个包含路径,而 …
我想使用Q_CLASSINFO宏存储一些类信息.但是我想将它包装在我自己的宏中,例如:
#define DB_TABLE( TABLE ) \
Q_CLASSINFO( "db_table", #TABLE )
#define DB_FIELD( PROPERTY, COLUMN ) \
Q_CLASSINFO( "dbcol_" #PROPERTY, #COLUMN )
class Foo : public QObject
{
Q_OBJECT
DB_TABLE( some_table )
DB_FIELD( clientName, client_name )
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,moc不会扩展宏,因此不会添加Q_CLASSINFO.
我已经尝试用已经预处理的源来提供moc,但它在一些包含的Qt类上有效.
你知道任何解决方法吗?
我目前正在将使用qmake构建的项目转移到CMake.
在带有qmake的版本中,在.pri文件中,有
MOC_DIR = .moc/$${PLATFORM_NAME}
Run Code Online (Sandbox Code Playgroud)
允许在给定目录中生成MOC临时文件,保持源清洁.如何用CMake做同样的事情?
注意:使用CMake,我使用FindQt4.cmake包和命令QT4_WRAP_CPP().
使用Qt Visual Studio插件,它似乎以一种似乎看不见的方式处理了几乎所有事情。不幸的是,它使用msbuild中的CustomBuild步骤进行移动。这导致了一个接一个的串行移动。有没有办法说服msbuild并行执行它们-我已经厌倦了像我一样坐在它们的桂冠上的7个核心。
我已经看过msbuild的BuildInParallel,但是我不确定如何在这里应用它。
msbuild片段:
<Project>
...
<ItemGroup>
<CustomBuild Include="a_class4.h">
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Moc%27ing %(Identity)...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_CORE_LIB -DQT_GUI_LIB "-I." "-I.\GeneratedFiles" "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\qtmain" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I." "-I." "-I." "-I."</Command>
</CustomBuild>
<CustomBuild Include="a_class3.h">
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Moc%27ing %(Identity)...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_CORE_LIB -DQT_GUI_LIB "-I." "-I.\GeneratedFiles" "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\qtmain" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I." "-I." "-I." "-I."</Command>
</CustomBuild>
</ItemGroup>
...
</Project>
Run Code Online (Sandbox Code Playgroud) 我的目标是在保持冗长的同时,实现更多的代码重用。
考虑以下示例代码:
// qdot@defixio /tmp/test4 $ cat test.h
#include <QObject>
class Foo : public QObject {
Q_OBJECT
// Q_PROPERTY(int bar1 READ bar<1>)
// Q_PROPERTY(int bar2 READ bar<2>)
public:
template <int i> int bar() const;
};
// qdot@defixio /tmp/test4 $ cat test.cpp
#include "test.h"
#include <QDebug>
template <int i>
int Foo::bar() const { qDebug() << "Template parameter" << i; }
int main() {
Foo foo;
foo.bar<1>();
foo.bar<2>();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
该程序按预期编译并运行。
如果您想知道为什么我会这样 - 想象一组属性,DESIGNABLE 等,但属于同一个“类” - 在这种情况下,我希望使用枚举模板类型访问器拥有单独的属性。
取消注释属性定义会导致以下 moc 错误:
/usr/bin/moc …Run Code Online (Sandbox Code Playgroud) 这是一个已知的错误,moc跳过了libstdc ++中使用的宏,如下所述:http://lists.kde.org/? l = ancessitas-devel&m = 132317657926916&q = raw
我正在尝试编译一个使用gcc 4.6.3的项目,因为moc跳过宏而被卡住了.
克服该问题的一种方法是包含此链接中提到的指令:
http://doc.qt.io/qt-4.8/moc.html
但这是耗时的,而不是一个非常干净的方式,因为每个文件都必须有这些指令.
我想知道的是,是否可以配置qmake以使moc跳过某些目录/文件?
编辑:错别字
根据http://qt-project.org/doc/qt-4.8/moc.html#multiple-inheritance-requires-qobject-to-be-first的QObject规定,使用多重继承时,基类必须是第一个。
这是因为moc工具的某些限制还是C ++内存布局问题也被考虑在内,因此这种限制就已经存在了吗?
我试图简化(即摆脱样板代码的负载)创建QObject包装类,转发其他QObject派生类的属性访问.
从小处开始,我只是尝试使用一个属性:
// Sy_test.h - The wrapped class
class Sy_test : public QObject
{
Q_OBJECT
Q_PROPERTY( bool prop READ getProp WRITE setProp NOTIFY propChanged )
public:
Sy_test( QObject* parent = nullptr ) :
QObject{ parent },
prop_{ false } {}
bool getProp() const { return prop_; }
public slots:
void setProp( bool value )
{
if ( value != prop_ ) {
prop_ = value;
emit propChanged( prop_ );
}
}
signals:
void propChanged( bool value …Run Code Online (Sandbox Code Playgroud) 我将Qt与CMake一起使用,因为CMake比我自己的团队工作更容易.我经常遇到一个错误
ui_*.h: No such file or directory
Run Code Online (Sandbox Code Playgroud)
通常,当我的项目已经有一个ui_*.h文件开始时,它只会修改该.h文件.我在我的CMake文件中使用下面的命令,所以它应该.ui用适当的ui_*.h文件包装我的文件.
qt4_wrap_ui (mainwindow mainwindow.ui)
target_linked_library (mainwindow ${QT_LIBRARIES})
Run Code Online (Sandbox Code Playgroud)
但有时这不起作用,我必须完全重建整个ui_*.h文件.我究竟做错了什么?
moc ×10
qt ×10
c++ ×3
cmake ×2
qt4 ×2
automoc ×1
inheritance ×1
libstdc++ ×1
macros ×1
msbuild ×1
preprocessor ×1
properties ×1
qobject ×1
qt-creator ×1
templates ×1