首页 文章

如何让QMake只有在更新时才能复制大数据文件

提问于
浏览
6

我有一些大型数据文件,需要在我们的Qmake / QtCreator构建期间从源文件夹复制到构建文件夹 . 由于它们很大,我只希望复制发生在新的/更改的文件中 . 我真的想避免将它们全部列在项目文件中 . 这是我尝试过的:

这种复制数据文件的尝试失败,因为DemoData文件夹是目标 . 因此,如果添加或更改文件夹中的文件,则不会执行复制 . 仅当文件夹不存在时 .

DemoData.commands = $$COPY_CMD $${SRC_DATA_DIR}DemoData $${BLD_DATA_DIR}DemoData
DemoData.target += $${BLD_DATA_DIR}DemoData
PRE_TARGETDEPS += $${BLD_DATA_DIR}DemoData
QMAKE_EXTRA_TARGETS += DemoData

此方法失败,因为DemoData.target项不应具有多个项的列表 . QMake将列表放在生成的makefile中的引号中,使其成为一个目标 .

DemoData.commands = $$COPY_CMD $${SRC_DATA_DIR}DemoData $${BLD_DATA_DIR}DemoData
DEMO_DATA_FILES = $$files($${SRC_DATA_DIR}DemoData/*)
for(FILE, DEMO_DATA_FILES){
    DemoData.target += $${BLD_DATA_DIR}DemoData\\$$basename(FILE)
    PRE_TARGETDEPS += $${BLD_DATA_DIR}DemoData\\$$basename(FILE)
}
QMAKE_EXTRA_TARGETS += DemoData

此尝试失败,因为(AFAICT)QMake不支持其他变量中包含的变量名称 . 它似乎更像是一个级别的替代 . 生成一个makefile,但DemoDataX目标都没有命令行 . 所有显示“命令”字段内容的尝试都会产生语法错误 .

DEMO_DATA_FILES = $$files($${SRC_DATA_DIR}DemoData/*)
DEMO_DATA_NAME = DemoData
for(FILE, DEMO_DATA_FILES){
    $${DEMO_DATA_NAME}.target = $${FILE}
    $${DEMO_DATA_NAME}.commands = $$COPY_CMD $${FILE} $${BLD_DATA_DIR}DemoData
    PRE_TARGETDEPS += $${FILE}
    QMAKE_EXTRA_TARGETS += $${DEMO_DATA_NAME}
    DEMO_DATA_NAME = $${DEMO_DATA_NAME}X
}

这种方法有效,但有两个缺点 . 次要的是必须执行单独的“make install”步骤 . 主要的一点是始终无条件地复制文件 . 由于我们的数据文件很大,这在时间上是不可接受的 .

DemoData.path = $${BLD_DATA_DIR}DemoData
DemoData.files = $${SRC_DATA_DIR}DemoData/*
INSTALLS += DemoData

有没有办法做到这一点,还是我留下了某种外部脚本或手动生成/维护的makefile?

2 回答

  • 5

    使用QMAKE_EXTRA_COMPILES功能 .

    # list your files in this variable.
    # Masks are available with $$files functions but
    # if your set of files changes (files added or removed)
    # your have to re-run qmake after that explicitly, not just make
    MYFILES = $$files($${PWD}/files/*.*)
    
    copy_files.name = copy large files
    copy_files.input = MYFILES
    # change datafiles to a directory you want to put the files to
    copy_files.output = $${OUT_PWD}/datafiles/${QMAKE_FILE_BASE}${QMAKE_FILE_EXT}
    copy_files.commands = ${COPY_FILE} ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT}
    copy_files.CONFIG += no_link target_predeps
    
    QMAKE_EXTRA_COMPILERS += copy_files
    

    将您的大文件添加到MYFILES变量 . 对于每个文件,将在Makefile中生成一个规则,该规则将文件复制到指定的目录(示例中的数据文件) . 原始文件将在规则中列为依赖项(这是默认的qmake行为),因此仅当原始文件比现有副本更新时才会进行复制 . 生成的规则在目标文件规则(copy_files.CONFIG = target_predeps)中列为依赖项,因此将自动在每次构建时进行复制 .

    唯一需要注意的是:如果您的文件集是动态的(添加或删除文件),您可以像我的示例中那样使用掩码,但是在更改集之后必须小心执行qmake . 请注意,Qt Creator通过启动make而不是qmake来构建项目 . 确保启动qmake的最简单方法是修改.pro文件 .

    对于那些可以阅读俄语的人,有关于QMAKE_EXTRA_COMPILERS here的更多信息

  • 2

    你需要脚本跨平台吗?我个人不会使用复制命令,但在Windows上使用 robocopy ,在Mac / Linux上使用rsync .

    win32: $${DEMO_DATA_NAME}.commands = robocopy $${SRC_DIR} $${DST_DIR} $${FILE} /MIR /XO
    !win32: $${DEMO_DATA_NAME}.commands = rsync -aru $${FILE} $${BLD_DATA_DIR}
    

    我不确定你想在这里复制什么,但是你明白了,你可以调整文件和/或目录 .

    Robocopy参数描述为here .

    • /MIR 镜像目录树

    • /XO 排除旧文件 .

    Rsync参数描述为here .

    • -a 档案

    • -r 递归

    • -u 仅在源较新时更新

    作为旁注,如果您不想运行此 make install 命令,则可以将此额外目标设置为对需要这些文件的项目的依赖项: theProjectNeedingThoseFiles.depends += DemoData .

相关问题