首页 文章

QMake - 如何将文件复制到输出

提问于
浏览
39

如何使用qmake将文件从项目复制到输出目录?

我正在编译Linux,但将来我会在Mac和Windows上编译它 .

8 回答

  • 1

    在qmake用于config features的路径之一中创建文件 copy_files.prf . 该文件应如下所示:

    QMAKE_EXTRA_COMPILERS += copy_files
    copy_files.name = COPY
    copy_files.input = COPY_FILES
    copy_files.CONFIG = no_link
    
    copy_files.output_function = fileCopyDestination
    defineReplace(fileCopyDestination) {
        return($$shadowed($$1))
    }
    
    win32:isEmpty(MINGW_IN_SHELL) {
        # Windows shell
        copy_files.commands = copy /y ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT}
        TOUCH = copy /y nul
    }
    else {
        # Unix shell
        copy_files.commands = mkdir -p `dirname ${QMAKE_FILE_OUT}` && cp ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT}
        TOUCH = touch
    }
    
    QMAKE_EXTRA_TARGETS += copy_files_cookie
    copy_files_cookie.target = copy_files.cookie
    copy_files_cookie.depends = compiler_copy_files_make_all
    
    win32:!mingw {
        # NMake/MSBuild
        copy_files_cookie.commands = $$TOUCH $** && $$TOUCH $@
    }
    else {
        # GNU Make
        copy_files_cookie.commands = $$TOUCH $<  && $$TOUCH $@
    }
    
    PRE_TARGETDEPS += $${copy_files_cookie.target}
    

    How it works

    第一部分定义了extra compiler,它将从 COPY_FILES 变量中读取输入文件名 . 下一部分定义了它将用于合成与每个输入相对应的输出文件名的函数 . 然后我们定义用于调用此"compiler"的命令,具体取决于我们所处的shell类型 .

    然后我们定义一个extra makefile target copy_files.cookie ,它取决于目标 compiler_copy_files_make_all . 后者是qmake为我们在第一步中定义的额外编译器生成的目标的名称 . 这意味着当构建 copy_files.cookie 目标时,它将调用额外的编译器来复制文件 .

    我们指定要由此目标运行的命令,该命令将 touch 文件 copy_files.cookiecompiler_copy_files_make_all . 通过触摸这些文件,我们确保 make 不会再次尝试复制文件,除非它们的时间戳比触摸的文件更新 . 最后,我们将 copy_files.cookie 添加到 make all 目标的依赖项列表中 .

    How to use it

    .pro 文件中,将 copy_files 添加到 CONFIG 变量:

    CONFIG += copy_files
    

    然后将文件添加到 COPY_FILES 变量:

    COPY_FILES += docs/*.txt
    
  • 3

    如果使用make install,则可以使用INSTALLS variable of qmake . 这是一个例子:

    images.path    = $${DESTDIR}/images
    images.files   += images/splashscreen.png
    images.files   += images/logo.png
    INSTALLS       += images
    

    然后执行 make install .

  • 3

    作为Jake's answer和@Phlucious评论的补充,可以使用qmake defineReplace 函数,该函数适用于此用例 . 在使用提供的示例后,我遇到了一个问题,其中qmake跳过了我添加的最后一个帖子链接操作 . 这可能是变量导出的问题,尽管内容看起来一直很好 . 长话短说,这里是修改后的代码

    defineReplace(copyToDir) {
        files = $$1
        DIR = $$2
        LINK =
    
        for(FILE, files) {
            LINK += $$QMAKE_COPY $$shell_path($$FILE) $$shell_path($$DIR) $$escape_expand(\\n\\t)
        }
        return($$LINK)
    }
    

    这种通用复制功能可以被像这样的一些便利功能使用

    defineReplace(copyToBuilddir) {
        return($$copyToDir($$1, $$OUT_PWD))
    }
    

    第二个只接受一个参数(一个或多个文件)并提供固定路径 . 与参考答案几乎相同 .

    但现在请注意调用差异

    QMAKE_POST_LINK += $$copyToBuilddir(deploy.bat)
    

    如您所见,您可以将返回的命令附加到QMAKE_PRE_LINK以获得更大的灵活性 .

  • 0

    您可以使用qmake函数来重用:

    # Copies the given files to the destination directory
    defineTest(copyToDestdir) {
        files = $$1
    
        for(FILE, files) {
            DDIR = $$DESTDIR
    
            # Replace slashes in paths with backslashes for Windows
            win32:FILE ~= s,/,\\,g
            win32:DDIR ~= s,/,\\,g
    
            QMAKE_POST_LINK += $$QMAKE_COPY $$quote($$FILE) $$quote($$DDIR) $$escape_expand(\\n\\t)
        }
    
        export(QMAKE_POST_LINK)
    }
    

    然后使用如下:

    copyToDestdir($$OTHER_FILES) # a variable containing multiple paths
    copyToDestdir(run.sh) # a single filename
    copyToDestdir(run.sh README) # multiple files
    
  • 21

    首先定义下面的某个地方(来自 XD 框架):

    # --------------------------------------
    # This file defines few useful functions
    # --------------------------------------
    
    #copyDir(source, destination)
    # using "shell_path()" to correct path depending on platform
    # escaping quotes and backslashes for file paths
    defineTest(copyDir) {
        #append copy command
        !isEmpty(xd_copydir.commands): xd_copydir.commands += && \\$$escape_expand(\n\t)
        xd_copydir.commands += ( $(COPY_DIR) \"$$shell_path($$1)\" \"$$shell_path($$2)\" || echo \"copy failed\" )
        #the qmake generated MakeFile contains "first" and we depend that on "xd_copydir"
        first.depends *= xd_copydir
        QMAKE_EXTRA_TARGETS *= first xd_copydir
    
        export(first.depends)
        export(xd_copydir.commands)
        export(QMAKE_EXTRA_TARGETS)
    }
    
    #copy(source, destination) (i.e. the name "copyFile" was reserved)
    defineTest(copy) {
        #append copy command
        !isEmpty(xd_copyfile.commands): xd_copyfile.commands += && \\$$escape_expand(\n\t)
        xd_copyfile.commands += ( $(COPY_FILE) \"$$shell_path($$1)\" \"$$shell_path($$2)\" || echo \"copy failed\" )
        #the qmake generated MakeFile contains "first" and we depend that on "xd_copyfile"
        first.depends *= xd_copyfile
        QMAKE_EXTRA_TARGETS *= first xd_copyfile
    
        export(first.depends)
        export(xd_copyfile.commands)
        export(QMAKE_EXTRA_TARGETS)
    }
    

    并在您的项目中使用它,如:

    include($$PWD/functions.prf) #optional
    
    copy($$PWD/myfile1.txt, $$DESTDIR/myfile1.txt)
    copy($$PWD/README.txt, $$DESTDIR/README.txt)
    copy($$PWD/LICENSE, $$DESTDIR/LICENSE)
    copyDir($$PWD/redist, $$DESTDIR/redist) #copy "redist" folder to "$$DESTDIR"
    

    并注意在链接完成之前应复制所有文件

  • 47

    我发现我必须修改sje397给出的答案 . for Qt5 Beta1QtCreator 2.5.2 . 我使用此脚本将qml文件复制到目标目录,作为构建完成后的添加步骤 .

    我的.pro文件包含以下代码

    OTHER_FILES += \
        Application.qml
    
    # Copy qml files post build
    win32 {
        DESTDIR_WIN = $${DESTDIR}
        DESTDIR_WIN ~= s,/,\\,g
        PWD_WIN = $${PWD}
        PWD_WIN ~= s,/,\\,g
        for(FILE, OTHER_FILES){
            QMAKE_POST_LINK += $$quote(cmd /c copy /y $${PWD_WIN}\\$${FILE} $${DESTDIR_WIN}$$escape_expand(\\n\\t))
        }
    }
    unix {
        for(FILE, OTHER_FILES){
            QMAKE_POST_LINK += $$quote(cp $${PWD}/$${FILE} $${DESTDIR}$$escape_expand(\\n\\t))
    }
    

    }

    请注意,我使用$$ PWD_WIN将源文件的完整路径提供给copy命令 .

  • 13

    以下是我们其中一个项目的示例 . 它显示了如何将文件复制到Windows和Linux的 DESTDIR .

    linux-g++{
        #...
        EXTRA_BINFILES += \
            $${THIRDPARTY_PATH}/gstreamer-0.10/linux/plugins/libgstrtp.so \
            $${THIRDPARTY_PATH}/gstreamer-0.10/linux/plugins/libgstvideo4linux2.so
        for(FILE,EXTRA_BINFILES){
            QMAKE_POST_LINK += $$quote(cp $${FILE} $${DESTDIR}$$escape_expand(\n\t))
        }
    }
    
    win32 {
        #...
        EXTRA_BINFILES += \
            $${THIRDPARTY_PATH}/glib-2.0/win32/bin/libglib-2.0.dll \
            $${THIRDPARTY_PATH}/glib-2.0/win32/bin/libgmodule-2.0.dll
        EXTRA_BINFILES_WIN = $${EXTRA_BINFILES}
        EXTRA_BINFILES_WIN ~= s,/,\\,g
            DESTDIR_WIN = $${DESTDIR}
        DESTDIR_WIN ~= s,/,\\,g
        for(FILE,EXTRA_BINFILES_WIN){
                    QMAKE_POST_LINK +=$$quote(cmd /c copy /y $${FILE} $${DESTDIR_WIN}$$escape_expand(\n\t))
        }
    }
    
  • 0

    首先,定义以下两个函数以支持Windows / Unix .

    defineReplace(nativePath) {
        OUT_NATIVE_PATH = $$1
        # Replace slashes in paths with backslashes for Windows
        win32:OUT_NATIVE_PATH ~= s,/,\\,g
        return($$OUT_NATIVE_PATH)
    }
    
    # Copies the given files to the destination directory
    defineReplace(copyToDestDirCommands) {
        variable_files = $$1
        files = $$eval($$variable_files)
        DDIR = $$nativePath($$2)
        win32:DDIR ~= s,/,\\,g
        POST_LINK = echo "Copying files to $$DDIR" $$escape_expand(\\n\\t)
    
        win32 {
            POST_LINK += $$QMAKE_MKDIR $$quote($$DDIR) 2>&1 & set errorlevel=0 $$escape_expand(\\n\\t)
        }
        !win32 {
            POST_LINK += $$QMAKE_MKDIR -p $$quote($$DDIR) $$escape_expand(\\n\\t)
        }
    
        for(ORIGINAL_FILE, files) {
            FILE = $$nativePath($$ORIGINAL_FILE)
            POST_LINK += $$QMAKE_COPY $$quote($$FILE) $$quote($$DDIR) $$escape_expand(\\n\\t)
        }
    
        return ($$POST_LINK)
    }
    

    然后,您可以使用以下代码调用之前定义的函数将文件复制到特定文件夹,并在必要时创建目录 . 这是在Win32下测试的,欢迎Linux测试 .

    BATOS_FILES = \
        $$BATOS_BIN_ROOT/batos-core.dll \
        $$BATOS_BIN_ROOT/batos-pfw.dll \
        $$BATOS_BIN_ROOT/dre.dll \
        $$BATOS_BIN_ROOT/log4qt.dll
    
    QMAKE_POST_LINK += $$copyToDestDirCommands(BATOS_FILES, $$DESTDIR)
    
    BATOS_PLUGINS_FILES = \
        $$BATOS_BIN_ROOT/plugins/com.xaf.plugin-manager.dll \
        $$BATOS_BIN_ROOT/plugins/org.commontk.eventadmin.dll
    
    QMAKE_POST_LINK += $$copyToDestDirCommands(BATOS_PLUGINS_FILES, $$DESTDIR/plugins)
    

相关问题