如何使用cmake和QRC将Qt4的qm文件集成到二进制文件中?

13

我有一个Qt4 CMake项目,我想将i18n的QM文件集成到输出二进制文件中。目前我已经制定了生成TS和QM文件的规则:

set(myapp_TRANSLATIONS
    i18n/myapp_de.ts
)

set(FILES_TO_TRANSLATE
    ${myapp_SRCS}
    ${myapp_MOC_HDRS}
)

QT4_CREATE_TRANSLATION(QM_FILES ${FILES_TO_TRANSLATE} ${myapp_TRANSLATIONS})
QT4_ADD_TRANSLATION(QM ${myapp_TRANSLATIONS})

我尝试了以下方法将QM文件添加到可执行文件中:

add_executable(myapp ${myapp_SRCS} ${myapp_MOC_SRCS} ${myapp_RCC_SRCS} ${QM})

这是来自 main.cpp 的初始化:

QTranslator qtTranslator;
qtTranslator.load("qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath));
app.installTranslator(&qtTranslator);

QTranslator appTranslator;
appTranslator.load("myapp_" + QLocale::system().name());
app.installTranslator(&appTranslator);
然而,strings mypp 显示翻译没有进入二进制文件中。 更新: 我将每个 qm 文件添加到 i18n/translations.qrc 中。
<!DOCTYPE RCC><RCC version="1.0">
  <qresource prefix="/resources">
    <file>myapp_de.qm</file>
    <file>  ...   .qm</file>
  </qresource>
</RCC>

并使用

QT4_ADD_RESOURCES(myapp_QM_RCC_SRCS i18n/translations.qrc)

同时将myapp_QM_RCC_SRCS添加到可执行文件的依赖项中。

但是,在构建时会失败,因为CMake进行了影子构建(在源目录之外构建),但解析QRC文件以获取期望相对于QRC文件引用文件的依赖关系(这是一个不错的功能,但没有构建QM文件的规则来到达该位置)。QM文件位于${CMAKE_CURRENT_BINARY_DIR}(使用影子构建应该在此处),但期望其位于${CMAKE_CURRENT_SOURCE_DIR}(非生成文件所在的位置 - 因此根据情况,两个位置均正确)。

4个回答

11

我遇到了完全相同的问题。我想出了以下解决方案:

创建一个只包含预期QM文件的QRC文件,并给它一个不同的前缀,以避免与其他资源冲突:

<RCC>
    <qresource prefix="/translators">
    <file>myapp_en.qm</file>
    </qresource>
</RCC>

添加一个CMake规则,将QRC文件复制到输出目录,然后再添加另一个规则来运行资源编译器:

# Change 'myapp_en' to be the base file name of the qrc file.
SET( trans_file myapp_en )
SET( trans_srcfile ${CMAKE_CURRENT_SOURCE_DIR}/${trans_file}.qrc)
SET( trans_infile ${CMAKE_CURRENT_BINARY_DIR}/${trans_file}.qrc)
SET( trans_outfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${trans_file}.cxx)

# Copy the QRC file to the output directory, because the files listed in the 
# qrc file are relative to that directory.
ADD_CUSTOM_COMMAND(
    OUTPUT ${trans_infile}
    COMMAND ${CMAKE_COMMAND} -E copy ${trans_srcfile} ${trans_infile}
    MAIN_DEPENDENCY ${trans_srcfile}
    )

# Run the resource compiler (rcc_options should already be set). We can't
# use QT4_ADD_RESOURCES because the qrc file may not exist yet.
ADD_CUSTOM_COMMAND(
    OUTPUT ${trans_outfile}
    COMMAND ${QT_RCC_EXECUTABLE}
    ARGS ${rcc_options} -name ${trans_file} -o ${trans_outfile} ${trans_infile}
    MAIN_DEPENDENCY ${trans_infile}
    DEPENDS ${qm_files}
    )

# Add compiled resources to executable dependency list
ADD_EXECUTABLE( ${APP_NAME} ... ${trans_outfile} )

如果您使用Qt 5,请使用${Qt5Core_RCC_EXECUTABLE}而不是${QT_RCC_EXECUTABLE}


看起来很有前途,我会尝试一下。+1 - hurikhan77
我已经逐步构建了您的想法,以了解您是如何做到的。它完美地运作。 - hurikhan77
太棒了!像魔法一样顺利运行。 - Claudiu
2
不要停止阅读,有一种更简单的方法来做:https://dev59.com/gXA75IYBdhLWcg3wv77A#34798124 - Alexander Shishenko

6

我发现在CMake 3.0中(可能也适用于更早的版本),有一种非常简单的方法可以完成此操作,而无需使用ADD_CUSTOM_COMMAND和其他复杂的步骤。

首先,您应该创建一个包含所有列出的.qm文件的QRC文件(感谢the_fly_123):

<RCC>
  <qresource prefix="/translators">
    <file>myapp_en.qm</file>
  </qresource>
</RCC>

然后,您可以使用configure_file将此QRC文件复制到输出目录,并使用标准的Qt例程构建和添加它:

# Change lang.qrc to the name of QRC file, created on the previous step
set(lang_qrc "lang.qrc")
configure_file(${lang_qrc} ${lang_qrc} COPYONLY)
qt5_add_translation(myapp_QM ${myapp_TRANSLATIONS})
qt5_add_resources(myapp_QM_RC ${CMAKE_CURRENT_BINARY_DIR}/${lang_qrc})

然后在add_executable中包含${myapp_QM_RC}和其他源代码。
注意:对于Qt4,请将所有qt5_前缀替换为qt4_


1
应该使用${CMAKE_CURRENT_BINARY_DIR}(构建目录中的子目录),而不是${CMAKE_BINARY_DIR}(根构建目录),因为这是configure_file复制到的位置。 - Wang Weiyi
1
太棒了,这甚至不需要禁用CLEAN_NO_CUSTOM属性! - Amfasis

2
我的解决方案是从头开始生成带有编译翻译的ts.qrc XML文件,然后将其与应用程序一起编译。
以下是示例:
file(GLOB QRC_FILES *.qrc)
file(GLOB TS_FILES ts/*.ts)
...

# Option for updating translations
option(UPDATE_TRANSLATIONS "Update source translation ts/*.ts files (WARNING: make clean will delete the source *.ts files. Danger!)" OFF)
if(UPDATE_TRANSLATIONS)
qt4_create_translation(QM_FILES ${TS_FILES})
endif()
...
# Compiling translations *.ts -> *.qm
qt4_add_translation(QM_FILES ${TS_FILES})
...
# Create translations QRC file - ts.qrc
set(TRANSLATIONS_QRC "${CMAKE_CURRENT_BINARY_DIR}/ts.qrc")
file(WRITE ${TRANSLATIONS_QRC} "<RCC>\n\t<qresource prefix=\"/ts\">")
foreach(QM_FILE ${QM_FILES})
    get_filename_component(QM_FILE_NAME ${QM_FILE} NAME)
    file(APPEND ${TRANSLATIONS_QRC} "\n\t\t<file alias=\"${QM_FILE_NAME}\">${QM_FILE_NAME}</file>")
endforeach()
file(APPEND ${TRANSLATIONS_QRC} "\n\t</qresource>\n</RCC>")
list(APPEND QRC_FILES ${TRANSLATIONS_QRC})
...
# Compiling *.qrc files
qt4_add_resources(QRC_SRCS ${QRC_FILES})
...
# Add compiled resources to executable dependency list
add_executable(${APP_NAME} ... ${QRC_SRCS})

文件树:

/ - source code root
/rc.qrc - contains app icons etc.
/ts/appname_*.ts - application translations
...
/build - build root
/build/appname_*.qm - compiled translations
/build/ts.qrc - translations rescources
/build/Release/qrc_rc.cxx - compiled icon etc. resources
/build/Release/qrc_ts.cxx - compiled translation resources

ts目录中的文件最初是由lupdate工具生成的。


很好,但它不能与并行make(make -jSOMETHING)一起工作。 - drizzt

0

是的,我已经弄清楚了。但它不起作用:CMake 2.6可以发现QRC的源代码(在我的情况下是要生成的QM文件),但不知道如何构建此文件,因为它期望该文件位于源路径中,而不是构建路径(在此之前创建)。 - hurikhan77

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接