简体   繁体   English

如何强制具有依赖性的QBS产品之间进行同步?

[英]How to force synchronisation between qbs products with dependencies?

I have a Project with multiple products, some of them are depending about generated code (cpp and hpp files). 我有一个包含多个产品的项目,其中一些取决于生成的代码(cpp和hpp文件)。 This generated code is it self depending about the code_generator product that is a CppApplication. 生成的代码本身取决于CppApplication的code_generator产品。

I want that the code_generator to be rebuilt if his sources changed, and then always run. 我希望如果code_generator的源发生更改,则将其重建,然后始终运行。 It will modify the output files only if they change (it internally generate them in a temporary folder and check changes with checksum before moving them to the right place). 仅当输出文件更改时,它才会修改输出文件(它会在临时文件夹中内部生成它们,并在将它们移到正确的位置之前使用校验和检查更改)。 Then once files are generated the compilation of other products can start. 然后,一旦生成文件,便可以开始其他产品的编译。

My issue is that the StaticLibrary in which I put the generated files start to be build before the code_generator.exe is built. 我的问题是,在生成code_generator.exe之前,我开始将生成的文件放入其中的StaticLibrary。 And other products that are depending on the StaticLibrary can also start to be build before the .hpp files are generated. 在生成.hpp文件之前,也可以开始构建依赖于StaticLibrary的其他产品。

So my question is: is there some mechanisms that can be used to make a product waiting until a particular dependency is completely built? 所以我的问题是:是否有一些机制可以用来使产品等待完全建立特定的依赖关系?

I am open to any kind of solution, the generated code can be in any kind of Module, I just tried with a StaticLibrary as it seems more convenient. 我接受任何一种解决方案,生成的代码可以在任何一种Module中使用,我只是尝试使用StaticLibrary,因为它看起来更方便。

PS: The code_generator product generated a lot of files and take few inputs that I didn't precise in the qbs as it can always run and it can be considered as an input itself as it can change. PS:code_generator产品生成了许多文件,并且接受了一些我在qbs中没有提到的输入,因为它可以一直运行,并且可以更改,因此可以视为输入本身。 This is why I am not sure that using Rule is really interesting for me. 这就是为什么我不确定使用Rule对我来说真的很有趣的原因。

Here is an extract of my qbs file: 这是我的qbs文件的摘录:

    CppApplication
    {
        name: "code_generator"

        consoleApplication: true

        files: [
            "../sources/code_generator/code_generator.cpp",
            "../sources/code_generator/code_generator.hpp",
            ...
        ]

        Depends { name: "default-cpp-configuration" }
        Depends { name: "tinyxml2" }

        destinationDirectory: "../" // @Warning we move the binary to ease his usage by the "generated_code" module
    }

    StaticLibrary    // @Warning as static library to build those sources only once
    {
        name: "generated_code"

        Depends { name: "default-cpp-configuration" }
        Depends { name: "code_generator" }

        Rule {
            multiplex: true
            alwaysRun: true
//            inputs: [project.buildDirectory + "/../code_generator.exe"]

            Artifact { filePath: "generated/common/directx/driver_call_table.cpp"; fileTags: "cpp" }
            Artifact { filePath: "generated/common/directx/driver_call_table.hpp"; fileTags: "hpp" }
            Artifact { filePath: "generated/common/directx/d3d11.def"; fileTags: "def" }
            Artifact { filePath: "generated/common/directx/uuid_helpers.cpp"; fileTags: "cpp" }
            Artifact { filePath: "generated/common/directx/uuid_helpers.hpp"; fileTags: "hpp" }


            prepare: {
                var code_generator_path = project.buildDirectory + "/../code_generator.exe";

                var cmd = new Command(code_generator_path, ["DirectX", "Outdir=${GENERATED_SOURCES_PATH}", "Indir=${CMAKE_SOURCE_DIR}/lib/specs", "CompilerPath=${CMAKE_CXX_COMPILER}", "--preprocess"]);
                cmd.description = "generating sources";
                return cmd;
            }
        }
    }

    CppApplication
    {
        name: "client"

        consoleApplication: true

        files: [
            "../sources/client/main.cpp",
        ]

        Depends { name: "default-cpp-configuration" }
        Depends { name: "generated_code" }
        Depends { name: "openssl" }
    }

Product dependencies just make the product's artifacts available in the depending product's rules. 产品依赖关系仅使产品的工件在相关产品的规则中可用。 They do not cause synchronization by themselves. 它们本身不会引起同步。 Synchronization happens on the artifact level; 同步发生在工件级别; otherwise, parallelization would be hindered. 否则,并行化将受到阻碍。 Your problem is that your rule does not state that it depends on the code generator executable. 您的问题是您的规则未声明它依赖于代码生成器可执行文件。 Here's what it should look like (untested): 这是它的样子(未经测试):

Rule {
    multiplex: true
    inputsFromDependencies: "application" // These are tags, not paths!
    Artifact { 
        filePath: "generated/common/directx/driver_call_table.cpp"
        fileTags: "cpp" 
    }
    Artifact { 
      filePath: "generated/common/directx/driver_call_table.hpp"
      fileTags: "hpp" 
    }
    Artifact { 
      filePath: "generated/common/directx/d3d11.def"
      fileTags: "def" 
    }
    Artifact { 
        filePath: "generated/common/directx/uuid_helpers.cpp"
        fileTags: "cpp" 
    }
    Artifact { 
        filePath: "generated/common/directx/uuid_helpers.hpp"
        fileTags: "hpp" 
    }
    prepare: {
        var code_generator_path = inputs.application[0].filePath;
        var args = [
            "DirectX", "Outdir=${GENERATED_SOURCES_PATH}", 
            "Indir=${CMAKE_SOURCE_DIR}/lib/specs", 
            CompilerPath=${CMAKE_CXX_COMPILER}", "--preprocess"
        ];
        var cmd = new Command(code_generator_path, args);
        cmd.description = "generating sources";
        return cmd;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM