How to get QMake to copy large data files only if they are updated
我在Qmake / QtCreator构建期间需要从源文件夹复制一些大数据文件来构建文件夹。由于它们很大,因此我只希望对新文件/更改过的文件进行复制。而且我真的想避免在项目文件中专门列出它们。这是我尝试过的:
由于DemoData文件夹是目标,因此尝试复制数据文件失败。因此,如果添加或更改文件夹中的文件,则不会执行复制。仅当文件夹不存在时。
1 2 3 4 | 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中的引号中,因此它成为一个目标。
1 2 3 4 5 6 7 | 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不支持其他变量中包含的变量名称。似乎更像是一级替代。生成了一个生成文件,但是DemoDataX目标都没有命令行。所有试图显示"命令"字段内容的尝试都会产生语法错误。
1 2 3 4 5 6 7 8 9 | 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"步骤。主要的一点是,总是无条件地复制文件。由于我们的数据文件很大,所以这在时间上是不可接受的。
1 2 3 | DemoData.path = $${BLD_DATA_DIR}DemoData DemoData.files = $${SRC_DATA_DIR}DemoData/* INSTALLS += DemoData |
有没有办法做到这一点,还是我剩下某种外部脚本或手动生成/维护的makefile?
使用QMAKE_EXTRA_COMPILES功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # 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的信息
您是否需要脚本跨平台?我个人不会使用copy命令,但是在Windows上使用
1 2 | 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参数。
-
/MIR 镜像目录树 -
/XO 排除较旧的文件。
Rsync参数在这里描述。
-
-a 存档 -
-r 递归 -
-u 仅在源较新时更新
作为附带说明,如果您不想运行此