8

在我们的 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?

4

2 回答 2

8

使用 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 的更多信息

于 2013-09-06T06:45:17.707 回答
4

你需要脚本是跨平台的吗?我个人不会使用 copy 命令,而是robocopy在 Windows 和 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 参数在此处描述。

  • /MIR镜像目录树
  • /XO排除旧文件。

此处描述了 Rsync 参数。

  • -a档案
  • -r递归的
  • -u仅在源较新时更新

附带说明一下,如果您不想运行此make install命令,可以将此额外目标设置为需要这些文件的项目的依赖项:theProjectNeedingThoseFiles.depends += DemoData.

于 2013-08-30T10:12:18.177 回答